diff --git a/src/netedit/GNEApplicationWindow.cpp b/src/netedit/GNEApplicationWindow.cpp index 09572156d9b4..d4aa32c0a957 100644 --- a/src/netedit/GNEApplicationWindow.cpp +++ b/src/netedit/GNEApplicationWindow.cpp @@ -648,7 +648,7 @@ GNEApplicationWindow::~GNEApplicationWindow() { long GNEApplicationWindow::onCmdQuit(FXObject*, FXSelector, void*) { - if (continueWithUnsavedChanges()) { + if (askSaveElements()) { storeWindowSizeAndPos(); getApp()->reg().writeStringEntry("SETTINGS", "basedir", gCurrentFolder.text()); if (isMaximized()) { @@ -1116,7 +1116,7 @@ long GNEApplicationWindow::onCmdClose(FXObject*, FXSelector, void*) { if (myViewNet == nullptr) { return 1; - } else if (continueWithUnsavedChanges()) { + } else if (askSaveElements()) { closeAllWindows(); // add a separator to the log myMessageWindow->addSeparator(); @@ -4299,151 +4299,50 @@ GNEApplicationWindow::onCmdSaveMeanDatasAs(FXObject* sender, FXSelector sel, voi bool -GNEApplicationWindow::continueWithUnsavedChanges() { - if (continueWithUnsavedNetworkChanges() && - continueWithUnsavedAdditionalChanges() && - continueWithUnsavedDemandElementChanges() && - continueWithUnsavedDataElementChanges() && - continueWithUnsavedMeanDataElementChanges()) { - // clear undo list - clearUndoList(); - return true; - } else { - return false; - } -} - - -bool -GNEApplicationWindow::continueWithUnsavedNetworkChanges() { - if (myNet && !myNet->getSavingStatus()->isNetworkSaved()) { - // write warning if netedit is running in testing mode - // open question box - const std::string header = TL("Confirm close Network"); - const std::string contentsA = TL("You have unsaved changes in the network."); - const std::string contentsB = TL("Do you wish to close and discard all changes?"); - const auto answer = GUISaveDialog::question(getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); - // if user close dialog box, check additionals and demand elements - if (answer == GUISaveDialog::CLICKED_DISCARD) { - // nothing to save, return true - return true; - } else if (answer == GUISaveDialog::CLICKED_SAVE) { - // return true if was sucessfully saved - return (onCmdSaveNetwork(nullptr, 0, nullptr) == 1); - } else { - // return false to stop closing/reloading +GNEApplicationWindow::askSaveElements() { + if (myNet) { + const auto saveNetwork = myNet->getSavingStatus()->askSaveNetwork(); + const auto saveAdditionalElements = myNet->getSavingStatus()->askSaveAdditionalElements(); + const auto saveDemandElements = myNet->getSavingStatus()->askSaveDemandElements(); + const auto saveDataElements = myNet->getSavingStatus()->askSaveDataElements(); + const auto saveMeanDataElements = myNet->getSavingStatus()->askSaveMeanDataElements(); + // first check if abort saving + if ((saveNetwork == GNENetHelper::SavingStatus::AskSaving::ABORT) || + (saveAdditionalElements == GNENetHelper::SavingStatus::AskSaving::ABORT) || + (saveDemandElements == GNENetHelper::SavingStatus::AskSaving::ABORT) || + (saveDataElements == GNENetHelper::SavingStatus::AskSaving::ABORT) || + (saveMeanDataElements == GNENetHelper::SavingStatus::AskSaving::ABORT)) { return false; } - } else { - // nothing to save, return true - return true; - } -} - - -bool -GNEApplicationWindow::continueWithUnsavedAdditionalChanges() { - // Check if there are non saved additionals - if (myNet && !myNet->getSavingStatus()->isAdditionalsSaved()) { - // open question box - const std::string header = TL("Save additional elements before close"); - const std::string contentsA = TL("You have unsaved additional elements."); - const std::string contentsB = TL("Do you wish to close and discard all changes?"); - const auto answer = GUISaveDialog::question(getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); - // if answer was affirmative, but there was an error during saving additionals, return false to stop closing/reloading - if (answer == GUISaveDialog::CLICKED_DISCARD) { - // nothing to save, return true - return true; - } else if (answer == GUISaveDialog::CLICKED_SAVE) { - // return true if was sucessfully saved - return (onCmdSaveAdditionals(nullptr, 0, nullptr) == 1); - } else { - // abort saving + // save every type of file + if ((saveNetwork == GNENetHelper::SavingStatus::AskSaving::SAVE) && + (onCmdSaveNetwork(nullptr, 0, nullptr) != 1)) { return false; } - } else { - // nothing to save, return true - return true; - } -} - - -bool -GNEApplicationWindow::continueWithUnsavedDemandElementChanges() { - // Check if there are non saved demand elements - if (myNet && !myNet->getSavingStatus()->isDemandElementsSaved()) { - // open question box - const std::string header = TL("Save demand elements before close"); - const std::string contentsA = TL("You have unsaved demand elements."); - const std::string contentsB = TL("Do you wish to close and discard all changes?"); - const auto answer = GUISaveDialog::question(getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); - // if answer was affirmative, but there was an error during saving demand elements, return false to stop closing/reloading - if (answer == GUISaveDialog::CLICKED_DISCARD) { - // nothing to save, return true - return true; - } else if (answer == GUISaveDialog::CLICKED_SAVE) { - // return true if was sucessfully saved - return (onCmdSaveDemandElements(nullptr, MID_GNE_AUTOMATICFILENAME, nullptr) == 1); - } else { - // abort saving + if ((saveAdditionalElements == GNENetHelper::SavingStatus::AskSaving::SAVE) && + (onCmdSaveAdditionals(nullptr, 0, nullptr) != 1)) { return false; } - } else { - // nothing to save, return true - return true; - } -} - - -bool -GNEApplicationWindow::continueWithUnsavedDataElementChanges() { - // Check if there are non saved data elements - if (myNet && !myNet->getSavingStatus()->isDataElementsSaved()) { - // open question box - const std::string header = TL("Save data elements before close"); - const std::string contentsA = TL("You have unsaved data elements."); - const std::string contentsB = TL("Do you wish to close and discard all changes?"); - const auto answer = GUISaveDialog::question(getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); - // if answer was affirmative, but there was an error during saving data elements, return false to stop closing/reloading - if (answer == GUISaveDialog::CLICKED_DISCARD) { - // nothing to save, return true - return true; - } else if (answer == GUISaveDialog::CLICKED_SAVE) { - // return true if was sucessfully saved - return (onCmdSaveDataElements(nullptr, MID_GNE_AUTOMATICFILENAME, nullptr) == 1); - } else { - // abort saving + if ((saveDemandElements == GNENetHelper::SavingStatus::AskSaving::SAVE) && + (onCmdSaveDemandElements(nullptr, 0, nullptr) != 1)) { return false; } - } else { - // nothing to save, return true - return true; - } -} - - -bool -GNEApplicationWindow::continueWithUnsavedMeanDataElementChanges() { - // Check if there are non saved data elements - if (myNet && !myNet->getSavingStatus()->isMeanDatasSaved()) { - // open question box - const std::string header = TL("Save meanData elements before close"); - const std::string contentsA = TL("You have unsaved meanData elements."); - const std::string contentsB = TL("Do you wish to close and discard all changes?"); - const auto answer = GUISaveDialog::question(getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); - // if answer was affirmative, but there was an error during saving meanData elements, return false to stop closing/reloading - if (answer == GUISaveDialog::CLICKED_DISCARD) { - // nothing to save, return true - return true; - } else if (answer == GUISaveDialog::CLICKED_SAVE) { - // return true if was sucessfully saved - return (onCmdSaveMeanDatas(nullptr, MID_GNE_AUTOMATICFILENAME, nullptr) == 1); - } else { - // abort saving + if ((saveDataElements == GNENetHelper::SavingStatus::AskSaving::SAVE) && + (onCmdSaveDataElements(nullptr, 0, nullptr) != 1)) { return false; } + if ((saveMeanDataElements == GNENetHelper::SavingStatus::AskSaving::SAVE) && + (onCmdSaveMeanDatas(nullptr, 0, nullptr) != 1)) { + return false; + } + // restore focus in viewNet + myViewNet->setFocus(); + // clear undo list + clearUndoList(); + // all saved, then continue + return true; } else { - // nothing to save, return true + // nothing to do, then continue return true; } } diff --git a/src/netedit/GNEApplicationWindow.h b/src/netedit/GNEApplicationWindow.h index 6e7623f44979..0a8efc11a883 100644 --- a/src/netedit/GNEApplicationWindow.h +++ b/src/netedit/GNEApplicationWindow.h @@ -789,22 +789,7 @@ class GNEApplicationWindow : public GUIMainWindow, public MFXInterThreadEventCli void closeAllWindows(); /// @brief warns about unsaved changes and gives the user the option to abort - bool continueWithUnsavedChanges(); - - /// @brief warns about unsaved changes in network and gives the user the option to abort - bool continueWithUnsavedNetworkChanges(); - - /// @brief warns about unsaved changes in additionals and gives the user the option to abort - bool continueWithUnsavedAdditionalChanges(); - - /// @brief warns about unsaved changes in demand elements and gives the user the option to abort - bool continueWithUnsavedDemandElementChanges(); - - /// @brief warns about unsaved changes in data elements and gives the user the option to abort - bool continueWithUnsavedDataElementChanges(); - - /// @brief warns about unsaved changes in meanData elements and gives the user the option to abort - bool continueWithUnsavedMeanDataElementChanges(); + bool askSaveElements(); /// @brief set input files in sumo options void setInputInSumoOptions(const bool ignoreAdditionals, const bool ignoreRoutes); diff --git a/src/netedit/GNENet.cpp b/src/netedit/GNENet.cpp index 7eb4ee89b0c6..2d9739a09992 100644 --- a/src/netedit/GNENet.cpp +++ b/src/netedit/GNENet.cpp @@ -91,7 +91,7 @@ GNENet::GNENet(NBNetBuilder* netBuilder) : GUIGlObject(GLO_NETWORK, "", nullptr), myNetBuilder(netBuilder), myAttributeCarriers(new GNENetHelper::AttributeCarriers(this)), - mySavingStatus(new GNENetHelper::SavingStatus()), + mySavingStatus(new GNENetHelper::SavingStatus(this)), myNetworkPathManager(new GNEPathManager(this)), myDemandPathManager(new GNEPathManager(this)), myDataPathManager(new GNEPathManager(this)) { diff --git a/src/netedit/GNENetHelper.cpp b/src/netedit/GNENetHelper.cpp index a4c58bcf2ea1..facba0a0e908 100644 --- a/src/netedit/GNENetHelper.cpp +++ b/src/netedit/GNENetHelper.cpp @@ -44,9 +44,11 @@ #include #include #include +#include #include #include + #include "GNENetHelper.h" // --------------------------------------------------------------------------- @@ -2745,7 +2747,8 @@ GNENetHelper::AttributeCarriers::updateDemandElementFrames(const GNETagPropertie // GNENetHelper::SavingStatus - methods // --------------------------------------------------------------------------- -GNENetHelper::SavingStatus::SavingStatus() { +GNENetHelper::SavingStatus::SavingStatus(GNENet* net) : + myNet(net) { } @@ -2926,6 +2929,121 @@ GNENetHelper::SavingStatus::isMeanDatasSaved() const { return myMeanDataElementSaved; } + +GNENetHelper::SavingStatus::AskSaving +GNENetHelper::SavingStatus::askSaveNetwork() const { + // Check if there are non saved network elements + if (myNetworkSaved) { + return AskSaving::CONTINUE; + } else { + // open question box + const std::string header = TL("Confirm close Network"); + const std::string contentsA = TL("You have unsaved changes in the network."); + const std::string contentsB = TL("Do you wish to close and discard all changes?"); + const auto answer = GUISaveDialog::question(myNet->getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); + // continue depending of answer + if (answer == GUISaveDialog::CLICKED_DISCARD) { + return AskSaving::DISCARD; + } else if (answer == GUISaveDialog::CLICKED_SAVE) { + return AskSaving::SAVE; + } else { + return AskSaving::ABORT; + } + } +} + + +GNENetHelper::SavingStatus::AskSaving +GNENetHelper::SavingStatus::askSaveAdditionalElements() const { + // Check if there are non saved additional elements + if (myAdditionalSaved) { + return AskSaving::CONTINUE; + } else { + // open question box + const std::string header = TL("Save additional elements before close"); + const std::string contentsA = TL("You have unsaved additional elements."); + const std::string contentsB = TL("Do you wish to close and discard all changes?"); + const auto answer = GUISaveDialog::question(myNet->getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); + // continue depending of answer + if (answer == GUISaveDialog::CLICKED_DISCARD) { + return AskSaving::DISCARD; + } else if (answer == GUISaveDialog::CLICKED_SAVE) { + return AskSaving::SAVE; + } else { + return AskSaving::ABORT; + } + } +} + + +GNENetHelper::SavingStatus::AskSaving +GNENetHelper::SavingStatus::askSaveDemandElements() const { + // Check if there are non saved demand elements + if (myDemandElementSaved) { + return AskSaving::CONTINUE; + } else { + // open question box + const std::string header = TL("Save demand elements before close"); + const std::string contentsA = TL("You have unsaved demand elements."); + const std::string contentsB = TL("Do you wish to close and discard all changes?"); + const auto answer = GUISaveDialog::question(myNet->getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); + // continue depending of answer + if (answer == GUISaveDialog::CLICKED_DISCARD) { + return AskSaving::DISCARD; + } else if (answer == GUISaveDialog::CLICKED_SAVE) { + return AskSaving::SAVE; + } else { + return AskSaving::ABORT; + } + } +} + + +GNENetHelper::SavingStatus::AskSaving +GNENetHelper::SavingStatus::askSaveDataElements() const { + // Check if there are non saved data elements + if (myDataElementSaved) { + return AskSaving::CONTINUE; + } else { + // open question box + const std::string header = TL("Save data elements before close"); + const std::string contentsA = TL("You have unsaved data elements."); + const std::string contentsB = TL("Do you wish to close and discard all changes?"); + const auto answer = GUISaveDialog::question(myNet->getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); + // continue depending of answer + if (answer == GUISaveDialog::CLICKED_DISCARD) { + return AskSaving::DISCARD; + } else if (answer == GUISaveDialog::CLICKED_SAVE) { + return AskSaving::SAVE; + } else { + return AskSaving::ABORT; + } + } +} + + +GNENetHelper::SavingStatus::AskSaving +GNENetHelper::SavingStatus::askSaveMeanDataElements() const { + // Check if there are non saved mean data elements + if (myMeanDataElementSaved) { + return AskSaving::CONTINUE; + } else { + // open question box + const std::string header = TL("Save meanData elements before close"); + const std::string contentsA = TL("You have unsaved meanData elements."); + const std::string contentsB = TL("Do you wish to close and discard all changes?"); + const auto answer = GUISaveDialog::question(myNet->getApp(), header.c_str(), "%s", (contentsA + "\n" + contentsB).c_str()); + // continue depending of answer + if (answer == GUISaveDialog::CLICKED_DISCARD) { + return AskSaving::DISCARD; + } else if (answer == GUISaveDialog::CLICKED_SAVE) { + return AskSaving::SAVE; + } else { + return AskSaving::ABORT; + } + } +} + // --------------------------------------------------------------------------- // GNENetHelper::GNEChange_ReplaceEdgeInTLS - methods // --------------------------------------------------------------------------- diff --git a/src/netedit/GNENetHelper.h b/src/netedit/GNENetHelper.h index 5a4f06538954..846336565bea 100644 --- a/src/netedit/GNENetHelper.h +++ b/src/netedit/GNENetHelper.h @@ -848,8 +848,16 @@ struct GNENetHelper { class SavingStatus { public: + /// @brief enum used to keep the result of ask about saving elements + enum class AskSaving { + CONTINUE, // nothing to save + SAVE, // save elements + DISCARD, // discard saving + ABORT, // abort saving + }; + /// @brief constructor - SavingStatus(); + SavingStatus(GNENet* net); /// @name SumoConfig /// @{ @@ -977,7 +985,30 @@ struct GNENetHelper { /// @} + /// @name function to ask if save elements before close/quit + /// @{ + + /// @brief warns about unsaved changes in network and gives the user the option to abort + AskSaving askSaveNetwork() const; + + /// @brief warns about unsaved changes in additionals and gives the user the option to abort + AskSaving askSaveAdditionalElements() const; + + /// @brief warns about unsaved changes in demand elements and gives the user the option to abort + AskSaving askSaveDemandElements() const; + + /// @brief warns about unsaved changes in data elements and gives the user the option to abort + AskSaving askSaveDataElements() const; + + /// @brief warns about unsaved changes in meanData elements and gives the user the option to abort + AskSaving askSaveMeanDataElements() const; + + /// @} + private: + /// @brief pointer to net + GNENet* myNet; + /// @brief flag for SumoConfigSumoConfig saved bool mySumoConfigSaved = true; @@ -1005,6 +1036,9 @@ struct GNENetHelper { /// @brief flag for meanData elements saved bool myMeanDataElementSaved = true; + /// @brief invalidate default constructor + SavingStatus() = delete; + /// @brief Invalidated copy constructor. SavingStatus(const SavingStatus&) = delete; diff --git a/tests/complex/traci/simulation/convertRoad/runner.py b/tests/complex/traci/simulation/convertRoad/runner.py index af234681803d..47dd7d9e3f82 100755 --- a/tests/complex/traci/simulation/convertRoad/runner.py +++ b/tests/complex/traci/simulation/convertRoad/runner.py @@ -34,5 +34,5 @@ "--no-step-log" ]) -print(traci.simulation.convertRoad(120.44,106.40)) +print(traci.simulation.convertRoad(120.44, 106.40)) traci.close() diff --git a/tests/complex/tutorial/gtfs/plain/errors.complex b/tests/complex/tutorial/gtfs/plain/errors.complex index ca635fd734a2..c65121d35af4 100644 --- a/tests/complex/tutorial/gtfs/plain/errors.complex +++ b/tests/complex/tutorial/gtfs/plain/errors.complex @@ -1,6 +1,6 @@ Warning: Ambiguity in turnarounds computation at junction '1644613975'. Warning: Found sharp turn with radius 5.47 at the end of edge '-204836052'. -Warning: Found angle of 124.67 degrees at edge '-26637317', segment 0. +Warning: Found angle of 121.61 degrees at edge '-741297440', segment 0. Warning: Shape for junction '246767394' has distance 84.10 to its given position. Warning: Converting invalid rail_crossing to priority junction '7076971117'. Warning: Converting invalid rail_crossing to traffic_light at junction '7465967492'. @@ -11,8 +11,8 @@ Warning: 51 total messages of type: Ambiguity in turnarounds computation at junc Warning: 2 total messages of type: Converting invalid rail_crossing to priority junction '%'. Warning: 2 total messages of type: Converting invalid rail_crossing to traffic_light at junction '%'. Warning: 2 total messages of type: Edge '%' is not connected to outgoing edges at junction '%'. -Warning: 30 total messages of type: Found angle of % degrees at edge '%', segment %. -Warning: 85 total messages of type: Found sharp turn with radius % at the % of edge '%'. +Warning: 12 total messages of type: Found angle of % degrees at edge '%', segment %. +Warning: 20 total messages of type: Found sharp turn with radius % at the % of edge '%'. Warning: 3 total messages of type: Lane '%' is not connected from any incoming edge at junction '%'. Warning: 3 total messages of type: Shape for junction '%' has distance % to its given position. Warning: 4 total messages of type: The rail crossing '%' does not have any roads. diff --git a/tests/complex/tutorial/gtfs/tram/errors.complex b/tests/complex/tutorial/gtfs/tram/errors.complex index 08e23ef1c036..7e0b1a8df291 100644 --- a/tests/complex/tutorial/gtfs/tram/errors.complex +++ b/tests/complex/tutorial/gtfs/tram/errors.complex @@ -1,6 +1,6 @@ Warning: Ambiguity in turnarounds computation at junction '1644613975'. Warning: Found sharp turn with radius 5.47 at the end of edge '-204836052'. -Warning: Found angle of 124.67 degrees at edge '-26637317', segment 0. +Warning: Found angle of 121.61 degrees at edge '-741297440', segment 0. Warning: Shape for junction '246767394' has distance 84.10 to its given position. Warning: Converting invalid rail_crossing to priority junction '7076971117'. Warning: Converting invalid rail_crossing to traffic_light at junction '7465967492'. @@ -11,8 +11,8 @@ Warning: 51 total messages of type: Ambiguity in turnarounds computation at junc Warning: 2 total messages of type: Converting invalid rail_crossing to priority junction '%'. Warning: 2 total messages of type: Converting invalid rail_crossing to traffic_light at junction '%'. Warning: 2 total messages of type: Edge '%' is not connected to outgoing edges at junction '%'. -Warning: 30 total messages of type: Found angle of % degrees at edge '%', segment %. -Warning: 85 total messages of type: Found sharp turn with radius % at the % of edge '%'. +Warning: 12 total messages of type: Found angle of % degrees at edge '%', segment %. +Warning: 20 total messages of type: Found sharp turn with radius % at the % of edge '%'. Warning: 3 total messages of type: Lane '%' is not connected from any incoming edge at junction '%'. Warning: 3 total messages of type: Shape for junction '%' has distance % to its given position. Warning: 4 total messages of type: The rail crossing '%' does not have any roads. diff --git a/tests/netedit/basic/configs/netecfg/open/overwritte/yes/network/sumo.sumocfg b/tests/netedit/basic/configs/netecfg/open/menu/additionals/sumo.sumocfg similarity index 92% rename from tests/netedit/basic/configs/netecfg/open/overwritte/yes/network/sumo.sumocfg rename to tests/netedit/basic/configs/netecfg/open/menu/additionals/sumo.sumocfg index 32cb90a8bc75..0fba743fae84 100644 --- a/tests/netedit/basic/configs/netecfg/open/overwritte/yes/network/sumo.sumocfg +++ b/tests/netedit/basic/configs/netecfg/open/menu/additionals/sumo.sumocfg @@ -17,6 +17,8 @@ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later + +