diff --git a/crdesigner/common/config/config_base.py b/crdesigner/common/config/config_base.py index 9f151b80..6f093562 100644 --- a/crdesigner/common/config/config_base.py +++ b/crdesigner/common/config/config_base.py @@ -4,7 +4,15 @@ import yaml from PyQt6.QtCore import QObject, pyqtSignal -from PyQt6.QtWidgets import QMessageBox + +try: + # required for Ubuntu 20.04 since there a system library is too old for pyqt6 and the import fails + # when not importing this, one can still use the map conversion + from PyQt6.QtWidgets import QMessageBox + + pyqt_available = True +except (ImportError, RuntimeError): + pyqt_available = False from crdesigner.ui.gui.utilities.custom_yaml import add_custom_interval_interpreter @@ -136,15 +144,16 @@ def restore_last_value(self): self.value = copy.deepcopy(self.last_saved) def _warning_wrong_setting(self): - warning_dialog = QMessageBox() - warning_dialog.warning( - None, - "Warning", - f"Setting {self.display_name} contains invalid value!", - QMessageBox.StandardButton.Ok, - QMessageBox.StandardButton.Ok, - ) - warning_dialog.close() + if pyqt_available: + warning_dialog = QMessageBox() + warning_dialog.warning( + None, + "Warning", + f"Setting {self.display_name} contains invalid value!", + QMessageBox.StandardButton.Ok, + QMessageBox.StandardButton.Ok, + ) + warning_dialog.close() self.reset() diff --git a/crdesigner/common/sumo_available.py b/crdesigner/common/sumo_available.py new file mode 100644 index 00000000..82a2671a --- /dev/null +++ b/crdesigner/common/sumo_available.py @@ -0,0 +1,17 @@ +from crdesigner.common import logging + +try: + from sumocr.interface.sumo_simulation import SumoSimulation # noqa: F401 + + from crdesigner.map_conversion.sumo_map.config import SumoConfig # noqa: F401 + from crdesigner.map_conversion.sumo_map.cr2sumo.converter import ( # noqa: F401 + CR2SumoMapConverter, + ) + + SUMO_AVAILABLE = True +except ImportError: + logging.warning( + "Cannot import SUMO. SUMO simulation will not be offered in Scenario Designer GUI. " + "The GUI and other map conversions should work." + ) + SUMO_AVAILABLE = False diff --git a/crdesigner/map_conversion/map_conversion_interface.py b/crdesigner/map_conversion/map_conversion_interface.py index 2d40a222..2613dbf8 100644 --- a/crdesigner/map_conversion/map_conversion_interface.py +++ b/crdesigner/map_conversion/map_conversion_interface.py @@ -12,12 +12,12 @@ from crdesigner.common.config.lanelet2_config import lanelet2_config from crdesigner.common.config.opendrive_config import open_drive_config from crdesigner.common.file_reader import CRDesignerFileReader +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.map_conversion.lanelet2.cr2lanelet import CR2LaneletConverter from crdesigner.map_conversion.lanelet2.lanelet2_parser import Lanelet2Parser from crdesigner.map_conversion.lanelet2.lanelet2cr import Lanelet2CRConverter from crdesigner.map_conversion.opendrive.opendrive_conversion.network import Network from crdesigner.map_conversion.opendrive.opendrive_parser.parser import parse_opendrive -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE if SUMO_AVAILABLE: from crdesigner.map_conversion.sumo_map.config import SumoConfig diff --git a/crdesigner/map_conversion/sumo_map/sumo2cr.py b/crdesigner/map_conversion/sumo_map/sumo2cr.py index cd7ba56d..ece319c6 100644 --- a/crdesigner/map_conversion/sumo_map/sumo2cr.py +++ b/crdesigner/map_conversion/sumo_map/sumo2cr.py @@ -3,7 +3,15 @@ from commonroad.scenario.scenario import Scenario from lxml import etree -from PyQt6.QtWidgets import QMessageBox + +try: + # required for Ubuntu 20.04 since there a system library is too old for pyqt6 and the import fails + # when not importing this, one can still use the map conversion + from PyQt6.QtWidgets import QMessageBox + + pyqt_available = True +except (ImportError, RuntimeError): + pyqt_available = False from crdesigner.map_conversion.opendrive.opendrive_conversion.network import Network from crdesigner.map_conversion.opendrive.opendrive_parser.parser import parse_opendrive @@ -18,8 +26,8 @@ def convert_net_to_cr(net_file: str, verbose: bool = False) -> Scenario: :return: commonroad map file """ - if net_file is None: - QMessageBox.warning(None, "Warning", "No file selected.", QMessageBox.Ok) + if net_file is None and pyqt_available: + QMessageBox.warning(None, "Warning", "No file selected.", QMessageBox.StandardButton.Ok) return assert isinstance(net_file, str) diff --git a/crdesigner/ui/gui/controller/animated_viewer/animated_viewer_controller.py b/crdesigner/ui/gui/controller/animated_viewer/animated_viewer_controller.py index 7ea2a802..59378c64 100644 --- a/crdesigner/ui/gui/controller/animated_viewer/animated_viewer_controller.py +++ b/crdesigner/ui/gui/controller/animated_viewer/animated_viewer_controller.py @@ -6,11 +6,11 @@ from PyQt6.QtWidgets import QFileDialog, QMessageBox from crdesigner.common.config.gui_config import gui_config +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.ui.gui.controller.animated_viewer.dynamic_canvas_controller import ( DynamicCanvasController, ) from crdesigner.ui.gui.model.planning_problem_set_model import PlanningProblemSetModel -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE from crdesigner.ui.gui.utilities.helper import draw_lanelet_polygon if SUMO_AVAILABLE: diff --git a/crdesigner/ui/gui/controller/mwindow_controller.py b/crdesigner/ui/gui/controller/mwindow_controller.py index 2101a179..bfef2c03 100644 --- a/crdesigner/ui/gui/controller/mwindow_controller.py +++ b/crdesigner/ui/gui/controller/mwindow_controller.py @@ -8,6 +8,7 @@ from crdesigner.common.config.gui_config import gui_config from crdesigner.common.logging import logger +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.ui.gui.autosaves.autosaves_setup import DIR_AUTOSAVE from crdesigner.ui.gui.controller.animated_viewer.animated_viewer_wrapper_controller import ( AnimatedViewerWrapperController, @@ -32,7 +33,6 @@ from crdesigner.ui.gui.model.planning_problem_set_model import PlanningProblemSetModel from crdesigner.ui.gui.model.scenario_model import ScenarioModel from crdesigner.ui.gui.utilities.file_actions import open_commonroad_file -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE from crdesigner.ui.gui.utilities.util import ( find_invalid_lanelet_polygons, find_invalid_ref_of_traffic_lights, diff --git a/crdesigner/ui/gui/controller/toolboxes/converter_toolbox/map_conversion_controller.py b/crdesigner/ui/gui/controller/toolboxes/converter_toolbox/map_conversion_controller.py index 316780cd..c1c9adfb 100644 --- a/crdesigner/ui/gui/controller/toolboxes/converter_toolbox/map_conversion_controller.py +++ b/crdesigner/ui/gui/controller/toolboxes/converter_toolbox/map_conversion_controller.py @@ -8,6 +8,7 @@ from crdesigner.common.config.osm_config import osm_config from crdesigner.common.logging import logger +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.map_conversion.lanelet2.cr2lanelet import CR2LaneletConverter from crdesigner.map_conversion.lanelet2.lanelet2_parser import Lanelet2Parser from crdesigner.map_conversion.lanelet2.lanelet2cr import Lanelet2CRConverter @@ -27,7 +28,6 @@ download_around_map, ) from crdesigner.ui.gui.model.scenario_model import ScenarioModel -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE from crdesigner.ui.gui.utilities.util import select_local_file from crdesigner.ui.gui.utilities.waitingspinnerwidget import QtWaitingSpinner from crdesigner.ui.gui.view.toolboxes.converter_toolbox.converter_toolbox_ui import ( diff --git a/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/aerial_image_controller.py b/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/aerial_image_controller.py index aed5e985..15e26fd2 100644 --- a/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/aerial_image_controller.py +++ b/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/aerial_image_controller.py @@ -5,7 +5,15 @@ from commonroad.scenario.scenario import Scenario from pyproj import CRS, Transformer from PyQt6.QtCore import Q_ARG, QMetaObject, QRunnable, Qt, QThreadPool -from PyQt6.QtWidgets import QMessageBox + +try: + # required for Ubuntu 20.04 since there a system library is too old for pyqt6 and the import fails + # when not importing this, one can still use the map conversion + from PyQt6.QtWidgets import QMessageBox + + pyqt_available = True +except (ImportError, RuntimeError): + pyqt_available = False from crdesigner.common.config.gui_config import gui_config as config_settings from crdesigner.common.config.gui_config import lanelet2_default @@ -149,7 +157,7 @@ def show_aerial_image(self, current_position: bool = False): return if self.road_network_toolbox_ui.bing_selection.isChecked(): - if config_settings.BING_MAPS_KEY == "": + if config_settings.BING_MAPS_KEY == "" and pyqt_available: print("_Warning__: No Bing Maps key specified. Go to settings and set password.") warning_dialog = QMessageBox() warning_dialog.warning( diff --git a/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/traffic_lights_controller.py b/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/traffic_lights_controller.py index 46651eb1..b1a8736e 100644 --- a/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/traffic_lights_controller.py +++ b/crdesigner/ui/gui/controller/toolboxes/road_network_toolbox/traffic_lights_controller.py @@ -10,8 +10,8 @@ ) from crdesigner.common.logging import logger +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.ui.gui.model.scenario_model import ScenarioModel -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE from crdesigner.ui.gui.view.toolboxes.road_network_toolbox.road_network_toolbox_ui.road_network_toolbox_ui import ( RoadNetworkToolboxUI, ) diff --git a/crdesigner/ui/gui/utilities/errors.py b/crdesigner/ui/gui/utilities/errors.py index 57900099..6f917056 100644 --- a/crdesigner/ui/gui/utilities/errors.py +++ b/crdesigner/ui/gui/utilities/errors.py @@ -1,28 +1,31 @@ -""" """ +try: + # required for Ubuntu 20.04 since there a system library is too old for pyqt6 and the import fails + # when not importing this, one can still use the map conversion + from PyQt6.QtWidgets import QMessageBox, QWidget -from PyQt6.QtWidgets import QMessageBox, QWidget + pyqt_available = True + def _message( + widget: QWidget, + title: str, + text: str, + buttons=QMessageBox.StandardButton.Ok, + default_button=QMessageBox.StandardButton.Ok, + ) -> QMessageBox.StandardButton: + messagebox = QMessageBox() + reply = messagebox.warning(widget, title, text, buttons, default_button) + messagebox.close() + return reply -def _message( - widget: QWidget, - title: str, - text: str, - buttons=QMessageBox.StandardButton.Ok, - default_button=QMessageBox.StandardButton.Ok, -) -> QMessageBox.StandardButton: - messagebox = QMessageBox() - reply = messagebox.warning(widget, title, text, buttons, default_button) - messagebox.close() - return reply + def error( + widget: QWidget, text: str, buttons=QMessageBox.StandardButton.Ok, default_button=QMessageBox.StandardButton.Ok + ) -> QMessageBox.StandardButton: + return _message(widget, "Error", text, buttons, default_button) + def warning( + widget: QWidget, text: str, buttons=QMessageBox.StandardButton.Ok, default_button=QMessageBox.StandardButton.Ok + ) -> QMessageBox.StandardButton: + return _message(widget, "Warning", text, buttons, default_button) -def error( - widget: QWidget, text: str, buttons=QMessageBox.StandardButton.Ok, default_button=QMessageBox.StandardButton.Ok -) -> QMessageBox.StandardButton: - return _message(widget, "Error", text, buttons, default_button) - - -def warning( - widget: QWidget, text: str, buttons=QMessageBox.StandardButton.Ok, default_button=QMessageBox.StandardButton.Ok -) -> QMessageBox.StandardButton: - return _message(widget, "Warning", text, buttons, default_button) +except (ImportError, RuntimeError): + pyqt_available = False diff --git a/crdesigner/ui/gui/utilities/gui_sumo_simulation.py b/crdesigner/ui/gui/utilities/gui_sumo_simulation.py index 806a34c4..af31a9c8 100644 --- a/crdesigner/ui/gui/utilities/gui_sumo_simulation.py +++ b/crdesigner/ui/gui/utilities/gui_sumo_simulation.py @@ -3,24 +3,15 @@ from commonroad.scenario.scenario import Scenario +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.ui.gui.utilities.errors import error from crdesigner.ui.gui.utilities.util import Observable -# try to import sumo functionality -try: +if SUMO_AVAILABLE: from sumocr.interface.sumo_simulation import SumoSimulation - from crdesigner.map_conversion.sumo_map.config import SumoConfig from crdesigner.map_conversion.sumo_map.cr2sumo.converter import CR2SumoMapConverter - SUMO_AVAILABLE = True -except ImportError: - logging.warning( - "Cannot import SUMO. SUMO simulation will not be offered in Scenario Designer GUI. " - "The GUI and other map conversions should work." - ) - SUMO_AVAILABLE = False - from PyQt6 import QtWidgets from PyQt6.QtCore import QThread from PyQt6.QtWidgets import QFrame, QMessageBox diff --git a/crdesigner/ui/gui/utilities/sumo_settings.py b/crdesigner/ui/gui/utilities/sumo_settings.py index 2984f4d1..ce559a50 100644 --- a/crdesigner/ui/gui/utilities/sumo_settings.py +++ b/crdesigner/ui/gui/utilities/sumo_settings.py @@ -1,6 +1,14 @@ from commonroad.common.util import Interval from commonroad.scenario.obstacle import ObstacleType -from PyQt6.QtWidgets import QMessageBox + +try: + # required for Ubuntu 20.04 since there a system library is too old for pyqt6 and the import fails + # when not importing this, one can still use the map conversion + from PyQt6.QtWidgets import QMessageBox + + pyqt_available = True +except (ImportError, RuntimeError): + pyqt_available = False from crdesigner.map_conversion.sumo_map.config import SumoConfig from crdesigner.ui.gui.utilities.util import Observable @@ -162,5 +170,6 @@ def restore_defaults(self): self.update_ui_values() def warn(self, msg): - messbox = QMessageBox() - messbox.warning(None, "Warning", msg, QMessageBox.Ok, QMessageBox.Ok) + if pyqt_available: + messbox = QMessageBox() + messbox.warning(None, "Warning", msg, QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) diff --git a/crdesigner/ui/gui/view/mwindow_ui.py b/crdesigner/ui/gui/view/mwindow_ui.py index deb8487d..f80fbb10 100644 --- a/crdesigner/ui/gui/view/mwindow_ui.py +++ b/crdesigner/ui/gui/view/mwindow_ui.py @@ -6,8 +6,8 @@ from PyQt6.QtWidgets import QApplication, QMainWindow, QMessageBox from crdesigner.common.config.gui_config import ColorSchema, gui_config +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.ui.gui.resources.MainWindow import Ui_mainWindow -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE if SUMO_AVAILABLE: pass diff --git a/tutorials/conversion_examples/example_commonroad_to_sumo.py b/tutorials/conversion_examples/example_commonroad_to_sumo.py index cff0e11e..62e719d4 100644 --- a/tutorials/conversion_examples/example_commonroad_to_sumo.py +++ b/tutorials/conversion_examples/example_commonroad_to_sumo.py @@ -7,8 +7,8 @@ from crdesigner.common.file_reader import CRDesignerFileReader from crdesigner.common.file_writer import CRDesignerFileWriter, OverwriteExistingFile +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.map_conversion.map_conversion_interface import commonroad_to_sumo -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE if SUMO_AVAILABLE: from sumocr.interface.sumo_simulation import SumoSimulation diff --git a/tutorials/conversion_examples/example_sumo_to_commonroad.py b/tutorials/conversion_examples/example_sumo_to_commonroad.py index 2d46da8b..4ee13c8b 100644 --- a/tutorials/conversion_examples/example_sumo_to_commonroad.py +++ b/tutorials/conversion_examples/example_sumo_to_commonroad.py @@ -4,8 +4,8 @@ from commonroad.scenario.scenario import Tag from crdesigner.common.file_writer import CRDesignerFileWriter, OverwriteExistingFile +from crdesigner.common.sumo_available import SUMO_AVAILABLE from crdesigner.map_conversion.map_conversion_interface import sumo_to_commonroad -from crdesigner.ui.gui.utilities.gui_sumo_simulation import SUMO_AVAILABLE if SUMO_AVAILABLE: from crdesigner.map_conversion.sumo_map.sumo2cr import convert_net_to_cr