From 1b69e9e465a8b74cb15b9cf72069802f4b7f2b31 Mon Sep 17 00:00:00 2001 From: Jakob Erdmann Date: Mon, 27 Jan 2025 08:47:47 +0100 Subject: [PATCH 1/8] first version to have stepwise installer creation, refs #15213 --- tools/build_config/buildMacOSInstaller.py | 233 +++++++++++----------- 1 file changed, 114 insertions(+), 119 deletions(-) diff --git a/tools/build_config/buildMacOSInstaller.py b/tools/build_config/buildMacOSInstaller.py index 8484ebed9c2..e46a9309789 100755 --- a/tools/build_config/buildMacOSInstaller.py +++ b/tools/build_config/buildMacOSInstaller.py @@ -30,7 +30,6 @@ import plistlib import re import shutil -import string import subprocess import sys import tempfile @@ -69,8 +68,8 @@ def parse_args(def_dmg_name, def_pkg_name): def_output_apps_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "apps")) def_output_fw_pkg_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "framework-pkg")) def_output_apps_pkg_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "apps-pkg")) - # def_output_dmg_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", def_dmg_name)) - # def_output_pkg_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", def_pkg_name)) + def_output_dmg_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", def_dmg_name)) + def_output_pkg_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", def_pkg_name)) op = ArgumentParser(description="Build an installer for macOS (dmg file)") @@ -80,6 +79,8 @@ def parse_args(def_dmg_name, def_pkg_name): action_group.add_argument("--create-framework-pkg", dest="create_framework_pkg", action="store_true") action_group.add_argument("--create-apps-dir", dest="create_apps_dir", action="store_true") action_group.add_argument("--create-apps-pkg", dest="create_apps_pkg", action="store_true") + action_group.add_argument("--create-installer-pkg", dest="create_installer_pkg", action="store_true") + action_group.add_argument("--create-installer-dmg", dest="create_installer_dmg", action="store_true") # ... and supply some arguments op.add_argument("--build-dir", dest="build_dir", default=def_build_dir) @@ -87,9 +88,8 @@ def parse_args(def_dmg_name, def_pkg_name): op.add_argument("--framework-pkg-dir", dest="framework_pkg_dir", default=def_output_fw_pkg_dir) op.add_argument("--apps-dir", dest="apps_dir", default=def_output_apps_dir) op.add_argument("--apps-pkg-dir", dest="apps_pkg_dir", default=def_output_apps_pkg_dir) - - # op.add_argument("--output-pkg", dest="output_pkg", help="Output path for pkg", default=def_output_pkg_path) - # op.add_argument("--output-dmg", dest="output_dmg", help="Output path for dmg", default=def_output_dmg_path) + op.add_argument("--installer-pkg-file", dest="installer_pkg_file", default=def_output_pkg_path) + op.add_argument("--installer-dmg-file", dest="installer_dmg_file", default=def_output_dmg_path) args = op.parse_args() @@ -109,54 +109,6 @@ def parse_args(def_dmg_name, def_pkg_name): return args -def create_installer_conclusion_content(framework_name): - template_html = """ - - - - - - - -
-

Important:

- -

-

For support options, including the "sumo-user" mailing list, please visit: - SUMO Contact. -

-
- - -""" - template = string.Template(template_html) - context = { - "framework_name": framework_name, - } - html = template.substitute(context) - return html - - def create_framework_dir(name, longname, pkg_id, version, sumo_build_directory, framework_output_dir): # Create the directory structure for the framework bundle # see: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html # noqa @@ -333,45 +285,87 @@ def create_app_pkg(app_name, pkg_id, version, app_dir, apps_pkg_dir): return app_name, pkg_name, pkg_id, pkg_path, pkg_size -def create_installer(frmwk_pkg, app_pkgs, id, version, output_path, verbose): - cwd = os.path.dirname(os.path.abspath(__file__)) - print(" - Creating temporary directory") - temp_dir = tempfile.mkdtemp() - resources_dir = os.path.join(temp_dir, "Resources") - os.makedirs(resources_dir) +def create_installer(framework_pkg, apps_pkg, version, installer_pkg_file): + """"Creates the installer package + + framework_pkg: framework info [framework_path, framework_id] + apps_pkg: apps info [[app1_path, app1_id], [app2_path, app2_id], ...] + id: id of the pkg-file for the installer + version: 1.20.0 + installer_pkg_file: name of the output pkg file + """ - # Copy the framework package - framework_pkg_path = frmwk_pkg[3] - shutil.copy(framework_pkg_path, temp_dir) + # Create a temporary directory to assemble everything for the installer + temp_dir = tempfile.mkdtemp() - # Copy the app packages - for app_pkg in app_pkgs: - app_pkg_path = app_pkg[3] - shutil.copy(app_pkg_path, temp_dir) + # Copy the framework pkg file and the launcher apps pkg files + shutil.copy(framework_pkg[0], temp_dir) + for app_pkg in apps_pkg: + shutil.copy(app_pkg[0], temp_dir) # Add license, background and other nice stuff - print(" - Adding additional resources to the installer") - sumo_dir = os.path.join(cwd, "..", "..", "") + resources_dir = os.path.join(temp_dir, "Resources") + os.makedirs(resources_dir) + sumo_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") sumo_data_installer_dir = os.path.join(sumo_dir, "build_config", "macos", "installer") - installer_resources_dir = os.path.join(temp_dir, "Resources") - shutil.copy(os.path.join(sumo_data_installer_dir, "background.png"), installer_resources_dir) - shutil.copy(os.path.join(sumo_dir, "LICENSE"), os.path.join(installer_resources_dir, "LICENSE.txt")) + shutil.copy(os.path.join(sumo_data_installer_dir, "background.png"), resources_dir) + shutil.copy(os.path.join(sumo_dir, "LICENSE"), os.path.join(resources_dir, "LICENSE.txt")) # Create conclusion.html in the installer resources folder - with open(os.path.join(installer_resources_dir, "conclusion.html"), "w") as file: - file.write(create_installer_conclusion_content(frmwk_pkg[0])) + with open(os.path.join(resources_dir, "conclusion.html"), "w") as file: + file.write(""" + + + + + + +
+

Important:

+ +

+

For support options, including the "sumo-user" mailing list, please visit: + SUMO Contact. +

+
+ + +""") # Create distribution.xml print(" - Creating distribution.xml") + size = os.path.getsize(framework_pkg[0]) // 1024 + path = os.path.basename(framework_pkg[0]) + refs = f" {path}" - size = frmwk_pkg[4] // 1024 - path = os.path.basename(frmwk_pkg[3]) - refs = f" {path}" - - for _, app_pkg in enumerate(app_pkgs): - size = app_pkg[4] // 1024 - path = os.path.basename(app_pkg[3]) - refs += f"\n {path}" + for app_pkg in apps_pkg: + size = os.path.getsize(app_pkg[0]) // 1024 + path = os.path.basename(app_pkg[0]) + refs += f"\n {path}" # See: https://developer.apple.com/library/archive/documentation/ # DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html @@ -405,20 +399,16 @@ def create_installer(frmwk_pkg, app_pkgs, id, version, output_path, verbose): temp_dir, "--resources", resources_dir, - output_path, + installer_pkg_file, ] - sys.stdout.flush() - out = None if verbose else subprocess.DEVNULL - subprocess.run(productbuild_command, check=True, stdout=out, stderr=out) - pkg_size = os.path.getsize(output_path) + subprocess.run(productbuild_command, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + # Removing temporary build directory print(" - Cleaning up") shutil.rmtree(temp_dir) - return "Installer", os.path.basename(output_path), id, output_path, pkg_size - -def create_dmg(dmg_title, dmg_output_path, installer_pkg_path): +def create_dmg(dmg_title, installer_pkg_path, dmg_path): print(" - Preparing disk image folder") dmg_prep_folder = tempfile.mkdtemp() @@ -426,9 +416,9 @@ def create_dmg(dmg_title, dmg_output_path, installer_pkg_path): # FIXME: Add uninstaller script to the installer folder - if os.path.exists(dmg_output_path): - print(" - Removing already existing disk image before creating a new disk image") - os.remove(dmg_output_path) + if os.path.exists(dmg_path): + print(" - Removing existing disk image before creating a new disk image") + os.remove(dmg_path) print(" - Collecting files and calculating file size") files_to_store = [] @@ -445,7 +435,7 @@ def create_dmg(dmg_title, dmg_output_path, installer_pkg_path): "files": files_to_store, # FIXME: add background and badge } - build_dmg(dmg_output_path, dmg_title, settings=settings) + build_dmg(dmg_path, dmg_title, settings=settings) print(" - Cleaning up") shutil.rmtree(dmg_prep_folder) @@ -495,12 +485,6 @@ def main(): # Parse and check the command line arguments opts = parse_args(default_dmg_name, default_pkg_name) - # if not os.path.exists(os.path.dirname(opts.output_dmg)): - # print(f"Error: dmg output directory '{os.path.dirname(opts.output_dmg)}' does not exist.", file=sys.stderr) - # sys.exit(1) - # if not os.path.exists(os.path.dirname(opts.output_pkg)): - # print(f"Error: pkg output directory '{os.path.dirname(opts.output_pkg)}' does not exist.", file=sys.stderr) - # sys.exit(1) # Let's see what we need to do if opts.create_framework_dir: @@ -562,25 +546,36 @@ def main(): _, pkg_name, _, _, pkg_size = create_app_pkg(app_name, app_id, app_ver, app_dir, opts.apps_pkg_dir) print(f" - Created \"{pkg_name}\" ({pkg_size / (1024 * 1024):.2f} MB)") - # # Building the installer package - # print("Building installer") - # installer_pkg = create_installer(framework_pkg, app_pkgs, f"{base_id}.installer", version, - # opts.output_pkg, opts.verbose) - # print("Successfully built installer\n") - - # # Putting the installer package into a dmg file - ready for signing - # print("Building disk image") - # create_dmg("Eclipse SUMO", opts.output_dmg, installer_pkg[3]) - # print("Successfully built disk image\n") - - # # Removing non-installer pkg-files - # os.remove(framework_pkg[3]) - # for app_pkg in app_pkgs: - # os.remove(app_pkg[3]) - - # print("Build completed successfully") - # print(f" - disk image : '{opts.output_dmg}' ({os.path.getsize(opts.output_dmg) / (1024 * 1024):.2f} MB)") - # print(f" - installer pkg: '{opts.output_pkg}' ({os.path.getsize(opts.output_pkg) / (1024 * 1024):.2f} MB)") + elif opts.create_installer_pkg: + if not os.path.exists(os.path.dirname(opts.installer_pkg_file)): + print(f"Error: pkg output directory '{os.path.dirname( + opts.installer_pkg_file)}' does not exist.", file=sys.stderr) + sys.exit(1) + + print("Building installer pkg file") + # Where do we find our pkgs? + fw_pkg = [os.path.join(opts.framework_pkg_dir, f"{ + default_framework_name}-{version}.pkg"), f"{base_id}.framework"] + app_pkgs = [] + for app_name, app_binary, app_framework, app_id, app_ver, app_icons, app_folder in app_list: + app_pkgs.append([os.path.join(opts.apps_pkg_dir, f"Launcher-{app_name}-{version}.pkg"), app_id]) + + # Build the installer pkg file + create_installer(fw_pkg, app_pkgs, f"{base_id}.installer", version, opts.installer_pkg_file) + pkg_size = os.path.getsize(opts.installer_pkg_file) + + print(f"Installer pkg file created: \"{opts.installer_pkg_file}\" ({pkg_size / (1024 * 1024):.2f} MB)") + + elif opts.create_installer_dmg: + if not os.path.exists(os.path.dirname(opts.installer_dmg_file)): + print(f"Error: output directory '{os.path.dirname( + opts.installer_dmg_file)}' does not exist.", file=sys.stderr) + sys.exit(1) + + print("Building installer disk image (dmg file)") + create_dmg(default_framework_long_name, opts.installer_pkg_file, opts.installer_dmg_file) + pkg_size = os.path.getsize(opts.installer_dmg_file) + print(f"Successfully built disk image: \"{opts.installer_dmg_file}\" ({pkg_size / (1024 * 1024):.2f} MB)") if __name__ == "__main__": From f1ef183d3622c4cc8aa88a64caf2551f00fe6a61 Mon Sep 17 00:00:00 2001 From: Robert Hilbrich Date: Mon, 27 Jan 2025 12:37:18 +0100 Subject: [PATCH 2/8] minor, refs #15213 --- tools/build_config/buildMacOSInstaller.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/build_config/buildMacOSInstaller.py b/tools/build_config/buildMacOSInstaller.py index e46a9309789..f3537347d2e 100755 --- a/tools/build_config/buildMacOSInstaller.py +++ b/tools/build_config/buildMacOSInstaller.py @@ -17,14 +17,6 @@ # @date 2024-07-16 # Creates the macOS installer for the current version of SUMO. -# It requires a build to have completed successfully. -# This build directory needs to be provided as parameter. -# -# This script will then: -# 1. Create a pkg file for Eclipse SUMO (= "framework") (and also add dependent libraries) -# 2. Create pkg files for all launchers (= "apps") -# 3. Create an installer pkg to jointly install the framework pkg and all app pkgs -# 4. Put the installer pkg into a dmg - ready to be notarized import os import plistlib From 5b8a4d1d84c7e50dc063cf6ec0f80ba4d0050652 Mon Sep 17 00:00:00 2001 From: Michael Behrisch Date: Mon, 27 Jan 2025 13:26:22 +0100 Subject: [PATCH 3/8] improving requirements #2 --- tools/req_dev.txt | 1 + tools/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/req_dev.txt b/tools/req_dev.txt index 756b07ca12d..7176b9a8668 100644 --- a/tools/req_dev.txt +++ b/tools/req_dev.txt @@ -1,5 +1,6 @@ # additional requirements for a developer system for GUI testing and wheel creation build>=0.7.0 +flake8 pre-commit>=3.5.0 pyautogui>=0.9.53 pyinstaller>=6.1.0 diff --git a/tools/requirements.txt b/tools/requirements.txt index 47b90a1b09b..ce1477238a7 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -2,7 +2,7 @@ ezdxf>=0.17 fmpy>=0.3.5,!=0.3.17 lxml>=4.5.0 matplotlib>=3.1.2 -ortools>=9.4.1874; python_version < '3.13' +ortools>=9.4.1874; python_version < '3.13'; sys_platform != 'darwin' pandas>=1.2.4 pandas_read_xml>=0.3.1 pillow>=10.3.0; python_version >= '3.8' From 56c313198a9bb57a9702e42fef2ed8cc57bba74a Mon Sep 17 00:00:00 2001 From: Jakob Erdmann Date: Mon, 27 Jan 2025 14:24:27 +0100 Subject: [PATCH 4/8] tweaking debug code --- .../traffic_lights/MSActuatedTrafficLightLogic.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/microsim/traffic_lights/MSActuatedTrafficLightLogic.cpp b/src/microsim/traffic_lights/MSActuatedTrafficLightLogic.cpp index ef21fbebf69..5fe8b4318d0 100644 --- a/src/microsim/traffic_lights/MSActuatedTrafficLightLogic.cpp +++ b/src/microsim/traffic_lights/MSActuatedTrafficLightLogic.cpp @@ -41,6 +41,7 @@ //#define DEBUG_DETECTORS //#define DEBUG_PHASE_SELECTION +//#define DEBUG_PHASE_SELECTION_CUSTOM #define DEBUG_COND (getID()=="C") // =========================================================================== @@ -1173,7 +1174,12 @@ MSActuatedTrafficLightLogic::decideNextPhaseCustom(bool mustSwitch) { for (int next : getCurrentPhaseDef().nextPhases) { const MSPhaseDefinition* phase = myPhases[next]; const std::string& condition = mustSwitch ? phase->finalTarget : phase->earlyTarget; - //std::cout << SIMTIME << " mustSwitch=" << mustSwitch << " condition=" << condition << "\n"; +#ifdef DEBUG_PHASE_SELECTION_CUSTOM + if (DEBUG_COND) { + std::cout << SIMTIME << " mustSwitch=" << mustSwitch << " cur=" << myStep << " next=" << next << " condition=" << condition + << " eval=" << (condition == "" ? NAN : evalExpression(condition)) << "\n"; + } +#endif if (condition != "") { // backward compatibility if a user redefined DEFAULT_CONDITION if (condition == DEFAULT_CONDITION && myConditions.count(DEFAULT_CONDITION) == 0) { From 34bc35b2ff0a00b6ae96efc4fdf361260eb8bfc3 Mon Sep 17 00:00:00 2001 From: Jakob Erdmann Date: Mon, 27 Jan 2025 14:33:39 +0100 Subject: [PATCH 5/8] #2 removed outdated restriction notice on --weight-attribute --- docs/web/docs/Simulation/Routing.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/web/docs/Simulation/Routing.md b/docs/web/docs/Simulation/Routing.md index fe6787d7809..fad66d43261 100644 --- a/docs/web/docs/Simulation/Routing.md +++ b/docs/web/docs/Simulation/Routing.md @@ -155,8 +155,7 @@ also be set using *traci.edge.setEffort*. !!! caution The default effort value is 0 which causes detour routes to be preferred when not loading sensible effort values. -The applications [duarouter](../duarouter.md) and [marouter](../marouter.md) also support the options **--weight-file** and **--weight-attribute** but they can only be used with one of the weight attributes "CO", "CO2", "PMx", "HC", "NOx", "fuel", "electricity", "noise". However, they will still work as expected when the user loads custom effort values for these attributes. - +The applications [duarouter](../duarouter.md) and [marouter](../marouter.md) also support the options **--weight-file** and **--weight-attribute** and this may be used to ready any edge attribute value in the given file. # Routing by *distance* From cc34cc50d61314348a76a69c0eaddc3aa75239ce Mon Sep 17 00:00:00 2001 From: Pablo Alvarez Lopez Date: Mon, 27 Jan 2025 13:12:15 +0100 Subject: [PATCH 6/8] Updated creation of duplicated elements. Refs #16027 --- .../elements/demand/GNERouteHandler.cpp | 271 ++++++++---------- src/netedit/elements/demand/GNERouteHandler.h | 10 +- 2 files changed, 129 insertions(+), 152 deletions(-) diff --git a/src/netedit/elements/demand/GNERouteHandler.cpp b/src/netedit/elements/demand/GNERouteHandler.cpp index 7a7c627f63a..a926787308f 100644 --- a/src/netedit/elements/demand/GNERouteHandler.cpp +++ b/src/netedit/elements/demand/GNERouteHandler.cpp @@ -109,33 +109,36 @@ GNERouteHandler::buildVType(const CommonXMLStructure::SumoBaseObject* sumoBaseOb if (DEFAULT_VTYPES.count(vTypeParameter.id) > 0) { // overwrite default vehicle type return GNEVType::overwriteVType(myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, vTypeParameter.id, false), vTypeParameter, myNet->getViewNet()->getUndoList()); - } else if (!checkValidDemandElementID(SUMO_TAG_VTYPE, vTypeParameter.id)) { - return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_VTYPE, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vTypeParameter.id)) { - return false; } else { - // create vType/pType using myCurrentVType - GNEDemandElement* vType = new GNEVType(myNet, vTypeParameter); - // check if add this vType to a distribution - GNEDemandElement* vTypeDistribution = nullptr; - if (sumoBaseObject->getParentSumoBaseObject() && sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION) { - vTypeDistribution = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false); - } - if (myAllowUndoRedo) { - myNet->getViewNet()->getUndoList()->begin(vType, TL("add ") + vType->getTagStr() + " '" + vTypeParameter.id + "'"); - myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vType, true), true); - if (vTypeDistribution) { - vTypeDistribution->addDistributionKey(vType, vType->getAttributeDouble(SUMO_ATTR_PROB), myNet->getViewNet()->getUndoList()); - } - myNet->getViewNet()->getUndoList()->end(); + const auto element = retrieveDemandElement({SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vTypeParameter.id); + if (!checkElement(SUMO_TAG_VTYPE, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_VTYPE, vTypeParameter.id)) { + return false; } else { - myNet->getAttributeCarriers()->insertDemandElement(vType); - if (vTypeDistribution) { - vTypeDistribution->addDistributionKey(vType, vType->getAttributeDouble(SUMO_ATTR_PROB)); + // create vType/pType using myCurrentVType + GNEDemandElement* vType = new GNEVType(myNet, vTypeParameter); + // check if add this vType to a distribution + GNEDemandElement* vTypeDistribution = nullptr; + if (sumoBaseObject->getParentSumoBaseObject() && sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION) { + vTypeDistribution = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false); + } + if (myAllowUndoRedo) { + myNet->getViewNet()->getUndoList()->begin(vType, TL("add ") + vType->getTagStr() + " '" + vTypeParameter.id + "'"); + myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vType, true), true); + if (vTypeDistribution) { + vTypeDistribution->addDistributionKey(vType, vType->getAttributeDouble(SUMO_ATTR_PROB), myNet->getViewNet()->getUndoList()); + } + myNet->getViewNet()->getUndoList()->end(); + } else { + myNet->getAttributeCarriers()->insertDemandElement(vType); + if (vTypeDistribution) { + vTypeDistribution->addDistributionKey(vType, vType->getAttributeDouble(SUMO_ATTR_PROB)); + } + vType->incRef("buildVType"); } - vType->incRef("buildVType"); + return true; } - return true; } } @@ -145,10 +148,11 @@ GNERouteHandler::buildVTypeDistribution(const CommonXMLStructure::SumoBaseObject const std::vector& vTypeIDs, const std::vector& probabilities) { // declare vector with vType and their probabilities std::vector vTypes; - // first check conditions - if (!checkValidDemandElementID(SUMO_TAG_VTYPE_DISTRIBUTION, id)) { + // check conditions + const auto element = retrieveDemandElement({SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, id); + if (!checkElement(SUMO_TAG_VTYPE_DISTRIBUTION, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_VTYPE_DISTRIBUTION, id)) { return false; } else if (getDistributionElements(sumoBaseObject, SUMO_TAG_VTYPE, vTypeIDs, probabilities, vTypes)) { return false; @@ -180,12 +184,11 @@ bool GNERouteHandler::buildRoute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, SUMOVehicleClass vClass, const std::vector& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime, const double probability, const Parameterised::Map& routeParameters) { - // first check if we have to overwritte element - checkOverwritteElement({SUMO_TAG_ROUTE}, id); // check conditions - if (!checkValidDemandElementID(SUMO_TAG_ROUTE, id)) { + const auto element = retrieveDemandElement({SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, id); + if (!checkElement(SUMO_TAG_ROUTE, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_ROUTE, {SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_ROUTE, id)) { return false; } else { // parse edges @@ -224,16 +227,15 @@ GNERouteHandler::buildRoute(const CommonXMLStructure::SumoBaseObject* sumoBaseOb bool -GNERouteHandler::buildRouteDistribution(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, - const std::vector& routeIDs, const std::vector& probabilities) { +GNERouteHandler::buildRouteDistribution(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, + const std::vector& /*routeIDs*/, const std::vector& probabilities) { // declare vector with route and their probabilities std::vector routes; - // first check conditions - if (!checkValidDemandElementID(SUMO_TAG_ROUTE_DISTRIBUTION, id)) { - return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_ROUTE_DISTRIBUTION, {SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, id)) { + // check conditions + const auto element = retrieveDemandElement({SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, id); + if (!checkElement(SUMO_TAG_ROUTE_DISTRIBUTION, element)) { return false; - } else if (!getDistributionElements(sumoBaseObject, SUMO_TAG_ROUTE, routeIDs, probabilities, routes)) { + } else if (!checkValidDemandElementID(SUMO_TAG_ROUTE_DISTRIBUTION, id)) { return false; } else { // create distributions @@ -261,12 +263,11 @@ GNERouteHandler::buildRouteDistribution(const CommonXMLStructure::SumoBaseObject bool GNERouteHandler::buildVehicleOverRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(SUMO_TAG_VEHICLE, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(SUMO_TAG_VEHICLE, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_VEHICLE, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_VEHICLE, vehicleParameters.id)) { return false; } else { // obtain routes and vtypes @@ -304,12 +305,11 @@ bool GNERouteHandler::buildVehicleEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::vector& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime, const double probability, const Parameterised::Map& routeParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if ID is duplicated - if (!checkValidDemandElementID(GNE_TAG_VEHICLE_WITHROUTE, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_VEHICLE_WITHROUTE, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_VEHICLE_WITHROUTE, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_VEHICLE_WITHROUTE, vehicleParameters.id)) { return false; } else { // parse route edges @@ -355,12 +355,11 @@ GNERouteHandler::buildVehicleEmbeddedRoute(const CommonXMLStructure::SumoBaseObj bool GNERouteHandler::buildFlowOverRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(GNE_TAG_FLOW_ROUTE, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_FLOW_ROUTE, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_FLOW_ROUTE, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_FLOW_ROUTE, vehicleParameters.id)) { return false; } else { // obtain routes and vtypes @@ -398,12 +397,11 @@ bool GNERouteHandler::buildFlowEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::vector& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime, const double probability, const Parameterised::Map& routeParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if ID is duplicated - if (!checkValidDemandElementID(GNE_TAG_FLOW_WITHROUTE, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_ROUTE_EMBEDDED, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_FLOW_WITHROUTE, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_ROUTE_EMBEDDED, vehicleParameters.id)) { return false; } else { // parse route edges @@ -450,20 +448,17 @@ GNERouteHandler::buildFlowEmbeddedRoute(const CommonXMLStructure::SumoBaseObject bool GNERouteHandler::buildTrip(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVehicleParameter& vehicleParameters, const std::string& fromEdgeID, const std::string& toEdgeID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // set via attribute - if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) { - vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA); - } - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(SUMO_TAG_TRIP, vehicleParameters.id)) { - return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_TRIP, myVehicleTags, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(SUMO_TAG_TRIP, element)) { return false; - } else if (!checkViaAttribute(SUMO_TAG_TRIP, vehicleParameters.id, vehicleParameters.via)) { + } else if (!checkValidDemandElementID(SUMO_TAG_TRIP, vehicleParameters.id)) { return false; } else { + // set via attribute + if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) { + vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA); + } // parse edges const auto fromEdge = parseEdge(SUMO_TAG_TRIP, vehicleParameters.id, fromEdgeID, sumoBaseObject, true); const auto toEdge = parseEdge(SUMO_TAG_TRIP, vehicleParameters.id, toEdgeID, sumoBaseObject, false); @@ -504,12 +499,11 @@ GNERouteHandler::buildTrip(const CommonXMLStructure::SumoBaseObject* sumoBaseObj bool GNERouteHandler::buildTripJunctions(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::string& fromJunctionID, const std::string& toJunctionID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_TRIP_JUNCTIONS, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_TRIP_JUNCTIONS, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id)) { return false; } else { // parse junctions @@ -552,12 +546,11 @@ GNERouteHandler::buildTripJunctions(const CommonXMLStructure::SumoBaseObject* /* bool GNERouteHandler::buildTripTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::string& fromTAZID, const std::string& toTAZID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(GNE_TAG_TRIP_TAZS, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_TRIP_TAZS, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_TRIP_TAZS, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_TRIP_TAZS, vehicleParameters.id)) { return false; } else { // parse TAZs @@ -600,20 +593,17 @@ GNERouteHandler::buildTripTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoB bool GNERouteHandler::buildFlow(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVehicleParameter& vehicleParameters, const std::string& fromEdgeID, const std::string& toEdgeID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // set via attribute - if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) { - vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA); - } - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(SUMO_TAG_FLOW, vehicleParameters.id)) { - return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_FLOW, myVehicleTags, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(SUMO_TAG_FLOW, element)) { return false; - } else if (!checkViaAttribute(SUMO_TAG_FLOW, vehicleParameters.id, vehicleParameters.via)) { + } else if (!checkValidDemandElementID(SUMO_TAG_FLOW, vehicleParameters.id)) { return false; } else { + // set via attribute + if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) { + vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA); + } // parse edges const auto fromEdge = parseEdge(SUMO_TAG_FLOW, vehicleParameters.id, fromEdgeID, sumoBaseObject, true); const auto toEdge = parseEdge(SUMO_TAG_FLOW, vehicleParameters.id, toEdgeID, sumoBaseObject, false); @@ -654,12 +644,11 @@ GNERouteHandler::buildFlow(const CommonXMLStructure::SumoBaseObject* sumoBaseObj bool GNERouteHandler::buildFlowJunctions(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::string& fromJunctionID, const std::string& toJunctionID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_FLOW_JUNCTIONS, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_FLOW_JUNCTIONS, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id)) { return false; } else { // parse junctions @@ -702,12 +691,11 @@ GNERouteHandler::buildFlowJunctions(const CommonXMLStructure::SumoBaseObject* /* bool GNERouteHandler::buildFlowTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters, const std::string& fromTAZID, const std::string& toTAZID) { - // first check if we have to overwritte element - checkOverwritteElement(myVehicleTags, vehicleParameters.id); - // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace) - if (!checkValidDemandElementID(GNE_TAG_FLOW_TAZS, vehicleParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myVehicleTags, vehicleParameters.id); + if (!checkElement(GNE_TAG_FLOW_TAZS, element)) { return false; - } else if (!checkDuplicatedDemandElement(GNE_TAG_FLOW_TAZS, myVehicleTags, vehicleParameters.id)) { + } else if (!checkValidDemandElementID(GNE_TAG_FLOW_TAZS, vehicleParameters.id)) { return false; } else { // parse TAZs @@ -749,12 +737,11 @@ GNERouteHandler::buildFlowTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoB bool GNERouteHandler::buildPerson(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myPersonTags, personParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(SUMO_TAG_PERSON, personParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myPersonTags, personParameters.id); + if (!checkElement(SUMO_TAG_PERSON, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_PERSON, myPersonTags, personParameters.id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_PERSON, personParameters.id)) { return false; } else { // obtain type @@ -784,12 +771,11 @@ GNERouteHandler::buildPerson(const CommonXMLStructure::SumoBaseObject* /*sumoBas bool GNERouteHandler::buildPersonFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personFlowParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myPersonTags, personFlowParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(SUMO_TAG_PERSONFLOW, personFlowParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myPersonTags, personFlowParameters.id); + if (!checkElement(SUMO_TAG_PERSONFLOW, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_PERSONFLOW, myPersonTags, personFlowParameters.id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_PERSONFLOW, personFlowParameters.id)) { return false; } else { // obtain type @@ -927,12 +913,11 @@ GNERouteHandler::buildRide(const CommonXMLStructure::SumoBaseObject* sumoBaseObj bool GNERouteHandler::buildContainer(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myPersonTags, containerParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(SUMO_TAG_CONTAINER, containerParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myContainerTags, containerParameters.id); + if (!checkElement(SUMO_TAG_CONTAINER, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_CONTAINER, myContainerTags, containerParameters.id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_CONTAINER, containerParameters.id)) { return false; } else { // obtain type @@ -962,12 +947,11 @@ GNERouteHandler::buildContainer(const CommonXMLStructure::SumoBaseObject* /*sumo bool GNERouteHandler::buildContainerFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerFlowParameters) { - // first check if we have to overwritte element - checkOverwritteElement(myPersonTags, containerFlowParameters.id); - // first check if ID is duplicated - if (!checkValidDemandElementID(SUMO_TAG_CONTAINERFLOW, containerFlowParameters.id)) { + // check conditions + const auto element = retrieveDemandElement(myContainerTags, containerFlowParameters.id); + if (!checkElement(SUMO_TAG_CONTAINERFLOW, element)) { return false; - } else if (!checkDuplicatedDemandElement(SUMO_TAG_CONTAINERFLOW, myContainerTags, containerFlowParameters.id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_CONTAINERFLOW, containerFlowParameters.id)) { return false; } else { // obtain type @@ -2623,42 +2607,35 @@ GNERouteHandler::getDistributionElements(const CommonXMLStructure::SumoBaseObjec } -bool -GNERouteHandler::checkDuplicatedDemandElement(const SumoXMLTag tag, const std::vector tags, const std::string& id) { - for (const auto& tagChecked : tags) { +GNEDemandElement* +GNERouteHandler::retrieveDemandElement(const std::vector tags, const std::string& id) { + for (const auto& tag : tags) { // retrieve demand element - auto demandElement = myNet->getAttributeCarriers()->retrieveDemandElement(tagChecked, id, false); - // if demand element exist, check if overwrite (delete) + auto demandElement = myNet->getAttributeCarriers()->retrieveDemandElement(tag, id, false); if (demandElement) { - if (!myAllowUndoRedo) { - // only demand element if allow undo-redo - return writeErrorDuplicated(tag, id, tagChecked); - } else if (myOverwrite) { - // delete demand element (and all of their childrens) - myNet->deleteDemandElement(demandElement, myNet->getViewNet()->getUndoList()); - } else { - // duplicated demand element - return writeErrorDuplicated(tag, id, tagChecked); - } + return demandElement; } } - return true; + return nullptr; } -void -GNERouteHandler::checkOverwritteElement(const std::vector& tags, const std::string& id) { - if (myOverwrite) { - // retrieve demand element and remove it - for (const auto& tag : tags) { - auto demandElement = myNet->getAttributeCarriers()->retrieveDemandElement(tag, id, false); - if (demandElement) { - writeWarningOverwritting(tag, id); - myNet->getViewNet()->getUndoList()->begin(demandElement, TL("delete ") + demandElement->getTagStr() + " '" + id + "'"); - myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(demandElement, false), true); - myNet->getViewNet()->getUndoList()->end(); - } +bool +GNERouteHandler::checkElement(const SumoXMLTag tag, GNEDemandElement* demandElement) { + if (demandElement) { + if (myAllowUndoRedo && myOverwrite) { + writeWarningOverwritting(tag, demandElement->getID()); + myNet->getViewNet()->getUndoList()->begin(demandElement, TL("delete ") + demandElement->getTagStr() + " '" + demandElement->getID() + "'"); + myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(demandElement, false), true); + myNet->getViewNet()->getUndoList()->end(); + // continue creating new element + return true; + } else { + // write errorduplicated demand element + return writeErrorDuplicated(tag, demandElement->getID(), demandElement->getTagProperty().getTag()); } + } else { + return true; } } diff --git a/src/netedit/elements/demand/GNERouteHandler.h b/src/netedit/elements/demand/GNERouteHandler.h index 1a8d5861724..457281fd344 100644 --- a/src/netedit/elements/demand/GNERouteHandler.h +++ b/src/netedit/elements/demand/GNERouteHandler.h @@ -289,11 +289,11 @@ class GNERouteHandler : public RouteHandler { const std::vector& distributionElementIDs, const std::vector& probabilities, std::vector& elements); - /// @brief check if given ID correspond to a duplicated demand element - bool checkDuplicatedDemandElement(const SumoXMLTag tag, const std::vector tags, const std::string& id); + /// @brief get element by ID + GNEDemandElement* retrieveDemandElement(const std::vector tags, const std::string& id); - /// @brief check if - void checkOverwritteElement(const std::vector& tags, const std::string& id); + /// @brief check if element exist, and if overwritte + bool checkElement(const SumoXMLTag tag, GNEDemandElement* demandElement); private: /// @brief pointer to GNENet @@ -308,7 +308,7 @@ class GNERouteHandler : public RouteHandler { /// @brief allow undo/redo const bool myAllowUndoRedo; - /// @brief check if overwrite + /// @brief flag to check if overwrite elements const bool myOverwrite; /// @brief vehicle tags From 2af454e024ea8ed1bf836195b661dcacdef0cc08 Mon Sep 17 00:00:00 2001 From: Pablo Alvarez Lopez Date: Mon, 27 Jan 2025 14:25:00 +0100 Subject: [PATCH 7/8] Fixed problem overwriting elements. Refs #16027 --- .../elements/additional/GNEAdditionalHandler.cpp | 4 ++-- src/netedit/elements/data/GNEDataHandler.cpp | 4 ++-- src/netedit/elements/data/GNEMeanDataHandler.cpp | 4 ++-- src/netedit/elements/demand/GNERouteHandler.cpp | 7 +++---- src/utils/handlers/CommonHandler.cpp | 12 ++++++------ src/utils/handlers/CommonHandler.h | 6 +++--- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/netedit/elements/additional/GNEAdditionalHandler.cpp b/src/netedit/elements/additional/GNEAdditionalHandler.cpp index b4166cf552b..8aaf0e2e389 100644 --- a/src/netedit/elements/additional/GNEAdditionalHandler.cpp +++ b/src/netedit/elements/additional/GNEAdditionalHandler.cpp @@ -2066,13 +2066,13 @@ GNEAdditionalHandler::checkDuplicatedAdditional(const SumoXMLTag tag, const std: if (additional) { if (!myAllowUndoRedo) { // only overwrite if allow undo-redo - return writeErrorDuplicated(tag, id, tagChecked); + return writeWarningDuplicated(tag, id, tagChecked); } else if (myOverwrite) { // delete additional (and all of their childrens) myNet->deleteAdditional(additional, myNet->getViewNet()->getUndoList()); } else { // duplicated additional - return writeErrorDuplicated(tag, id, tagChecked); + return writeWarningDuplicated(tag, id, tagChecked); } } } diff --git a/src/netedit/elements/data/GNEDataHandler.cpp b/src/netedit/elements/data/GNEDataHandler.cpp index f3a9ba7e230..2b3b8bcbf1f 100644 --- a/src/netedit/elements/data/GNEDataHandler.cpp +++ b/src/netedit/elements/data/GNEDataHandler.cpp @@ -273,13 +273,13 @@ GNEDataHandler::checkDuplicatedDataSet(const std::string& id) { if (dataSet) { if (!myAllowUndoRedo) { // only overwrite if allow undo-redo - return writeErrorDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); + return writeWarningDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); } else if (myOverwrite) { // delete demand element (and all of their childrens) myNet->deleteDataSet(dataSet, myNet->getViewNet()->getUndoList()); } else { // duplicated dataSet - return writeErrorDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); + return writeWarningDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); } } return true; diff --git a/src/netedit/elements/data/GNEMeanDataHandler.cpp b/src/netedit/elements/data/GNEMeanDataHandler.cpp index 48f5207e875..390d75a7c91 100644 --- a/src/netedit/elements/data/GNEMeanDataHandler.cpp +++ b/src/netedit/elements/data/GNEMeanDataHandler.cpp @@ -191,13 +191,13 @@ GNEMeanDataHandler::checkDuplicatedMeanDataElement(const SumoXMLTag tag, const s if (meanDataElement) { if (!myAllowUndoRedo) { // only overwrite if allow undo-redo - return writeErrorDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); + return writeWarningDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); } else if (myOverwrite) { // delete meanData element (and all of their childrens) myNet->deleteMeanData(meanDataElement, myNet->getViewNet()->getUndoList()); } else { // duplicated demand - return writeErrorDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); + return writeWarningDuplicated(SUMO_TAG_DATASET, id, SUMO_TAG_DATASET); } } return true; diff --git a/src/netedit/elements/demand/GNERouteHandler.cpp b/src/netedit/elements/demand/GNERouteHandler.cpp index a926787308f..31a53957919 100644 --- a/src/netedit/elements/demand/GNERouteHandler.cpp +++ b/src/netedit/elements/demand/GNERouteHandler.cpp @@ -2625,14 +2625,13 @@ GNERouteHandler::checkElement(const SumoXMLTag tag, GNEDemandElement* demandElem if (demandElement) { if (myAllowUndoRedo && myOverwrite) { writeWarningOverwritting(tag, demandElement->getID()); - myNet->getViewNet()->getUndoList()->begin(demandElement, TL("delete ") + demandElement->getTagStr() + " '" + demandElement->getID() + "'"); - myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(demandElement, false), true); - myNet->getViewNet()->getUndoList()->end(); + // delete element + myNet->deleteDemandElement(demandElement, myNet->getViewNet()->getUndoList()); // continue creating new element return true; } else { // write errorduplicated demand element - return writeErrorDuplicated(tag, demandElement->getID(), demandElement->getTagProperty().getTag()); + return writeWarningDuplicated(tag, demandElement->getID(), demandElement->getTagProperty().getTag()); } } else { return true; diff --git a/src/utils/handlers/CommonHandler.cpp b/src/utils/handlers/CommonHandler.cpp index 1af9af13d7c..0fb4dd012a0 100644 --- a/src/utils/handlers/CommonHandler.cpp +++ b/src/utils/handlers/CommonHandler.cpp @@ -328,6 +328,12 @@ CommonHandler::writeWarningOverwritting(const SumoXMLTag tag, const std::string& } +bool +CommonHandler::writeWarningDuplicated(const SumoXMLTag tag, const std::string& id, const SumoXMLTag checkedTag) { + return writeError(TLF("Could not build % with ID '%' in netedit; Found another % with the same ID.", toString(tag), id, toString(checkedTag))); +} + + bool CommonHandler::writeError(const std::string& error) { WRITE_ERROR(error); @@ -342,12 +348,6 @@ CommonHandler::writeErrorInvalidPosition(const SumoXMLTag tag, const std::string } -bool -CommonHandler::writeErrorDuplicated(const SumoXMLTag tag, const std::string& id, const SumoXMLTag checkedTag) { - return writeError(TLF("Could not build % with ID '%' in netedit; Found another % with the same ID.", toString(tag), id, toString(checkedTag))); -} - - bool CommonHandler::writeErrorEmptyEdges(const SumoXMLTag tag, const std::string& id) { return writeError(TLF("Could not build % with ID '%' in netedit; List of edges cannot be empty.", toString(tag), id)); diff --git a/src/utils/handlers/CommonHandler.h b/src/utils/handlers/CommonHandler.h index 1bf259fed6c..2648862096b 100644 --- a/src/utils/handlers/CommonHandler.h +++ b/src/utils/handlers/CommonHandler.h @@ -109,15 +109,15 @@ class CommonHandler { /// @brief write warning overwritting element void writeWarningOverwritting(const SumoXMLTag tag, const std::string& id); + /// @brief write warning duplicated element + bool writeWarningDuplicated(const SumoXMLTag tag, const std::string& id, const SumoXMLTag checkedTag); + /// @brief write error and enable error creating element bool writeError(const std::string& error); /// @brief write error "invalid position" bool writeErrorInvalidPosition(const SumoXMLTag tag, const std::string& id); - /// @brief write error duplicated element - bool writeErrorDuplicated(const SumoXMLTag tag, const std::string& id, const SumoXMLTag checkedTag); - /// @brief write error "empty edges" bool writeErrorEmptyEdges(const SumoXMLTag tag, const std::string& id); From b036265773f3d16fcc03fa4e3e02e3e803234cfb Mon Sep 17 00:00:00 2001 From: Pablo Alvarez Lopez Date: Mon, 27 Jan 2025 15:47:14 +0100 Subject: [PATCH 8/8] Extended same loading system for additionals. Refs #16027 --- .../additional/GNEAdditionalHandler.cpp | 223 ++++++++++-------- .../additional/GNEAdditionalHandler.h | 11 +- .../elements/demand/GNERouteHandler.cpp | 2 +- 3 files changed, 137 insertions(+), 99 deletions(-) diff --git a/src/netedit/elements/additional/GNEAdditionalHandler.cpp b/src/netedit/elements/additional/GNEAdditionalHandler.cpp index 8aaf0e2e389..4323fd011e7 100644 --- a/src/netedit/elements/additional/GNEAdditionalHandler.cpp +++ b/src/netedit/elements/additional/GNEAdditionalHandler.cpp @@ -90,9 +90,10 @@ GNEAdditionalHandler::buildBusStop(const CommonXMLStructure::SumoBaseObject* sum const std::vector& lines, const int personCapacity, const double parkingLength, const RGBColor& color, const bool friendlyPosition, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_BUS_STOP, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::busStops, id); + if (!checkElement(SUMO_TAG_BUS_STOP, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_BUS_STOP, {SUMO_TAG_BUS_STOP, SUMO_TAG_TRAIN_STOP}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_BUS_STOP, id)) { return false; } else { // get netedit parameters @@ -134,9 +135,10 @@ GNEAdditionalHandler::buildTrainStop(const CommonXMLStructure::SumoBaseObject* s const std::vector& lines, const int personCapacity, const double parkingLength, const RGBColor& color, const bool friendlyPosition, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_TRAIN_STOP, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::busStops, id); + if (!checkElement(SUMO_TAG_TRAIN_STOP, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_TRAIN_STOP, {SUMO_TAG_TRAIN_STOP, SUMO_TAG_BUS_STOP}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_TRAIN_STOP, id)) { return false; } else { // get netedit parameters @@ -236,9 +238,10 @@ GNEAdditionalHandler::buildContainerStop(const CommonXMLStructure::SumoBaseObjec const double startPos, const double endPos, const std::string& name, const std::vector& lines, const int containerCapacity, const double parkingLength, const RGBColor& color, const bool friendlyPosition, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_CONTAINER_STOP, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_CONTAINER_STOP}, id); + if (!checkElement(SUMO_TAG_CONTAINER_STOP, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_CONTAINER_STOP, {SUMO_TAG_CONTAINER_STOP}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_CONTAINER_STOP, id)) { return false; } else { // get netedit parameters @@ -280,12 +283,11 @@ GNEAdditionalHandler::buildChargingStation(const CommonXMLStructure::SumoBaseObj const double efficiency, const bool chargeInTransit, const SUMOTime chargeDelay, const std::string& chargeType, const SUMOTime waitingTime, const bool friendlyPosition, const std::string& /* parkingAreaID */, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_CHARGING_STATION, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_CHARGING_STATION}, id); + if (!checkElement(SUMO_TAG_CHARGING_STATION, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_CHARGING_STATION, {SUMO_TAG_CHARGING_STATION}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_CHARGING_STATION, id)) { return false; - } else if (!SUMOXMLDefinitions::ChargeTypes.hasString(chargeType)) { - return writeError(TLF("Could not build % with ID '%' in netedit; Invalid charge type '%' .", toString(SUMO_TAG_CHARGING_STATION), id, chargeType)); } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -300,6 +302,8 @@ GNEAdditionalHandler::buildChargingStation(const CommonXMLStructure::SumoBaseObj return false; } else if (!checkNegative(SUMO_TAG_CHARGING_STATION, id, SUMO_ATTR_CHARGEDELAY, chargeDelay, true)) { return false; + } else if (!SUMOXMLDefinitions::ChargeTypes.hasString(chargeType)) { + return writeError(TLF("Could not build % with ID '%' in netedit; Invalid charge type '%' .", toString(SUMO_TAG_CHARGING_STATION), id, chargeType)); } else { // build chargingStation GNEAdditional* chargingStation = new GNEChargingStation(id, lane, myNet, startPos, endPos, name, chargingPower, efficiency, chargeInTransit, @@ -326,9 +330,10 @@ GNEAdditionalHandler::buildParkingArea(const CommonXMLStructure::SumoBaseObject* const std::vector& badges, const bool friendlyPosition, const int roadSideCapacity, const bool onRoad, const double width, const double length, const double angle, const bool lefthand, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_PARKING_AREA, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_PARKING_AREA}, id); + if (!checkElement(SUMO_TAG_PARKING_AREA, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_PARKING_AREA, {SUMO_TAG_PARKING_AREA}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_PARKING_AREA, id)) { return false; } else { // get netedit parameters @@ -424,9 +429,10 @@ GNEAdditionalHandler::buildE1Detector(const CommonXMLStructure::SumoBaseObject* const std::vector& nextEdges, const std::string& detectPersons, const std::string& name, const bool friendlyPos, const Parameterised::Map& parameters) { // check conditions - if (!checkValidDetectorID(SUMO_TAG_INDUCTION_LOOP, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_INDUCTION_LOOP}, id); + if (!checkElement(SUMO_TAG_INDUCTION_LOOP, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_INDUCTION_LOOP, {SUMO_TAG_INDUCTION_LOOP}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_INDUCTION_LOOP, id)) { return false; } else { // get netedit parameters @@ -471,9 +477,10 @@ GNEAdditionalHandler::buildSingleLaneDetectorE2(const CommonXMLStructure::SumoBa const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos, const bool show, const Parameterised::Map& parameters) { // check conditions - if (!checkValidDetectorID(SUMO_TAG_LANE_AREA_DETECTOR, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::laneAreaDetectors, id); + if (!checkElement(SUMO_TAG_LANE_AREA_DETECTOR, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_LANE_AREA_DETECTOR, {SUMO_TAG_LANE_AREA_DETECTOR, GNE_TAG_MULTI_LANE_AREA_DETECTOR}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_LANE_AREA_DETECTOR, id)) { return false; } else { // get netedit parameters @@ -534,9 +541,10 @@ GNEAdditionalHandler::buildMultiLaneDetectorE2(const CommonXMLStructure::SumoBas const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos, const bool show, const Parameterised::Map& parameters) { // check conditions - if (!checkValidDetectorID(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::laneAreaDetectors, id); + if (!checkElement(GNE_TAG_MULTI_LANE_AREA_DETECTOR, element)) { return false; - } else if (!checkDuplicatedAdditional(GNE_TAG_MULTI_LANE_AREA_DETECTOR, {SUMO_TAG_LANE_AREA_DETECTOR, GNE_TAG_MULTI_LANE_AREA_DETECTOR}, id)) { + } else if (!checkValidDemandElementID(GNE_TAG_MULTI_LANE_AREA_DETECTOR, id)) { return false; } else { // get netedit parameters @@ -599,7 +607,10 @@ GNEAdditionalHandler::buildDetectorE3(const CommonXMLStructure::SumoBaseObject* const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const bool openEntry, const bool expectedArrival, const Parameterised::Map& parameters) { // check conditions - if (!checkValidDetectorID(SUMO_TAG_LANE_AREA_DETECTOR, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_ENTRY_EXIT_DETECTOR}, id); + if (!checkElement(SUMO_TAG_ENTRY_EXIT_DETECTOR, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_ENTRY_EXIT_DETECTOR, id)) { return false; } else if (!checkNegative(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, SUMO_ATTR_PERIOD, period, true)) { return false; @@ -611,8 +622,6 @@ GNEAdditionalHandler::buildDetectorE3(const CommonXMLStructure::SumoBaseObject* return false; } else if (!checkListOfVehicleTypes(SUMO_TAG_ENTRY_EXIT_DETECTOR, id, vehicleTypes)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_ENTRY_EXIT_DETECTOR, {SUMO_TAG_ENTRY_EXIT_DETECTOR}, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -708,9 +717,10 @@ GNEAdditionalHandler::buildDetectorE1Instant(const CommonXMLStructure::SumoBaseO const std::string& filename, const std::vector& vehicleTypes, const std::vector& nextEdges, const std::string& detectPersons, const std::string& name, const bool friendlyPos, const Parameterised::Map& parameters) { // check conditions - if (!checkValidDetectorID(SUMO_TAG_INSTANT_INDUCTION_LOOP, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_INSTANT_INDUCTION_LOOP}, id); + if (!checkElement(SUMO_TAG_INSTANT_INDUCTION_LOOP, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_INSTANT_INDUCTION_LOOP, {SUMO_TAG_INSTANT_INDUCTION_LOOP}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_INSTANT_INDUCTION_LOOP, id)) { return false; } else { // get netedit parameters @@ -719,7 +729,7 @@ GNEAdditionalHandler::buildDetectorE1Instant(const CommonXMLStructure::SumoBaseO GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(laneID, false); // check lane if (lane == nullptr) { - return writeErrorInvalidParent(SUMO_TAG_INDUCTION_LOOP, id, SUMO_TAG_LANE, laneID); + return writeErrorInvalidParent(SUMO_TAG_INSTANT_INDUCTION_LOOP, id, SUMO_TAG_LANE, laneID); } else if (!checkFileName(SUMO_TAG_INSTANT_INDUCTION_LOOP, id, SUMO_ATTR_FILE, filename)) { return false; } else if (!checkLanePosition(pos, 0, lane->getParentEdge()->getNBEdge()->getFinalLength(), friendlyPos)) { @@ -753,9 +763,10 @@ GNEAdditionalHandler::buildLaneCalibrator(const CommonXMLStructure::SumoBaseObje // get routeProbe GNEAdditional* routeProbe = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ROUTEPROBE, routeprobeID, false); // check conditions - if (!checkValidAdditionalID(GNE_TAG_CALIBRATOR_LANE, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::calibrators, id); + if (!checkElement(GNE_TAG_CALIBRATOR_LANE, element)) { return false; - } else if (!checkDuplicatedAdditional(GNE_TAG_CALIBRATOR_LANE, {SUMO_TAG_CALIBRATOR, GNE_TAG_CALIBRATOR_LANE}, id)) { + } else if (!checkValidDemandElementID(GNE_TAG_CALIBRATOR_LANE, id)) { return false; } else if ((routeprobeID.size() > 0) && (routeProbe == nullptr)) { return writeErrorInvalidParent(GNE_TAG_CALIBRATOR_LANE, id, SUMO_TAG_ROUTEPROBE, routeprobeID); @@ -808,9 +819,10 @@ GNEAdditionalHandler::buildEdgeCalibrator(const CommonXMLStructure::SumoBaseObje // get routeProbe GNEAdditional* routeProbe = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ROUTEPROBE, routeprobeID, false); // check conditions - if (!checkValidAdditionalID(SUMO_TAG_CALIBRATOR, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::calibrators, id); + if (!checkElement(SUMO_TAG_CALIBRATOR, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_CALIBRATOR, {SUMO_TAG_CALIBRATOR, GNE_TAG_CALIBRATOR_LANE}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_CALIBRATOR, id)) { return false; } else if ((routeprobeID.size() > 0) && (routeProbe == nullptr)) { return writeErrorInvalidParent(SUMO_TAG_CALIBRATOR, id, SUMO_TAG_ROUTEPROBE, routeprobeID); @@ -893,7 +905,10 @@ GNEAdditionalHandler::buildRerouter(const CommonXMLStructure::SumoBaseObject* su const bool off, const bool optional, const SUMOTime timeThreshold, const std::vector& vTypes, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_REROUTER, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_REROUTER}, id); + if (!checkElement(SUMO_TAG_REROUTER, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_REROUTER, id)) { return false; } else if (!checkNegative(SUMO_TAG_REROUTER, id, SUMO_ATTR_PROB, prob, true)) { return false; @@ -901,8 +916,6 @@ GNEAdditionalHandler::buildRerouter(const CommonXMLStructure::SumoBaseObject* su return false; } else if (!checkListOfVehicleTypes(SUMO_TAG_REROUTER, id, vTypes)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_REROUTER, {SUMO_TAG_REROUTER}, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -1138,9 +1151,10 @@ GNEAdditionalHandler::buildRouteProbe(const CommonXMLStructure::SumoBaseObject* const std::string& name, const std::string& file, const SUMOTime begin, const std::vector& vTypes, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_ROUTEPROBE, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_ROUTEPROBE}, id); + if (!checkElement(SUMO_TAG_ROUTEPROBE, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_ROUTEPROBE, {SUMO_TAG_ROUTEPROBE}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_ROUTEPROBE, id)) { return false; } else { // get netedit parameters @@ -1182,10 +1196,11 @@ GNEAdditionalHandler::buildRouteProbe(const CommonXMLStructure::SumoBaseObject* bool GNEAdditionalHandler::buildVariableSpeedSign(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const Position& pos, const std::vector& laneIDs, const std::string& name, const std::vector& vTypes, const Parameterised::Map& parameters) { - /// check conditions - if (!checkValidAdditionalID(SUMO_TAG_VSS, id)) { + // check conditions + const auto element = retrieveAdditionalElement({SUMO_TAG_VSS}, id); + if (!checkElement(SUMO_TAG_VSS, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_VSS, {SUMO_TAG_VSS}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_VSS, id)) { return false; } else { // get netedit parameters @@ -1264,9 +1279,10 @@ bool GNEAdditionalHandler::buildVaporizer(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& edgeID, const SUMOTime beginTime, const SUMOTime endTime, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_VAPORIZER, edgeID)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_VAPORIZER}, edgeID); + if (!checkElement(SUMO_TAG_VAPORIZER, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_VAPORIZER, {SUMO_TAG_VAPORIZER}, edgeID)) { + } else if (!checkValidDemandElementID(SUMO_TAG_VAPORIZER, edgeID)) { return false; } else { // get netedit parameters @@ -1336,9 +1352,10 @@ GNEAdditionalHandler::buildTAZ(const CommonXMLStructure::SumoBaseObject* sumoBas TAZShape = TAZBoundary.getShape(true); } // check TAZ - if (!checkValidAdditionalID(SUMO_TAG_TAZ, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_TAZ}, id); + if (!checkElement(SUMO_TAG_TAZ, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_TAZ, NamespaceIDs::polygons, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_TAZ, id)) { return false; } else if (TAZShape.size() == 0) { return writeError(TLF("Could not build TAZ with ID '%' in netedit; Invalid Shape.", id)); @@ -1496,14 +1513,15 @@ bool GNEAdditionalHandler::buildTractionSubstation(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const Position& pos, const double voltage, const double currentLimit, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_TRACTION_SUBSTATION, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_TRACTION_SUBSTATION}, id); + if (!checkElement(SUMO_TAG_TRACTION_SUBSTATION, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_TRACTION_SUBSTATION, id)) { return false; } else if (!checkNegative(SUMO_TAG_TRACTION_SUBSTATION, id, SUMO_ATTR_VOLTAGE, voltage, true)) { return false; } else if (!checkNegative(SUMO_TAG_TRACTION_SUBSTATION, id, SUMO_ATTR_CURRENTLIMIT, currentLimit, true)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_TRACTION_SUBSTATION, {SUMO_TAG_TRACTION_SUBSTATION}, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -1528,9 +1546,10 @@ GNEAdditionalHandler::buildOverheadWire(const CommonXMLStructure::SumoBaseObject const std::vector& laneIDs, const double startPos, const double endPos, const bool friendlyPos, const std::vector& forbiddenInnerLanes, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_OVERHEAD_WIRE_SECTION, id)) { + const auto element = retrieveAdditionalElement({SUMO_TAG_OVERHEAD_WIRE_SECTION}, id); + if (!checkElement(SUMO_TAG_OVERHEAD_WIRE_SECTION, element)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_OVERHEAD_WIRE_SECTION, {SUMO_TAG_OVERHEAD_WIRE_SECTION}, id)) { + } else if (!checkValidDemandElementID(SUMO_TAG_OVERHEAD_WIRE_SECTION, id)) { return false; } else { // get netedit parameters @@ -1592,28 +1611,30 @@ GNEAdditionalHandler::buildPolygon(const CommonXMLStructure::SumoBaseObject* sum return buildJpsWalkableArea(sumoBaseObject, id, shape, geo, name, parameters); } else if (type == "jupedsim.obstacle") { return buildJpsObstacle(sumoBaseObject, id, shape, geo, name, parameters); - } else if (!checkValidAdditionalID(SUMO_TAG_POLY, id)) { - return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_POLY, NamespaceIDs::polygons, id)) { - return false; - } else if (!checkNegative(SUMO_TAG_POLY, id, SUMO_ATTR_LINEWIDTH, lineWidth, true)) { - return false; } else { - // get netedit parameters - NeteditParameters neteditParameters(sumoBaseObject); - // create poly - GNEPoly* poly = new GNEPoly(myNet, id, type, shape, geo, fill, lineWidth, color, layer, angle, imgFile, relativePath, name, parameters); - // add it depending of allow undoRed - if (myAllowUndoRedo) { - myNet->getViewNet()->getUndoList()->begin(poly, TL("add polygon '") + id + "'"); - myNet->getViewNet()->getUndoList()->add(new GNEChange_Additional(poly, true), true); - myNet->getViewNet()->getUndoList()->end(); + // check conditions + const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id); + if (!checkElement(SUMO_TAG_POLY, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_POLY, id)) { + return false; } else { - // insert shape without allowing undo/redo - myNet->getAttributeCarriers()->insertAdditional(poly); - poly->incRef("addPolygon"); + // get netedit parameters + NeteditParameters neteditParameters(sumoBaseObject); + // create poly + GNEPoly* poly = new GNEPoly(myNet, id, type, shape, geo, fill, lineWidth, color, layer, angle, imgFile, relativePath, name, parameters); + // add it depending of allow undoRed + if (myAllowUndoRedo) { + myNet->getViewNet()->getUndoList()->begin(poly, TL("add polygon '") + id + "'"); + myNet->getViewNet()->getUndoList()->add(new GNEChange_Additional(poly, true), true); + myNet->getViewNet()->getUndoList()->end(); + } else { + // insert shape without allowing undo/redo + myNet->getAttributeCarriers()->insertAdditional(poly); + poly->incRef("addPolygon"); + } + return true; } - return true; } } @@ -1624,7 +1645,10 @@ GNEAdditionalHandler::buildPOI(const CommonXMLStructure::SumoBaseObject* sumoBas const std::string& imgFile, bool relativePath, double width, double height, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(SUMO_TAG_POI, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id); + if (!checkElement(SUMO_TAG_POI, element)) { + return false; + } else if (!checkValidDemandElementID(SUMO_TAG_POI, id)) { return false; } else if (!checkNegative(SUMO_TAG_POI, id, SUMO_ATTR_WIDTH, width, true)) { return false; @@ -1632,8 +1656,6 @@ GNEAdditionalHandler::buildPOI(const CommonXMLStructure::SumoBaseObject* sumoBas return false; } else if (!checkFileName(SUMO_TAG_POI, id, SUMO_ATTR_IMGFILE, imgFile)) { return false; - } else if (!checkDuplicatedAdditional(SUMO_TAG_POI, NamespaceIDs::POIs, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -1660,7 +1682,10 @@ GNEAdditionalHandler::buildPOILane(const CommonXMLStructure::SumoBaseObject* sum const std::string& icon, double layer, double angle, const std::string& imgFile, bool relativePath, double width, double height, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(GNE_TAG_POILANE, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id); + if (!checkElement(GNE_TAG_POILANE, element)) { + return false; + } else if (!checkValidDemandElementID(GNE_TAG_POILANE, id)) { return false; } else if (!checkNegative(GNE_TAG_POILANE, id, SUMO_ATTR_WIDTH, width, true)) { return false; @@ -1668,8 +1693,6 @@ GNEAdditionalHandler::buildPOILane(const CommonXMLStructure::SumoBaseObject* sum return false; } else if (!checkFileName(GNE_TAG_POILANE, id, SUMO_ATTR_IMGFILE, imgFile)) { return false; - } else if (!checkDuplicatedAdditional(GNE_TAG_POILANE, NamespaceIDs::POIs, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -1707,7 +1730,10 @@ GNEAdditionalHandler::buildPOIGeo(const CommonXMLStructure::SumoBaseObject* sumo double angle, const std::string& imgFile, bool relativePath, double width, double height, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(GNE_TAG_POIGEO, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::POIs, id); + if (!checkElement(GNE_TAG_POIGEO, element)) { + return false; + } else if (!checkValidDemandElementID(GNE_TAG_POIGEO, id)) { return false; } else if (!checkNegative(GNE_TAG_POIGEO, id, SUMO_ATTR_WIDTH, width, true)) { return false; @@ -1717,8 +1743,6 @@ GNEAdditionalHandler::buildPOIGeo(const CommonXMLStructure::SumoBaseObject* sumo return false; } else if (GeoConvHelper::getFinal().getProjString() == "!") { return writeError(TLF("Could not build POI with ID '%' in netedit", id) + std::string("; ") + TL("Network requires a geo projection.")); - } else if (!checkDuplicatedAdditional(GNE_TAG_POIGEO, NamespaceIDs::POIs, id)) { - return false; } else { // get netedit parameters NeteditParameters neteditParameters(sumoBaseObject); @@ -1743,9 +1767,10 @@ bool GNEAdditionalHandler::buildJpsWalkableArea(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const PositionVector& shape, bool geo, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(GNE_TAG_JPS_WALKABLEAREA, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id); + if (!checkElement(GNE_TAG_JPS_WALKABLEAREA, element)) { return false; - } else if (!checkDuplicatedAdditional(GNE_TAG_JPS_WALKABLEAREA, NamespaceIDs::polygons, id)) { + } else if (!checkValidDemandElementID(GNE_TAG_JPS_WALKABLEAREA, id)) { return false; } else { // get netedit parameters @@ -1771,9 +1796,10 @@ bool GNEAdditionalHandler::buildJpsObstacle(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, const PositionVector& shape, bool geo, const std::string& name, const Parameterised::Map& parameters) { // check conditions - if (!checkValidAdditionalID(GNE_TAG_JPS_OBSTACLE, id)) { + const auto element = retrieveAdditionalElement(NamespaceIDs::polygons, id); + if (!checkElement(GNE_TAG_JPS_OBSTACLE, element)) { return false; - } else if (!checkDuplicatedAdditional(GNE_TAG_JPS_OBSTACLE, NamespaceIDs::polygons, id)) { + } else if (!checkValidDemandElementID(GNE_TAG_JPS_OBSTACLE, id)) { return false; } else { // get netedit parameters @@ -2057,26 +2083,35 @@ GNEAdditionalHandler::parseLanes(const SumoXMLTag tag, const std::string& id, co } +GNEAdditional* +GNEAdditionalHandler::retrieveAdditionalElement(const std::vector tags, const std::string& id) { + for (const auto& tag : tags) { + // retrieve additional element + auto additionalElement = myNet->getAttributeCarriers()->retrieveAdditional(tag, id, false); + if (additionalElement) { + return additionalElement; + } + } + return nullptr; +} + + bool -GNEAdditionalHandler::checkDuplicatedAdditional(const SumoXMLTag tag, const std::vector tags, const std::string& id) { - for (const auto& tagChecked : tags) { - // retrieve additional - auto additional = myNet->getAttributeCarriers()->retrieveAdditional(tagChecked, id, false); - // if additional exist, check if overwrite (delete) - if (additional) { - if (!myAllowUndoRedo) { - // only overwrite if allow undo-redo - return writeWarningDuplicated(tag, id, tagChecked); - } else if (myOverwrite) { - // delete additional (and all of their childrens) - myNet->deleteAdditional(additional, myNet->getViewNet()->getUndoList()); - } else { - // duplicated additional - return writeWarningDuplicated(tag, id, tagChecked); - } +GNEAdditionalHandler::checkElement(const SumoXMLTag tag, GNEAdditional* additionalElement) { + if (additionalElement) { + if (myAllowUndoRedo && myOverwrite) { + writeWarningOverwritting(tag, additionalElement->getID()); + // delete element + myNet->deleteAdditional(additionalElement, myNet->getViewNet()->getUndoList()); + // continue creating new element + return true; + } else { + // write warning duplicated additional element + return writeWarningDuplicated(tag, additionalElement->getID(), additionalElement->getTagProperty().getTag()); } + } else { + return true; } - return true; } diff --git a/src/netedit/elements/additional/GNEAdditionalHandler.h b/src/netedit/elements/additional/GNEAdditionalHandler.h index 27843bec880..daccdbd475d 100644 --- a/src/netedit/elements/additional/GNEAdditionalHandler.h +++ b/src/netedit/elements/additional/GNEAdditionalHandler.h @@ -699,13 +699,16 @@ class GNEAdditionalHandler : public AdditionalHandler { GNEAdditional* getRerouterIntervalParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const; /// @brief parse edges - std::vector parseEdges(const SumoXMLTag tag, const std::string &id, const std::vector& edgeIDs); + std::vector parseEdges(const SumoXMLTag tag, const std::string& id, const std::vector& edgeIDs); /// @brief parse lanes - std::vector parseLanes(const SumoXMLTag tag, const std::string &id, const std::vector& laneIDs); + std::vector parseLanes(const SumoXMLTag tag, const std::string& id, const std::vector& laneIDs); - /// @brief check if given ID correspond to a duplicated additional - bool checkDuplicatedAdditional(const SumoXMLTag tag, const std::vector tags, const std::string& id); + /// @brief get element by ID + GNEAdditional* retrieveAdditionalElement(const std::vector tags, const std::string& id); + + /// @brief check if element exist, and if overwritte + bool checkElement(const SumoXMLTag tag, GNEAdditional* additional); /// @brief struct for Netedit parameters struct NeteditParameters { diff --git a/src/netedit/elements/demand/GNERouteHandler.cpp b/src/netedit/elements/demand/GNERouteHandler.cpp index 31a53957919..30358fcf8b6 100644 --- a/src/netedit/elements/demand/GNERouteHandler.cpp +++ b/src/netedit/elements/demand/GNERouteHandler.cpp @@ -2630,7 +2630,7 @@ GNERouteHandler::checkElement(const SumoXMLTag tag, GNEDemandElement* demandElem // continue creating new element return true; } else { - // write errorduplicated demand element + // write warning duplicated demand element return writeWarningDuplicated(tag, demandElement->getID(), demandElement->getTagProperty().getTag()); } } else {