From 957e56901e06c890452ba739c0d2f1ada478f176 Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Thu, 20 May 2021 15:39:02 -0300 Subject: [PATCH 1/5] Adds confirmation dialog when closing window Signed-off-by: Franco Cipollone --- include/ignition/gui/MainWindow.hh | 24 ++++++++++++++++++++- include/ignition/gui/qml/Main.qml | 29 +++++++++++++++++++++++++ src/MainWindow.cc | 34 ++++++++++++++++++++++++++++++ src/MainWindow_TEST.cc | 2 ++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/include/ignition/gui/MainWindow.hh b/include/ignition/gui/MainWindow.hh index 6953ba246..497f8c85c 100644 --- a/include/ignition/gui/MainWindow.hh +++ b/include/ignition/gui/MainWindow.hh @@ -44,7 +44,7 @@ namespace ignition /// \brief The main window class creates a QQuickWindow and acts as an /// interface which provides properties and functions which can be called - /// from MainWindow.qml + /// from Main.qml class IGNITION_GUI_VISIBLE MainWindow : public QObject { Q_OBJECT @@ -177,6 +177,14 @@ namespace ignition NOTIFY ShowPluginMenuChanged ) + /// \brief Flag to enable confirmation dialog on exit + Q_PROPERTY( + bool showDialogOnExit + READ ShowDialogOnExit + WRITE SetShowDialogOnExit + NOTIFY ShowDialogOnExitChanged + ) + /// \brief Constructor public: MainWindow(); @@ -344,6 +352,14 @@ namespace ignition /// \param[in] _showPluginMenu True to show. public: Q_INVOKABLE void SetShowPluginMenu(const bool _showPluginMenu); + /// \brief Get the flag to show the plugin menu. + /// \return True to show. + public: Q_INVOKABLE bool ShowDialogOnExit() const; + + /// \brief Set the flag to show the confirmation dialog when exiting. + /// \param[in] _showDialogOnExit True to show. + public: Q_INVOKABLE void SetShowDialogOnExit(bool _showDialogOnExit); + /// \brief Callback when load configuration is selected public slots: void OnLoadConfig(const QString &_path); @@ -398,6 +414,9 @@ namespace ignition /// \brief Notifies when the show menu flag has changed. signals: void ShowPluginMenuChanged(); + /// \brief Notifies when the showDialogOnExit flag has changed. + signals: void ShowDialogOnExitChanged(); + /// \brief Notifies when the window config has changed. signals: void configChanged(); @@ -484,6 +503,9 @@ namespace ignition /// \brief Show the plugins menu bool showPluginMenu{true}; + /// \brief Show the confirmation dialog on exit + bool showDialogOnExit{false}; + /// \brief True if plugins found in plugin paths should be listed under /// the Plugins menu. True by default. bool pluginsFromPaths{true}; diff --git a/include/ignition/gui/qml/Main.qml b/include/ignition/gui/qml/Main.qml index c914f0c0d..d6b4c4cfd 100644 --- a/include/ignition/gui/qml/Main.qml +++ b/include/ignition/gui/qml/Main.qml @@ -71,6 +71,14 @@ ApplicationWindow titleLabel.text = window.title } + // Handler for window closing + onClosing: { + close.accepted = !MainWindow.showDialogOnExit + if(MainWindow.showDialogOnExit){ + confirmationDialogOnExit.open() + } + } + // C++ signals to QML slots Connections { target: MainWindow @@ -315,4 +323,25 @@ ApplicationWindow } } } + + /** + * Confirmation dialog on close button + */ + Dialog { + id: confirmationDialogOnExit + title: "Do you really want to exit?" + + modal: true + focus: true + parent: ApplicationWindow.overlay + width: 300 + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + closePolicy: Popup.CloseOnEscape + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + Qt.quit() + } + } } diff --git a/src/MainWindow.cc b/src/MainWindow.cc index a0a40d0ca..d878efbff 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc @@ -259,6 +259,12 @@ bool MainWindow::ApplyConfig(const WindowConfig &_config) this->SetShowDefaultDrawerOpts(_config.showDefaultDrawerOpts); this->SetShowPluginMenu(_config.showPluginMenu); + // Confirmation dialog on exit + if (!_config.IsIgnoring("dialog_on_exit")) + { + this->SetShowDialogOnExit(_config.showDialogOnExit); + } + // Keep a copy this->dataPtr->windowConfig = _config; @@ -313,6 +319,7 @@ WindowConfig MainWindow::CurrentWindowConfig() const config.pluginsFromPaths = this->dataPtr->windowConfig.pluginsFromPaths; config.showPlugins = this->dataPtr->windowConfig.showPlugins; config.ignoredProps = this->dataPtr->windowConfig.ignoredProps; + config.showDialogOnExit = this->dataPtr->windowConfig.showDialogOnExit; // Plugins auto plugins = this->findChildren(); @@ -470,6 +477,12 @@ bool WindowConfig::MergeFromXML(const std::string &_windowXml) } } + // Show dialog on exit + if (auto dialogOnExitElem = winElem->FirstChildElement("dialog_on_exit")) + { + dialogOnExitElem->QueryBoolText(&this->showDialogOnExit); + } + // Ignore for (auto ignoreElem = winElem->FirstChildElement("ignore"); ignoreElem != nullptr; @@ -598,6 +611,14 @@ std::string WindowConfig::XMLString() const windowElem->InsertEndChild(menusElem); } + // Dialog on exit + if (!this->IsIgnoring("dialog_on_exit")) + { + auto elem = doc.NewElement("dialog_on_exit"); + elem->SetText(this->showDialogOnExit ? "true" : "false"); + windowElem->InsertEndChild(elem); + } + // Ignored properties { for (const auto &ignore : this->ignoredProps) @@ -843,3 +864,16 @@ void MainWindow::SetShowPluginMenu(const bool _showPluginMenu) this->dataPtr->windowConfig.showPluginMenu = _showPluginMenu; this->ShowPluginMenuChanged(); } + +///////////////////////////////////////////////// +bool MainWindow::ShowDialogOnExit() const +{ + return this->dataPtr->windowConfig.showDialogOnExit; +} + +///////////////////////////////////////////////// +void MainWindow::SetShowDialogOnExit(bool _showDialogOnExit) +{ + this->dataPtr->windowConfig.showDialogOnExit = _showDialogOnExit; + this->ShowDialogOnExitChanged(); +} diff --git a/src/MainWindow_TEST.cc b/src/MainWindow_TEST.cc index 3100586d8..62766b9d2 100644 --- a/src/MainWindow_TEST.cc +++ b/src/MainWindow_TEST.cc @@ -211,6 +211,7 @@ TEST(WindowConfigTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(defaultValues)) EXPECT_TRUE(c.materialAccent.empty()); EXPECT_TRUE(c.showDrawer); EXPECT_TRUE(c.showDefaultDrawerOpts); + EXPECT_FALSE(c.showDialogOnExit); EXPECT_TRUE(c.showPluginMenu); EXPECT_TRUE(c.pluginsFromPaths); EXPECT_TRUE(c.showPlugins.empty()); @@ -225,6 +226,7 @@ TEST(WindowConfigTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(defaultValues)) EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); } From 50ac12318af0cfabf47c30f7f8e72c8ede89890a Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Mon, 31 May 2021 18:54:36 -0300 Subject: [PATCH 2/5] Avoids breaking ABI. Signed-off-by: Franco Cipollone --- include/ignition/gui/MainWindow.hh | 3 --- src/Application.cc | 8 ++++++++ src/MainWindow.cc | 28 +++++----------------------- src/MainWindow_TEST.cc | 2 -- 4 files changed, 13 insertions(+), 28 deletions(-) diff --git a/include/ignition/gui/MainWindow.hh b/include/ignition/gui/MainWindow.hh index 497f8c85c..ea956e21e 100644 --- a/include/ignition/gui/MainWindow.hh +++ b/include/ignition/gui/MainWindow.hh @@ -503,9 +503,6 @@ namespace ignition /// \brief Show the plugins menu bool showPluginMenu{true}; - /// \brief Show the confirmation dialog on exit - bool showDialogOnExit{false}; - /// \brief True if plugins found in plugin paths should be listed under /// the Plugins menu. True by default. bool pluginsFromPaths{true}; diff --git a/src/Application.cc b/src/Application.cc index 3e11543ef..852356ee1 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -275,6 +275,14 @@ bool Application::LoadConfig(const std::string &_config) this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr())); } + // Closing behavior. + if (auto dialogOnExitElem = doc.FirstChildElement("dialog_on_exit")) + { + bool showDialogOnExit{false}; + dialogOnExitElem->QueryBoolText(&showDialogOnExit); + this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit); + } + this->ApplyConfig(); return true; diff --git a/src/MainWindow.cc b/src/MainWindow.cc index d878efbff..d7d62c597 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc @@ -47,6 +47,9 @@ namespace ignition /// \brief Minimum number of paint events to consider the window to be /// fully initialized. public: const unsigned int paintCountMin{20}; + + /// \brief Show the confirmation dialog on exit + public: bool showDialogOnExit{false}; }; } } @@ -259,12 +262,6 @@ bool MainWindow::ApplyConfig(const WindowConfig &_config) this->SetShowDefaultDrawerOpts(_config.showDefaultDrawerOpts); this->SetShowPluginMenu(_config.showPluginMenu); - // Confirmation dialog on exit - if (!_config.IsIgnoring("dialog_on_exit")) - { - this->SetShowDialogOnExit(_config.showDialogOnExit); - } - // Keep a copy this->dataPtr->windowConfig = _config; @@ -319,7 +316,6 @@ WindowConfig MainWindow::CurrentWindowConfig() const config.pluginsFromPaths = this->dataPtr->windowConfig.pluginsFromPaths; config.showPlugins = this->dataPtr->windowConfig.showPlugins; config.ignoredProps = this->dataPtr->windowConfig.ignoredProps; - config.showDialogOnExit = this->dataPtr->windowConfig.showDialogOnExit; // Plugins auto plugins = this->findChildren(); @@ -477,12 +473,6 @@ bool WindowConfig::MergeFromXML(const std::string &_windowXml) } } - // Show dialog on exit - if (auto dialogOnExitElem = winElem->FirstChildElement("dialog_on_exit")) - { - dialogOnExitElem->QueryBoolText(&this->showDialogOnExit); - } - // Ignore for (auto ignoreElem = winElem->FirstChildElement("ignore"); ignoreElem != nullptr; @@ -611,14 +601,6 @@ std::string WindowConfig::XMLString() const windowElem->InsertEndChild(menusElem); } - // Dialog on exit - if (!this->IsIgnoring("dialog_on_exit")) - { - auto elem = doc.NewElement("dialog_on_exit"); - elem->SetText(this->showDialogOnExit ? "true" : "false"); - windowElem->InsertEndChild(elem); - } - // Ignored properties { for (const auto &ignore : this->ignoredProps) @@ -868,12 +850,12 @@ void MainWindow::SetShowPluginMenu(const bool _showPluginMenu) ///////////////////////////////////////////////// bool MainWindow::ShowDialogOnExit() const { - return this->dataPtr->windowConfig.showDialogOnExit; + return this->dataPtr->showDialogOnExit; } ///////////////////////////////////////////////// void MainWindow::SetShowDialogOnExit(bool _showDialogOnExit) { - this->dataPtr->windowConfig.showDialogOnExit = _showDialogOnExit; + this->dataPtr->showDialogOnExit = _showDialogOnExit; this->ShowDialogOnExitChanged(); } diff --git a/src/MainWindow_TEST.cc b/src/MainWindow_TEST.cc index 62766b9d2..3100586d8 100644 --- a/src/MainWindow_TEST.cc +++ b/src/MainWindow_TEST.cc @@ -211,7 +211,6 @@ TEST(WindowConfigTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(defaultValues)) EXPECT_TRUE(c.materialAccent.empty()); EXPECT_TRUE(c.showDrawer); EXPECT_TRUE(c.showDefaultDrawerOpts); - EXPECT_FALSE(c.showDialogOnExit); EXPECT_TRUE(c.showPluginMenu); EXPECT_TRUE(c.pluginsFromPaths); EXPECT_TRUE(c.showPlugins.empty()); @@ -226,7 +225,6 @@ TEST(WindowConfigTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(defaultValues)) EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); EXPECT_NE(xml.find(""), std::string::npos); } From 0124e2790cb5ca6cfb344fd704c61546327c2742 Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Wed, 2 Jun 2021 10:41:57 -0300 Subject: [PATCH 3/5] Moves node back to the window node. Signed-off-by: Franco Cipollone --- include/ignition/gui/qml/Main.qml | 6 +++--- src/Application.cc | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/ignition/gui/qml/Main.qml b/include/ignition/gui/qml/Main.qml index d6b4c4cfd..ec75de916 100644 --- a/include/ignition/gui/qml/Main.qml +++ b/include/ignition/gui/qml/Main.qml @@ -45,7 +45,7 @@ ApplicationWindow property string pluginToolBarTextColorLight: MainWindow.pluginToolBarTextColorLight property string pluginToolBarColorDark: MainWindow.pluginToolBarColorDark property string pluginToolBarTextColorDark: MainWindow.pluginToolBarTextColorDark - + property bool showDialogOnExit: MainWindow.showDialogOnExit /** * Tool bar background color */ @@ -73,8 +73,8 @@ ApplicationWindow // Handler for window closing onClosing: { - close.accepted = !MainWindow.showDialogOnExit - if(MainWindow.showDialogOnExit){ + close.accepted = !showDialogOnExit + if(showDialogOnExit){ confirmationDialogOnExit.open() } } diff --git a/src/Application.cc b/src/Application.cc index 852356ee1..ea7f2aab2 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -273,14 +273,14 @@ bool Application::LoadConfig(const std::string &_config) return false; } this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr())); - } - // Closing behavior. - if (auto dialogOnExitElem = doc.FirstChildElement("dialog_on_exit")) - { - bool showDialogOnExit{false}; - dialogOnExitElem->QueryBoolText(&showDialogOnExit); - this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit); + // Closing behavior. + if (auto dialogOnExitElem = winElem->FirstChildElement("dialog_on_exit")) + { + bool showDialogOnExit{false}; + dialogOnExitElem->QueryBoolText(&showDialogOnExit); + this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit); + } } this->ApplyConfig(); From ceaaedc1bc44e20c08e1d91e22f67b08ea645fb7 Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Wed, 2 Jun 2021 14:19:09 -0300 Subject: [PATCH 4/5] Updates docs and extends test coverage. Signed-off-by: Franco Cipollone --- test/config/test.config | 4 ++++ tutorials/04_layout.md | 1 + 2 files changed, 5 insertions(+) diff --git a/test/config/test.config b/test/config/test.config index 706a1ad50..dd3b76e65 100644 --- a/test/config/test.config +++ b/test/config/test.config @@ -1,4 +1,8 @@ + + false + + diff --git a/tutorials/04_layout.md b/tutorials/04_layout.md index 6d04697e1..6ad02c358 100644 --- a/tutorials/04_layout.md +++ b/tutorials/04_layout.md @@ -28,6 +28,7 @@ by adding a `` element to the config file. The child elements are: the menu. If `from_paths` is true, all plugins will be shown anyway, so adding `` has no effect. For the plugin to be shown, it must be on the path. +* ``: If true, a confirmation dialog will show up when closing the window. ## Example layout From 6db723c7781aca2af798d4da4cb3bec60c99b8d5 Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Wed, 2 Jun 2021 14:21:55 -0300 Subject: [PATCH 5/5] Adds dialog_on_exit atribute to example .config Signed-off-by: Franco Cipollone --- examples/config/layout.config | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/config/layout.config b/examples/config/layout.config index 3f6ac5aab..6d3446a5f 100644 --- a/examples/config/layout.config +++ b/examples/config/layout.config @@ -6,6 +6,7 @@ 230 550 551 + true 1