diff --git a/README.md b/README.md index 2c7e327c..d48e55a2 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Please see Software dependencies --------------------- -PyQt5 which is either part of the Linux distribution or installable from +PyQt6 which is either part of the Linux distribution or installable from PyPi. The other Python dependencies are automatically installed during the GNS3 GUI installation and are listed [here](https://github.com/GNS3/gns3-gui/blob/master/requirements.txt) diff --git a/gns3/application.py b/gns3/application.py index d43c6ffe..edca7da7 100644 --- a/gns3/application.py +++ b/gns3/application.py @@ -29,22 +29,9 @@ log = logging.getLogger(__name__) class Application(QtWidgets.QApplication): file_open_signal = QtCore.Signal(str) - def __init__(self, argv, hdpi=True): + def __init__(self, argv): self.setStyle(QtWidgets.QStyleFactory.create("Fusion")) - #TODO: clean high DPI sclaling - # both Qt and PyQt must be version >= 5.6 in order to enable high DPI scaling - # if parse_version(QtCore.QT_VERSION_STR) >= parse_version("5.6") and parse_version(QtCore.PYQT_VERSION_STR) >= parse_version("5.6"): - # # only available starting Qt version 5.6 - # if hdpi: - # if sys.platform.startswith("linux"): - # log.warning("HDPI mode is enabled. HDPI support on Linux is not fully stable and GNS3 may crash depending of your version of Linux. To disabled HDPI mode please edit ~/.config/GNS3/gns3_gui.conf and set 'hdpi' to 'false'") - # self.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) - # self.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps) - # else: - # log.info("HDPI mode is disabled") - # self.setAttribute(QtCore.Qt.AA_DisableHighDpiScaling) - super().__init__(argv) # this is tell Wayland what is the name of the desktop file (gns3.desktop) @@ -61,7 +48,7 @@ class Application(QtWidgets.QApplication): self.open_file_at_startup = None def event(self, event): - # When you double click file you receive an event + # When you double click on a file, you receive an event # and not the file as command line parameter if sys.platform.startswith("darwin"): if isinstance(event, QtGui.QFileOpenEvent): diff --git a/gns3/dialogs/preferences_dialog.py b/gns3/dialogs/preferences_dialog.py index 307377f4..886bf7fb 100644 --- a/gns3/dialogs/preferences_dialog.py +++ b/gns3/dialogs/preferences_dialog.py @@ -19,7 +19,7 @@ Dialog to load module and built-in preference pages. """ -from ..qt import QtCore, QtWidgets +from ..qt import QtGui, QtCore, QtWidgets from ..ui.preferences_dialog_ui import Ui_PreferencesDialog from ..pages.server_preferences_page import ServerPreferencesPage from ..pages.general_preferences_page import GeneralPreferencesPage @@ -49,8 +49,9 @@ class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog): # We adapt the max size to the screen resolution # We need to manually do that otherwise on small screen the windows # could be bigger than the screen instead of displaying scrollbars - height = QtWidgets.QDesktopWidget().screenGeometry().height() - 100 - width = QtWidgets.QDesktopWidget().screenGeometry().width() - 100 + geometry = QtGui.QGuiApplication.primaryScreen().geometry() + height = geometry.height() - 100 + width = geometry.width() - 100 # 980 is the default width if self.width() > width: @@ -73,7 +74,7 @@ class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog): # set the maximum width based on the content of column 0 self.uiTreeWidget.setMaximumWidth(self.uiTreeWidget.sizeHintForColumn(0) + 10) - # Something has change? + # Something has changed? self._modified_pages = set() def _loadPreferencePages(self): diff --git a/gns3/graphics_view.py b/gns3/graphics_view.py index 3434bb84..82ea67f2 100644 --- a/gns3/graphics_view.py +++ b/gns3/graphics_view.py @@ -540,7 +540,7 @@ class GraphicsView(QtWidgets.QGraphicsView): if item and not sip.isdeleted(item): # Prevent right clicking on a selected item from de-selecting all other items if not item.isSelected(): - if not event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier: + if not (event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier): for it in self.scene().items(): it.setSelected(False) item.setSelected(True) @@ -566,12 +566,12 @@ class GraphicsView(QtWidgets.QGraphicsView): # If the left mouse button is not still pressed TOGETHER with the SHIFT key and neither is the middle button # this means the user is no longer trying to drag the view - if self._dragging and not (event.buttons() == QtCore.Qt.MouseButton.LeftButton and event.modifiers() == QtCore.Qt.KeyboardModifier.ShiftModifier) and not event.buttons() & QtCore.Qt.MouseButton.MiddleButton: + if self._dragging and not (event.buttons() == QtCore.Qt.MouseButton.LeftButton and event.modifiers() == QtCore.Qt.KeyboardModifier.ShiftModifier) and not (event.buttons() & QtCore.Qt.MouseButton.MiddleButton): self._dragging = False self.setCursor(QtCore.Qt.CursorShape.ArrowCursor) else: item = self.itemAt(event.position().toPoint()) - if item is not None and not event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier: + if item is not None and not (event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier): item.setSelected(True) super().mouseReleaseEvent(event) @@ -1648,15 +1648,15 @@ class GraphicsView(QtWidgets.QGraphicsView): def createDrawingItem(self, type, x, y, z, locked=False, rotation=0, svg=None, drawing_id=None): if type == "ellipse": - item = EllipseItem(pos=QtCore.QPoint(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = EllipseItem(pos=QtCore.QPointF(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "rect": - item = RectangleItem(pos=QtCore.QPoint(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = RectangleItem(pos=QtCore.QPointF(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "line": - item = LineItem(pos=QtCore.QPoint(x, y), dst=QtCore.QPoint(200, 0), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = LineItem(pos=QtCore.QPointF(x, y), dst=QtCore.QPoint(200, 0), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "image": - item = ImageItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = ImageItem(pos=QtCore.QPointF(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "text": - item = TextItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = TextItem(pos=QtCore.QPointF(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) if drawing_id is None: item.create() diff --git a/gns3/items/drawing_item.py b/gns3/items/drawing_item.py index 3ef65f72..88acbb0b 100644 --- a/gns3/items/drawing_item.py +++ b/gns3/items/drawing_item.py @@ -108,7 +108,7 @@ class DrawingItem: if error: log.error("Error while updating drawing: {}".format(result["message"])) return False - self.setPos(QtCore.QPoint(result["x"], result["y"])) + self.setPos(QtCore.QPointF(result["x"], result["y"])) self.setZValue(result["z"]) self.setLocked(result["locked"]) self.setRotation(result["rotation"]) diff --git a/gns3/items/ethernet_link_item.py b/gns3/items/ethernet_link_item.py index 2bb4bdc0..a62a3945 100644 --- a/gns3/items/ethernet_link_item.py +++ b/gns3/items/ethernet_link_item.py @@ -154,7 +154,7 @@ class EthernetLinkItem(LinkItem): self._source_port.setLabel(source_port_label) if self._draw_port_labels: - source_port_label.setFlag(source_port_label.ItemIsMovable, not self._source_item.locked()) + source_port_label.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, not self._source_item.locked()) source_port_label.show() else: source_port_label.hide() @@ -197,7 +197,7 @@ class EthernetLinkItem(LinkItem): self._destination_port.setLabel(destination_port_label) if self._draw_port_labels: - destination_port_label.setFlag(destination_port_label.ItemIsMovable, not self._destination_item.locked()) + destination_port_label.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, not self._destination_item.locked()) destination_port_label.show() else: destination_port_label.hide() diff --git a/gns3/items/serial_link_item.py b/gns3/items/serial_link_item.py index fe959476..edbbbdc8 100644 --- a/gns3/items/serial_link_item.py +++ b/gns3/items/serial_link_item.py @@ -142,7 +142,7 @@ class SerialLinkItem(LinkItem): self._source_port.setLabel(source_port_label) if self._draw_port_labels: - source_port_label.setFlag(source_port_label.ItemIsMovable, not self._source_item.locked()) + source_port_label.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, not self._source_item.locked()) source_port_label.show() else: source_port_label.hide() @@ -174,7 +174,7 @@ class SerialLinkItem(LinkItem): self._destination_port.setLabel(destination_port_label) if self._draw_port_labels: - destination_port_label.setFlag(destination_port_label.ItemIsMovable, not self._destination_item.locked()) + destination_port_label.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, not self._destination_item.locked()) destination_port_label.show() else: destination_port_label.hide() diff --git a/gns3/items/shape_item.py b/gns3/items/shape_item.py index 7f719f39..3e212aff 100644 --- a/gns3/items/shape_item.py +++ b/gns3/items/shape_item.py @@ -61,7 +61,7 @@ class ShapeItem(DrawingItem): """ self.update() - self._originally_movable = self.flags() & QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable + self._originally_movable = bool(self.flags() & QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable) if event.pos().x() > (self.rect().right() - self._border): self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, False) self._edge = "right" diff --git a/gns3/local_config.py b/gns3/local_config.py index fe9d0041..b84b2c45 100644 --- a/gns3/local_config.py +++ b/gns3/local_config.py @@ -394,14 +394,6 @@ class LocalConfig(QtCore.QObject): from gns3.settings import GENERAL_SETTINGS return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["experimental_features"] - def hdpi(self): - """ - :returns: Boolean. True if hdpi is allowed - """ - - from gns3.settings import GENERAL_SETTINGS - return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["hdpi"] - def multiProfiles(self): """ :returns: Boolean. True if multi_profiles is enabled diff --git a/gns3/main.py b/gns3/main.py index 5f425266..ee549dde 100644 --- a/gns3/main.py +++ b/gns3/main.py @@ -234,7 +234,7 @@ def main(): local_config = LocalConfig.instance() global app - app = Application(sys.argv, hdpi=local_config.hdpi()) + app = Application(sys.argv) if local_config.multiProfiles() and not options.profile: profile_select = ProfileSelectDialog() diff --git a/gns3/main_window.py b/gns3/main_window.py index bf7f58e8..cc1ab81f 100644 --- a/gns3/main_window.py +++ b/gns3/main_window.py @@ -1137,7 +1137,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): if self.uiAddLinkAction.isChecked() and key == QtCore.Qt.Key.Key_Escape: self.uiAddLinkAction.setChecked(False) self._addLinkActionSlot() - elif key == QtCore.Qt.Key.Key_C and event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier: + elif key == QtCore.Qt.Key.Key_C and (event.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier): status_bar_message = self.uiStatusBar.currentMessage() if status_bar_message: QtWidgets.QApplication.clipboard().setText(status_bar_message) diff --git a/gns3/pages/general_preferences_page.py b/gns3/pages/general_preferences_page.py index 3552c776..cc72f99b 100644 --- a/gns3/pages/general_preferences_page.py +++ b/gns3/pages/general_preferences_page.py @@ -305,7 +305,6 @@ class GeneralPreferencesPage(QtWidgets.QWidget, Ui_GeneralPreferencesPageWidget) self.uiCrashReportCheckBox.setChecked(local_server["report_errors"]) self.uiCheckForUpdateCheckBox.setChecked(settings["check_for_update"]) self.uiExperimentalFeaturesCheckBox.setChecked(settings["experimental_features"]) - self.uiHdpiCheckBox.setChecked(settings["hdpi"]) self.uiTelnetConsoleCommandLineEdit.setText(settings["telnet_console_command"]) self.uiTelnetConsoleCommandLineEdit.setCursorPosition(0) @@ -403,7 +402,6 @@ class GeneralPreferencesPage(QtWidgets.QWidget, Ui_GeneralPreferencesPageWidget) "style": self.uiStyleComboBox.currentText(), "symbol_theme": self.uiSymbolThemeComboBox.currentText(), "experimental_features": self.uiExperimentalFeaturesCheckBox.isChecked(), - "hdpi": self.uiHdpiCheckBox.isChecked(), "check_for_update": self.uiCheckForUpdateCheckBox.isChecked(), "overlay_notifications": self.uiOverlayNotificationsCheckBox.isChecked(), "telnet_console_command": self.uiTelnetConsoleCommandLineEdit.text(), diff --git a/gns3/qt/__init__.py b/gns3/qt/__init__.py index 0d59cf1c..628989cc 100644 --- a/gns3/qt/__init__.py +++ b/gns3/qt/__init__.py @@ -91,25 +91,56 @@ class QFileDialog(OldFileDialog): return path @staticmethod - def getOpenFileName(parent=None, caption='', directory='', filter='', selectedFilter='', options=OldFileDialog.options): - path, _ = OldFileDialog.getOpenFileName(parent, caption, directory, filter, selectedFilter, options) + def getOpenFileName(parent=None, caption='', directory='', filter='', initialFilter='', options=None): + + if options is None: + options = OldFileDialog.Option(0) + path, selected_filter = OldFileDialog.getOpenFileName( + parent=parent, + caption=caption, + directory=directory, + filter=filter, + initialFilter=initialFilter, + options=options + ) if path: path = os.path.normpath(path) - return path, _ + return path, selected_filter + @staticmethod - def getOpenFileNames(parent=None, caption='', directory='', filter='', selectedFilter='', options=OldFileDialog.options): - path, _ = OldFileDialog.getOpenFileNames(parent, caption, directory, filter, selectedFilter, options) - if path: - path = os.path.normpath(path) - return path, _ + def getOpenFileNames(parent=None, caption='', directory='', filter='', initialFilter='', options=None): + + if options is None: + options = OldFileDialog.Option(0) + paths, selected_filter = OldFileDialog.getOpenFileNames( + parent=parent, + caption=caption, + directory=directory, + filter=filter, + initialFilter=initialFilter, + options=options + ) + paths = [os.path.normpath(path) for path in paths] + return paths, selected_filter @staticmethod - def getSaveFileName(parent=None, caption='', directory='', filter='', selectedFilter='', options=OldFileDialog.options): - path, _ = OldFileDialog.getSaveFileName(parent, caption, directory, filter, selectedFilter, options) + def getSaveFileName(parent=None, caption='', directory='', filter='', initialFilter='', options=None): + + if options is None: + options = OldFileDialog.Option(0) + path, selected_filter = OldFileDialog.getSaveFileName( + parent=parent, + caption=caption, + directory=directory, + filter=filter, + initialFilter=initialFilter, + options=options + ) if path: path = os.path.normpath(path) - return path, _ + return path, selected_filter + QtWidgets.QFileDialog = QFileDialog diff --git a/gns3/settings.py b/gns3/settings.py index eebfd470..4ef3b8a0 100644 --- a/gns3/settings.py +++ b/gns3/settings.py @@ -303,7 +303,6 @@ GENERAL_SETTINGS = { #"preferences_dialog_geometry": "", "debug_level": 0, "multi_profiles": False, - "hdpi": not sys.platform.startswith("linux"), "direct_file_upload": False, "symbol_theme": "Classic" } diff --git a/gns3/ui/general_preferences_page.ui b/gns3/ui/general_preferences_page.ui index b7226e3d..4eabbc4f 100755 --- a/gns3/ui/general_preferences_page.ui +++ b/gns3/ui/general_preferences_page.ui @@ -6,7 +6,7 @@ 0 0 - 512 + 556 652 @@ -1016,13 +1016,6 @@ - - - - Enable HDPI mode (this may crash on Linux, restart required) - - - @@ -1126,7 +1119,6 @@ uiCrashReportCheckBox uiOverlayNotificationsCheckBox uiExperimentalFeaturesCheckBox - uiHdpiCheckBox uiMultiProfilesCheckBox uiDirectFileUpload uiRestoreDefaultsPushButton diff --git a/gns3/ui/general_preferences_page_ui.py b/gns3/ui/general_preferences_page_ui.py index c18eb28d..6aec0bb6 100644 --- a/gns3/ui/general_preferences_page_ui.py +++ b/gns3/ui/general_preferences_page_ui.py @@ -12,7 +12,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets class Ui_GeneralPreferencesPageWidget(object): def setupUi(self, GeneralPreferencesPageWidget): GeneralPreferencesPageWidget.setObjectName("GeneralPreferencesPageWidget") - GeneralPreferencesPageWidget.resize(512, 652) + GeneralPreferencesPageWidget.resize(556, 652) self.verticalLayout = QtWidgets.QVBoxLayout(GeneralPreferencesPageWidget) self.verticalLayout.setObjectName("verticalLayout") self.uiMiscTabWidget = QtWidgets.QTabWidget(parent=GeneralPreferencesPageWidget) @@ -451,9 +451,6 @@ class Ui_GeneralPreferencesPageWidget(object): self.uiExperimentalFeaturesCheckBox = QtWidgets.QCheckBox(parent=self.uiMiscTab) self.uiExperimentalFeaturesCheckBox.setObjectName("uiExperimentalFeaturesCheckBox") self.verticalLayout_2.addWidget(self.uiExperimentalFeaturesCheckBox) - self.uiHdpiCheckBox = QtWidgets.QCheckBox(parent=self.uiMiscTab) - self.uiHdpiCheckBox.setObjectName("uiHdpiCheckBox") - self.verticalLayout_2.addWidget(self.uiHdpiCheckBox) self.uiMultiProfilesCheckBox = QtWidgets.QCheckBox(parent=self.uiMiscTab) self.uiMultiProfilesCheckBox.setObjectName("uiMultiProfilesCheckBox") self.verticalLayout_2.addWidget(self.uiMultiProfilesCheckBox) @@ -517,8 +514,7 @@ class Ui_GeneralPreferencesPageWidget(object): GeneralPreferencesPageWidget.setTabOrder(self.uiCheckForUpdateCheckBox, self.uiCrashReportCheckBox) GeneralPreferencesPageWidget.setTabOrder(self.uiCrashReportCheckBox, self.uiOverlayNotificationsCheckBox) GeneralPreferencesPageWidget.setTabOrder(self.uiOverlayNotificationsCheckBox, self.uiExperimentalFeaturesCheckBox) - GeneralPreferencesPageWidget.setTabOrder(self.uiExperimentalFeaturesCheckBox, self.uiHdpiCheckBox) - GeneralPreferencesPageWidget.setTabOrder(self.uiHdpiCheckBox, self.uiMultiProfilesCheckBox) + GeneralPreferencesPageWidget.setTabOrder(self.uiExperimentalFeaturesCheckBox, self.uiMultiProfilesCheckBox) GeneralPreferencesPageWidget.setTabOrder(self.uiMultiProfilesCheckBox, self.uiDirectFileUpload) GeneralPreferencesPageWidget.setTabOrder(self.uiDirectFileUpload, self.uiRestoreDefaultsPushButton) GeneralPreferencesPageWidget.setTabOrder(self.uiRestoreDefaultsPushButton, self.uiMiscTabWidget) @@ -597,7 +593,6 @@ class Ui_GeneralPreferencesPageWidget(object): self.uiCrashReportCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Send anonymous crash reports")) self.uiOverlayNotificationsCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Display error, warning and info in an overlay popup")) self.uiExperimentalFeaturesCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Enable experimental features")) - self.uiHdpiCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Enable HDPI mode (this may crash on Linux, restart required)")) self.uiMultiProfilesCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Request for profile settings at application startup")) self.uiDirectFileUpload.setToolTip(_translate("GeneralPreferencesPageWidget", "Experimental, requires computes visibility from GUI network")) self.uiDirectFileUpload.setText(_translate("GeneralPreferencesPageWidget", "Upload files directly to computes (experimental)")) diff --git a/gns3/ui/main_window_ui.py b/gns3/ui/main_window_ui.py index ddcc9925..5f43400c 100644 --- a/gns3/ui/main_window_ui.py +++ b/gns3/ui/main_window_ui.py @@ -738,4 +738,4 @@ from ..nodes_dock_widget import NodesDockWidget from ..nodes_view import NodesView from ..status_bar import StatusBar from ..topology_summary_view import TopologySummaryView -from . import resources_rc +from . import resources_rc \ No newline at end of file diff --git a/gns3/ui/resources_rc.py b/gns3/ui/resources_rc.py index 50059419..0ee64008 100644 --- a/gns3/ui/resources_rc.py +++ b/gns3/ui/resources_rc.py @@ -73899,347 +73899,6 @@ L\xc2XCGL\xff!4p\xa5\x22u\xdbA\xfb\ \xb3SO\xef\xeb\xd0\x82\x0b\xaa2BP,p!n\ \xd2\xeb\x0f\xe0\xc9n\xbe\x94\x83\xf5+4N\xb4_.\ >\x0c\x84\xef\x0a\ -\x00\x00\x15&\ -(\ -\xb5/\xfd`Pf\xe5\xa8\x00\x0a\xef\x9c$,\xe0n\ -\x86\xd3\x063\xc3\xebT\xbe\xf8\xd7\xd9\xe8,\xd0j\xe0\ -\x02h\xf2\x99o\xec\x05\x5c\xac\xdf\xdd\xdd\xbd\xb9\x12Y\ -g5D5\x18c,b\x10B\x85\x02|\x02\x15\x02\ -\xdc\x89u\x98\xaa\x9buv|z\x9d\x1a\x96D\xe3\xae\ -{\x1b\xd3\xb7\xb2.\x99\xda\xa5\xea\xbd\x9f\x9a\xb8\xbe\x96\ -[wg\xaa\xfb\x97\xdd=o\xb8\x8a\xbdi\x09\x0d\x8d\ -\x0d9a\xe1&?\xfd\x16\xb1\x96S\xdf\xb4\xde\xe0x\ -\x99\xe7\xed\xc3'Stjj'We\xa7b\xce?\ -\xe1\x15\x17b\xfa\x99_\xc7\x99Z\x93\xcd\xd2\x1dK\x8d\ -\xdf`\xc5\xd8\xc0\xc8m\xc54\x1a\x0d\x86\x06\x97\x16j\ -\xeb\xea2\x0c\xd3\x8c\xf1o\xadO1\x8f\xf7\xfb\xff\xc2\ -\x9fo\x17\x1atk\x1d\xa7+\xeal\x5c\xc9\x16\x85e\ -i\xb3b\xd3\x92\xe9\xfd\x8d\xc9l7\xf7Rm\x0d\xbb\ --\xad\x9d\xbe\xbfI_\x8d\x06[}C\xaf\xea+7\ -/\x8b\xad\xd1\xc9\x9cu-\xd9\x8a\xd1J\xa6\x98G\xcb\ -\xbe\xed\xdde\xb0\x88\xba\xa9K/\xa1\x13i\x9bu\x0b\ -\x10L\xa2\xd7\xd2\xf7\x8c\xcf\x85LZY\x8c\xa7\xc9\x9a\ -m\xe9/\xd0\xea\xcd\xa4\xa1\xe1q`\x8c\x89\xc8y\x1c\ -Lh0\x0f\x06\x06\xf4,\x8f\x89H\xf2D\x13\xe5\xa3\ -\xa55\xa8\x81\x175\xe9D\x1fmS\x966\x1a`2\ -\xa7//\x8a\xbb\x9a)\xb4\xb6\xb5\x93\x95\xa2\xf9p7\ -}\x11@\xc2\x81\x22\x06\xb2\x00\x012\x890\x90\x04\xcd\ -d\x82\xc8\x03\x11@\xcd\x04\x22r\x22\x138\x5cei\ -%\xc40h\xa0\x07\xc6d\x82\x89x0\x8d\xe6\xf1x\ -\x1a\x09<\x18\xc7\xc1@\x0be\xa1W\x1d\x07\x07z\x96\ -\x0aUe\x13\x86W\x18\x8aD\x05\x92\x9b\x88\x1a\x8dD\ -\xc2\x93\x86\xc6\xf1 \xc2\x82MT*\xbc\xc4!\x11\x91\ -$|0\x11\x07\x025\xd1\xe2qX8\x1e\x0e\xc3\x22\ -\x9a\xd0X\xf0@\x92\xc5d\xd1@\x9e\x87E\xf3p\x1a\ -\x96\x08z$\x12Mj*h<\x8e\xfc\x9eA\x8a\xf5\ -/\x15C\xebl\x01\x82\xc3\x89\x1e\x1c\x9c\xe6AB\xc2\ -\xb8\x00\xe1!r,&M\x83\x91L\x1a\x08\x13qD\ -\x8eT\x8b\x04\x09$,\xa2&\x92\x9a\x86\xa6\x01A<\ -\x93$yH0\x16U\xf5E\x82\x89\x22\x13\x93e\xf9\ -\x17\xafEw\xdbE48 \x06\x93\xc8$\xf2@ \ -O\xa3\xa1\xe04\x1a\x0b\x0bK\xb6\x98D\x91\x06\xd2<\ -\x9aE\xc3\xf1\x80 $\x0b\x10\x1a\x0e\xc6$\xa2(\x0a\ -\x00\x0e\x14&\x0f\x00\x00 \xc2\xb2(\x0d\x16\x0e\xd0\x93\ -\x9c\x14\x11\x11\xb1X0$Q\xf4 \x80\xd2H\x98\xc6\ -dBD\x01\xe5!r\x22\x14G\x131\x0dt\x80\xb2\ -,\x01<\x00 \x02\x01\x0bOd\x01B\x13y\x1e\x8c\ -#\xc2D\x13e\x81\x17\x04$\x98`\x01\x82C\xc4q\ -<\x8dH\xa3,T\xb2\x05\x08\x91\xc7\x99@\x0d\x05\xe5\ -\x01\x91 \xe0A=\x91[k\xc9\x09\xa1\xbbL\xbb\xd3\ -W&\xbce\xbe\xbdRT;S\xecT\x0d\xea\x8e\x86\ -Bs\xfbm\xd3\x9e\x12\xd7\xf2X\x9dzK\xaf5;\ -\xa5\x82\x1e\xe6\xdd\xa2\xbc\xee\x9b\xe9p\xc9;\xb3\x82/\ -\xb7\x18S\xfd\x0aE\xe3MyS\x94+31v\x22\ -n\xd25\xac\xd4\xb4\xbf\x03\x14\xbeb\x85.\x9b\xa6\xb6\ -/J\x03\x9c\x95\x8d\x87\x88\x91D<\x8f\x06\xa8\xa1\xf0\ -8\x888\x0f\xc9\xc4q8h\x1e\x0f\x87\xc1\x998\x14\ -\x8a1\xc1@\x13\xc6\x81\x0c\xe7\x11i\x1c\x0e$\x82\x98\ -h\xb2@\xcd\x04\x88\x818\x80\x1aF\xc4y,pD\ -\x18\xc6h&<\x0e*D\x9e\x08\xa3y@@\x0d\xf6\ -\x020\x1a\x1c$\x9b\xd6\x0bo\x0d\xef\xf4\x8cm\xf3\x12\ -\xef=\x9f:%X[S\xe5D\xd4h\xa0\x06]\x86\ -\x97\xfa\x14\xad\x87\x96\x149W\xb9\xd2\xbf4\xdd\x88\x89\ -\xd1+\x1d\x1a\xc7\x03\x91@<\xa60\xb0\x00\xe1\xd10\ -0\x0f\x87\x09\xce\xa3\x80\x06b\x1e\x22\x98Pp\xa0&\ -* z\x1cp .h\xa0\x89#!\xf28Q\x03\ -\xc2\xf1@\x92\x06\x82Ebh\x22&\x91\x84\x01\xa8\x89\ -\x22P\x18 &0\x0b@08P\x14y\x1a\x8bJ\ -_0\x93e\x82a1\x99D\x9a\x86\xf2\x80\x804Q\ -\x04\xe7\xe1\xc0\x18\xd0h,`\x80\x98D\x9e\xc9\xe4\xe1\ -8\xa0\x14\xe0P\x00\xf4\xa4-eKV=B#A\ -\x84\xe6\x119\x0a<\x1eN\x14\xc1\xc2\x814\xd0\xe2\xc1\ -\x03\x221\x00\xc4\x89\x101\x8c\x86\x03\xe2a`&@\ -\x0f\x05\x8cF\x03\x01\x09\x100\x1a\x1c\xd0\x03c\x22\xc6\ -\xc1D\x0d\xe4AS\xc1\x818\x12\x0cd\xd28\x1c\x88\ -\xb3\xe7Zm\xdd\x12q\x22$$\x10\x10\x88\xc6\xe3\x80\ -\x80\xa2\x87\x81ai&\x0f\xa6\x01r\x88x\x1e&\xcd\ -\x04\xf3X \x08\x22\x151+\xf1\x1b-\x95-\x5c{\ -v\x90\xe7\xa9\x10\xf18\x98\x87I\x1d\xf2\x96\xb6)\xd4\ -8\xa0\x87\xa1\xa1q`$\x0cCD\xe3Pp\x1c \ -A\x82\x01|\x80\xdd\xe5\x1e\xb2\xd9ib|U\xba\xb4\ -;\xa64\xee\xefn\xea6\x07\xe4\xe00\xf6C\xe4\xea\ -\xdd\xdb\xda\xfb\xbd\xca2\xf5ii6^\xa2.\xa2\xfe\ -\xac5Sk.\xe2\xa6iw\xa7\xbdjKLz\xbb\ -\xc9v\xe9\x88w\x97O\x85m\x9bhKc\xcb\xfcJ\ -kXf\xd8\xcd\xc7\xb9\x8du\x87}\xe3\xb5\xa4\xd5x\ -\x8a\xd6Y\x8c\x95\xcc\xf4\x88y\xb4\xce\xac\xf3\xd3\xd0n\ -yQ+\xef\xbau\x9b\x1a/\x9f\x8c\xd8\xac\xa7\xa9\x8d\ -s\xf9\x10\xf9\x1a\xecs/\xf5\x15jK\xc3\xbc\xb6(\ -\x02jy\x85e\xf7\xed\xb6\x8cl\xa7\xd9\x5c\xd9\x89\xfc\ -+\x9b\xd2\xb8Z\xd5v5U\xddK\xcb\xdb]\x96\xaa\ -%Z\xa3a)\xef\xda\xbd\xbb\xb3^2\xc4\xdb\xea\xe5\ -\x8aY\xc5\xb6\xd8\xc5\xdc\x8aR\xb0\xd1,\xb1\x96\x86\xd3\ -\xf1\xa6\xda\xdd\xcfP\xaf\x98y\x0b\xb3W\x19\xeb\xa9\xb8\ -\x1brr\xb1j&\xe3\xde\xeal\x99\x8a\xabjg\xbb\ -\x0a3|(\x89\xbf\xe6\x17%\xb5,\xf37\xdcd\x8b\ -\xf2\xb7\xda6\xff|U\xe9\x14}X\x99\xa5\xb8M\xab\ -\x87r\xca\xdb\xdb\xd6j\xf7\xd4jS\xbcR\xbb\xe3=\ -\xd5\xa24\x94\xe4\xce\xe4T\xcc\x9b\xe9\xae@\xceu\x95\ -\x8d\xa6\x89\x0d\xc7\x80\xc1qM\xe3\x90\x98hT\x00-\ -\x14\x04\x111\x14 \x88\xc6\x02=\x91\xc8\xe2\xc1\xedO\ -$z\x10a!\x99\x9fO\x7fE\x18\x07b(<4\ -\xa2\x06b0\x0d\xa7\xc1i4\x92eq\x10\x01c\xe2\ -\xe1@\x98\x86\x88\x07\x03\x81\x1cHH\x0a\x19M\x05g\ -\xb2D\x91\xa7\xa1\x005\x93\x06j&\x8c\x07$\x92h\ -\xa2\xbc]C\x22\xdf\x80\x98\x85\x0a\x8a\xbdbJ^)\ - \xf1)\xb9\x9c\xf8\xf5\xa4\x8b\xa2\xaar/\xa1\x00M\ -\xc4<\xaa\xaey4 \xa7qx\xc8?'\xea\x1b\xd8\ -\x8ek\x06\xda\xf9\x97f\x16\xb6q\xde5Z\xa6\xbd\xd6\ -L\xc6\x94w\xda\xe9x[\x95\xafl\xb3\xb6\xb5\xb5\xdf\ -\xaeY\xaaD\xcb\xe2kbs'e\xc5\xb5+}\xe1\ -\x19\xdcn\xa9\xa6\xd9\xfeRabg-\xf6\xf6\xb1V\ -'\x1f\xf5{\x9d\x0c\xd9\xeeN\x8f\x8a\x1e\x95\x8f\xd8O\ -u\xe5\xcez3\xe1\x15\xabi\xc8\xe9\xde\x96G\xceV\ -\xdb\xceWj\xb6jK\xac\xb8\xb4\xac\xa4/{\x99\x82\ -\xf9\xf2\x9a6\x92\xe4oU\x93\x8fv\xd9\x8ae\xbd\xe9\ -\xd0lq3\x8f\x99\xe9\xcb\xb9gh\x89\x9d\x8e\xbf\x1f\ -\xd1\x1c\xe8\xf5\xf6\x14\xef\xce\xee\x5c\xdc\xbd\xcb\x9ay\x87\ -_{w-\xeff*\xea\x7f\x17\xe1\xd9\xb7\xac\xc1\xd8\ -\x18\xe4\xa6J\xb4>\x85\x01\xc5\xf4\xca\x14w\xf5\xb4J\ -\x9cx\xb6p6\xd6\xcc+\xff\x88\x95\xf6DM\xd6\x5c\ -{\xc6\xb4\xbc\xd7\xc6\x94\xff\xfd\x95\xfaY\xc5\x5ci\x0f\ -s7\x1b\xf5\x88\x15\x00Dp\xa00Y<8l\xae\ -N\xc5{\xeeO\xff\xf3\xa9\x82\xaf\x0fm\x13\x97\x13\xcb\ -\xaeXWk\x8f\x5cY\xddW\xe8\x97\xaf\xee\xecl\x9b\ -\xc7\xc5\xb6u\x5c\xab\x88v\xfaS\xcb\x172\xf3&\xdb\ --3n\x9f\x9b\xab\xda\xf8\xf7\xcc\xd2\xa7\x95\xe1V\xff\ -\x10S\xf9\x18\xad\xae\xd6\xc6z{\xe6;\xff\xf9<\xb7\ -}\xb7\xcd\x16\xed\x12\xcd8\xbb\xb1\xad\xd9\x14|\xf7u\ -+W\xe5\xa2\xea\xe5)\xb3&.gb\xd6\xadV-\ -\xb6\x22\xd9nW\xe6\xb2\xed;\x9b\xf2\xebh\xb6\xb6\xdc\ -w\xac\xc5LL\xa74c\xaa\x22\x96\xfe8\xcfv\xbe\ -^M\x0bu\xd1\x94DT\xd4\xfc;\xd1p\xf7\xf6\xb0\ -\x1b\xed\xfc\xf3)b\xdf\xe9\xb7\xed\xa6\xb7\xc4L\xe4\xad\ -\xc2\xe3\xd9\xd0l\xed\x95\xd6\xcd\xdb\xa6\xf7:\xf2s\x0d\ -\xb70\xf9\xb663Qy\x19_g\xbf\xaa\xca\xfa\xcf\ -\xec\xccj\xa7\xca\x96}\xc9\x8a\xdfd<\xcdg6&\ -\xde\xf2\xd8\xba\xf9\xbe{^>Kk;\xecB\xbc\xe3\ -\xd2lC\xb5\xac\xc4d\x8buO\xe6\xefwQS\xe5\ -\xed\xd5\xec[\x05\xfd*\x18s\xf5\xd1\xfa\xf0\xf2}\x95\ -\xa9\xa6\xd8\xa5\xa9\xd4\xb6\x5c\xbd\xf1\xa5kc\xc4\xfb\xad\ -\xa2\x9b\xb9 J\x054;\x5c\x1a\xec\xc4i\x88\xfd\xa7\ -\x99)\xde\x9b\xc5\xb6\xa6we}\xfcm\xdb,\x7f\xd7\ -we\xcb>^\xf1J\x15S>\xef:w\xb1\xfat\ -KO\xfb\x89\xcb\xbaz\xbb}\x8c\xa7\x89\xa9uKc\ -;\x05\xf1\xb8\x903\xd9=a\xe2\xed\xe9\xb7\xdc\xcc\xc7\ -\x8cW\xd6\xbd\xed\xab*.\xb3\xafM\xd3\xd0\xea\x96\xf7\ -m\xa6\x9c\xad\xec\xb6\xf4\xa5\x8bVYZ\xb9\xbd\xbf\xc5\ -\xec\xf3\x9d\xd3\x0awQ\x1b\xb9\x155\xefx\x85\xf3\x8a\ -\xaf/4\xbd\xb6\xe5S0\xeev.\xab\x1d\xf7\xf8\x9f\ -\xe9V:4L\xc3\xe3/\xf6\xd2\xf4\x222*\x8af\ -[\xbd\xcf\xba\xba>\xefX\xef\xdb\x9b\xc5\xc8]\xa6\xdc\ -\xa5\xd9\xcb\xfd\x85\x8f\xa8\x83\x16\xaa<\x12E\x19\xa4$\ -I\x92\x0c\x9b\x01\x03\xd3(\x142\x18\x0c\xe6\x83Ew\ ->\xa3c\xda(\x18\x0a\x22I\x8a\xc7\x18\x8aB\x08\xc2\ -\x0c!\x84 B\x88@Dd\x02\x22\x11\xb2\xe9 \xe0\ -(\xe8\xf5)\xf4%qeM\x0f=\xb4\x15G\x8c\x91\ -\xe2\xc5\x0d\x8f\xaa=\xb6_x\x91\x0a\xcb\xadJ\xe9\x98\ -W\x17K\x1b\x80\xa7\xb2\x90\x82+0Og\x18 \xbf\ -%U\xbf\xa7zS\x02\xb5\xed\xf4\xcb\xf6\xdd\xdc\xd8\xda\ -S\xab\xf9\x03\xbe\xd4+\xf2&\xd08|\xb1Ug'\ -\xd7\xde\xdb~\xb5[\xea\x9a3\x94\xaa\x00\x1d\x9fS\x1a\ -\xd0\xb2\x99\x93<\x03%\x13\xd9\xfc'\x95h\x0e\xd3\xee\ -\xc5Cy\xca\xa8\xee\xc4\x91.\x83\xf9X\x88hg\x14\ -\x7f|\xd1\x80\xc4\x96\xb9\x015|\xff\x5c\xa2\x11\xea\xe1\ -@\xb3F_\xaf\xd4\x22\xa6\xcba^\xf2\xa6\x9a\x18\x8f\ -\xa8w\xf61\x18}5\xb09@\xa2\xc3\x9d\xd6E\x10\ -\x10K&CA20-/G;:\xacV.\xcf\ -U\x9b\x9f\x05\xe9\x00\x0d\xd7\x14\x01\x82\x11\xe7q:M\ -\x91Lz\xfd\x0bW\xc2h\xfd\xc0\x5c\xce~\x1c\x85\xbc\ -\x15\x8d\xc7\x13t\x82P\xfa\x18\xe3\xa5\xacAd\x8f\xfc\ -_\xfc\x22h\xd3\x9d\xe14D\x1e\xfd}H&Q\x7f\ -|[\xa3\x1a:\x9d7\xca\x9d:Z;\xbc\xa9\xe6P\ -G\xe0\x02j\xf0/\xa9\x9a\x7f(EN\xf1\x95\xc7\xb2\ -S\xb1\x22\x8935\xa3\x92\xa6\x99\xff8\xd2\xe3\x05V\ -,\x14\xefyK\x9b\xff\x87~\x0f\xc9\x98\xe8YN\xaf\ -dc\xc0l\xf7\xec\xc0P=\x82\xd2b\xd4-\x01\xbc\ -\xfe\x1atcVE\xc8x\x03\x02=\xdc#\x95\xde\xa8\ -\xe3\x22\xa9\xb2mF\x13\x0a\xff\x87+\x5c\xc3s\x06\x03\ -\xc1\xe7\x8c\xbc\xa8\x19\x9f\xa7`\xf3@Rg*\xc3\xb0\ -\x0f\xdb\xbe\xe32\xb8\xba\xbcAG(\x96O\x02\xbd\xc1\ -\xed\x06{\x99\xca\x9a\x9c\xca\xa2\xd5\x9a\x80\xf1\xf4\xc01\ -\xff\xd9\x1d\xd8N.\x84\x82X\xbc=\x18\xdcoA\xfe\ -\xd2\xf5\xc0\xb3\x5c(\xb4\xa5*\x96R`o/Y\xe5\ -\xa5\xdf\x96 0\x17W\x9bm\xcc\x9c\x11\x01\x15.G\ -\x03\xe9r\x82\xf2\xbbb\xed>+%\xab\x92\x8c\xeb\xff\ -\xbb$\xcd\xd4e\x06\xf1\xd9\xd3V\x0c\xc6\xec\xe2\x02\x81\ -f\x0cM\xf3\xb8\x05\xae\xa2E\xd9\xc1\xffB\x09q\xea\ -8OL\xb7\xd5|\xf4\xb3i\x1c\x8e^\x98N\x11L\ -\xcf\xb9j\xb0dW\xb9\xa5\xfb!\x82 \x16fG\xb9\ -\xebk\xc6a\xd9\x03\x10\xf5\x97\x1d\xb6-I\x170m\ -\xd0\xaf}\xb5PM\xe8iU@\x05k2\x15Z\x08\ -\x8bDp\x8e\xa6\xe2\xfbC[\xb6P\x92Q\xef\x06E\ -X\xb7\xca;@\xf5\xdet\xeaXKd\xc8\x0c\x041\ -=\x83\xceVa<\xe2s\xa8\x0f\xbd)\xe7\x16U=\ -\xb3 \x10 \x8c\xbf\x8b\xbe\xca\x86cZ\x9avg\xdb\ -k'\x9b8\xc5V\xd9R\xd5\x8a\xbb\x94\xaa-\x14J\ -\xf7\x9a0-U\xee\x16eV\x04z|\xde\x17\xa0\x19\ -\xfb\x14\xe2\xf2f\xb9\x16\x8d\x89\xdc\x0c\xd4\x19\x18\xcb\x12\ -a\x9ca70:\x99\xe8N\x0fX\x9a\x94e\xc1B\ -6\x9b\xb5\x199`\x9c\x9asN\x9ff\xcb\xef?\x5c\ -J\x88\x15+\x8e\xe5\x1b\xdb\x92\x93R\xaa\x5c2eT\ -\x03\x03=[\x1e\xd4\xc6\x92\x91gE\x98\xb6Y\xe9]\ -\x91\xf2\x8b%'M\xe8j\x84\x5c\xd4\xebL\x0e\xea\xbd\ -\xd3\xe2\x90s\xb0j=\xf2)t\x98\xdb\xce\xbf\xfaH\ -\xc0\x9d\x82\xbe\xf3\x0c\xd2A\x1c>\x88$\xf9\x06a\x13\ -\x83!\xb8k\xbe\x85[\xac\xe2\x0bB@nN\xed-\ -\x11bC\x09\x14\x87\x1d3\x8c\xdf\xa1=\x02P\x00\xc1\ -\x22B\xa9\xfb[)~\xcf\xf9Pf\x1d\xd8p\xc1>\ -9!&\xf2d\x5c^\x9c\xb6\xf9\x7f\x94\x83o)D\ -\xe9A<\xceJ\x1b\x95(z\xbe>Lfl\xa6\x0a\ -\xa4S\xffB=Y\xa9b\xc8GB\xb4)c{\xb0\ -\x96\xe7\x5c\xfe\x03\xa0V\xdb-\xa7\xb3eg\x9f\xd5\x7f\ -g\xea%\xc4\xb1~\xa21\x94I?\x18>\xe4\x92\x8b\ -\xbd\xe3=W\xad \xa5\x80\xad\x09\x9d;\xcc\x9e\x98\xa0\ -\x1c\xcc\xfb\xd2\xa0\x8c_\xfd\xf5\x9f\xbc\xc69\xc7\xe2\x8e\ -\xa1E\x181aF\xe1u\xbd0N\x1a\x14nib\ -=\xfe\xf7Y\x1d\xc7\x1e\x1fi\x99;|s\xf6(\xae\ -\xbd\x94\x11\x87dK\xd3\xf7\x0a\xd6\x15\xc9\xfe\x7f\x17\x80\ -\x1bwz\xc2\xd7\xc87\x92\xb7\x08\x99k\x14\x9f\x90\xe8\ -z\x88\xb96\x0b\x1d\xc86\xff\xaf\x80\xd6f\x09+\x16\ -\x0d\xefxlV*s\xd3\xb2\x851\xd1\xab\x86di\ -\xe9\xdaz% \xf3\xd9h\xaa!N\x0c iD\xfa\ -Vh\xd4\xa5\xe2\xd3\xcd;\xf0\x0c\xb4\xd7[h\xf5\xaf\ -?ES\xe4\x92\xfb\xa7\xe34(=\x1b\xf3&\xd0p\ -\x17\xd5\x85\x82;\xccN\xa0\xe6\xdc\x01\x87\xe2U\x1c4\ -\xc6\xc62>\x87\xc7.\x19!\xe1DKM\xa6J\xaa\ -\x83H\x8a.\xe5S_b1\xc9\xfa\xae\xbc:\x1c\xae\ -2\xbe\x8bW@w\xbb\xb9\xce\x05\x9f\x95A\xe8\x1e\x1e\ -?\x82\x11t\x02.\x993\x13Z\xdfm\xdd0\x01\xf0\ -\x81\xa8\xb8\xba\x161\ -\x16\x9b`\x88A81\x9a%\x9c)\xa5\xd08,:\ -\x84\xd5]x\x8e\xf8x\x84@\xb8n\x88\x86\x22\xd0\xf0\ -\x93C\xca\x09\xe5[4\xc4\x94\xe8\xc51\xabj\x8e\x95\ -\xbba\xc0\x0c\xa0Vc\xdeB\x891\xc9\xe2\x05\xeaj\ -\xce\x9c;\x9a\xa6\x88\x94qT\xd1[yQ\xaa[\xb1\ - \x86\xa8\x9a\x1f;)x\x10_D%\xbd\xf7\xb4\xbd\ -\xc8\x9e'\xe8f\xb1\xa5\xa9b\x8a\xcd\xcf\x9a\x86\x1aR\ -\xbe \x07\x0b\xea\x85Q\xfdZ\x87\x0a\xfb\xe6\xebF\x84\ -\xa9\x22K1\xa2\xb8\x92B\xe7\x15\xa6\x17W{\xf1\xc2\ -}.}4nS\xed\x89\x93\x8e\x15\x80\xc1T\xcf\x09\ -\xa0{\x9c$\x88\xbe\xc0.\x12\x84(\x16\xfe\x00\x9b\xfa\ -\xe8\x22\x86@\xdc(~n?\x04']\x1c7\x82+\ -\xd6\xb4|\xc2\xd6`\xac\xee\xf5\xc8B\xc3V'\xa5\x0e\ -\xbe7\xe3\xe0q\x07v\x94\x02\x8a\xf6\xde\x19:lK\ -q\x82.\xac\xebK\x9f\xc3\xda\x0c\xff\x9aC\x1b\x0ck\ -u\xef\xba\xad\x22\xec\x11\xa3\x87j\xd3\xf6\xbc%\x82\xf0\ -\x87\xf5\xffh\x07\xd6\xb0\xee\xcd\xaf\x8dky\xc6{X\ -q\xf4\xd6\xeb\xb0\xaef\xbd\x15\xf1\xe7\x06y8\xeb4\ -\x92\xea\xfd\x00\x16\x19e\xa1\xd3\xfa\xb0\x19\x17Qs\x9e\ -\xb1\x15\xb7\x08\x80\xb5\x84\x12tXH\xdf\xaf\x0e\xa4W\ -\x06\x04T\xb10\xd9\xd1/}\xbe\xf9N\xc1\xf6\xcc\x09\ -\x13c\xfd\xcb\x9d<\xf1\xc0\xd0\xba$\x8b^\x13\x83\x95\ -*.\x0e%E^\xd4k\xd1\x94\x86>\x10\x84\x80\xca\ -\x81\x08\xcc\x1f\xa8\xc8\xc2I\xd0\x92\xde\xf2\x19[\x04\x92\ -Y\xe8\x9a\x014%\x91\xab\xaf7X\xa8\xf3\x00\xd5\x9f\ -\xa2\xb7\xfb!\x1e\xe3_W\x83\xe2\xb41\xfe\x15\xea\xc4\ -\x01\xeb\x10\x8a\x13'\x86\x06\xa20c\x86\xa8\x7f\x1c\x8f\ -\xcdq\xebC1\xf98(\x93\xe4,\xbfWB\x084\ -\x80\x08\x7f\x9a\x9el\x94E\x97\xcb\x1000[4\x16\ -\xe0ft\xde\x87U\xe0\xcf\xe9\x18\x12\x90\x02O\xfd \ -\xcc'N\x1d\x1eP)\xf0_T\xbd\x86\xdf\xc5B\x92\ -\xd2L\x87-47\xe5\xf5E\xf4\xb6\xacw\x98\xd8\xa2\ -\xff>\x02\x0a\xad\xe1F\xbc\x06n\xd7\xbc>p\x9e(\ -\xdd\xa2Y\xd6\xca\x96\x89iK=*\x9d\x16\xa8\x05y\ -\xa1\x5cN\xf1\xad\xcf$\x09cV\x01\x00Z\x15\xa2~\ -%\xb5\xeb\x84\x950\xee5\xd7\xddD\xa2\xbe\x16\xb37\ -\xb3\xfb;\x7f{\x1eL8\x17@\x17u\x01!\xc5\x8b\ -Q\xaa\x904C\x9c\xb3\x93\xef\xe1\x0c\x84\xef\x0a\ \x00\x01\x09\x97\ \x89\ PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ @@ -140063,7 +139722,7 @@ qt_resource_name = b"\ qt_resource_struct = b"\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00Y\x00\x00\x00\xf5\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00X\x00\x00\x00\xf5\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00V\x00\x02\x00\x00\x00\x04\x00\x00\x00\xf1\ \x00\x00\x00\x00\x00\x00\x00\x00\ @@ -140551,119 +140210,119 @@ qt_resource_struct = b"\ \x00\x00\x01\x89\xdf\x7f?h\ \x00\x00\x10\xa2\x00\x00\x00\x00\x00\x01\x00\x05\x11\x9c\ \x00\x00\x01\x89\xdf\x7f?h\ -\x00\x00\x0c\xf8\x00\x04\x00\x00\x00\x01\x00 \xb2\xf2\ +\x00\x00\x0c\xf8\x00\x04\x00\x00\x00\x01\x00 \x9d\xc8\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x08\x90\x00\x04\x00\x00\x00\x01\x00\x15\x0ar\ +\x00\x00\x08\x90\x00\x04\x00\x00\x00\x01\x00\x14\xf5H\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x17Z\x00\x04\x00\x00\x00\x01\x00 \xbf\x83\ +\x00\x00\x17Z\x00\x04\x00\x00\x00\x01\x00 \xaaY\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x15>\x00\x00\x00\x00\x00\x01\x00\x15+0\ +\x00\x00\x15>\x00\x00\x00\x00\x00\x01\x00\x15\x16\x06\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0a&\x00\x04\x00\x00\x00\x01\x00\x15\xbes\ +\x00\x00\x0a&\x00\x04\x00\x00\x00\x01\x00\x15\xa9I\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x14\xfe\x00\x04\x00\x00\x00\x01\x00\x14\x07\x0e\ +\x00\x00\x14\xfe\x00\x04\x00\x00\x00\x01\x00\x13\xf1\xe4\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x16\x08\x00\x00\x00\x00\x00\x01\x00\x1a\x90I\ +\x00\x00\x16\x08\x00\x00\x00\x00\x00\x01\x00\x1a{\x1f\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x13\xa2\x00\x00\x00\x00\x00\x01\x00\x0d\xdc\xaa\ \x00\x00\x01\x9b\x1b\xa0I\x8d\ \x00\x00\x05(\x00\x04\x00\x00\x00\x01\x00\x0fq\xdc\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x06\xea\x00\x04\x00\x00\x00\x01\x00\x13\xf5\xc2\ +\x00\x00\x06\xea\x00\x04\x00\x00\x00\x01\x00\x13\xe0\x98\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x07\x12\x00\x04\x00\x00\x00\x01\x00\x14\x0d:\ +\x00\x00\x07\x12\x00\x04\x00\x00\x00\x01\x00\x13\xf8\x10\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x07\x5c\x00\x04\x00\x00\x00\x01\x00\x14\x1d\x1e\ +\x00\x00\x07\x5c\x00\x04\x00\x00\x00\x01\x00\x14\x07\xf4\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x170\x00\x00\x00\x00\x00\x01\x00 \xa5~\ +\x00\x00\x170\x00\x00\x00\x00\x00\x01\x00 \x90T\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x04f\x00\x04\x00\x00\x00\x01\x00\x0f]J\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x15Z\x00\x04\x00\x00\x00\x01\x00\x15Qf\ +\x00\x00\x15Z\x00\x04\x00\x00\x00\x01\x00\x15<<\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0c\xa8\x00\x04\x00\x00\x00\x01\x00 \x9e\x1d\ +\x00\x00\x0c\xa8\x00\x04\x00\x00\x00\x01\x00 \x88\xf3\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x14:\x00\x00\x00\x00\x00\x01\x00\x0fD\xc2\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x17\x14\x00\x04\x00\x00\x00\x01\x00 \x88_\ +\x00\x00\x17\x14\x00\x04\x00\x00\x00\x01\x00 s5\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x15\x8a\x00\x00\x00\x00\x00\x01\x00\x15ca\ +\x00\x00\x15\x8a\x00\x00\x00\x00\x00\x01\x00\x15N7\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x10\x5c\x00\x04\x00\x00\x00\x01\x00!\xce\xc4\ +\x00\x00\x10\x5c\x00\x04\x00\x00\x00\x01\x00!\xb9\x9a\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x05l\x00\x04\x00\x00\x00\x01\x00\x10\x8e\x06\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x16T\x00\x04\x00\x00\x00\x01\x00\x1a\xd7\xbf\ +\x00\x00\x16T\x00\x04\x00\x00\x00\x01\x00\x1a\xc2\x95\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x03^\x00\x04\x00\x00\x00\x01\x00\x0e!n\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x16\xf4\x00\x00\x00\x00\x00\x01\x00 \x5c\xd1\ +\x00\x00\x16\xf4\x00\x00\x00\x00\x00\x01\x00 G\xa7\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x13\x8e\x00\x04\x00\x00\x00\x01\x00\x0d\xd0\x16\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0c\xd0\x00\x04\x00\x00\x00\x01\x00 \xab8\ +\x00\x00\x0c\xd0\x00\x04\x00\x00\x00\x01\x00 \x96\x0e\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x14\xd0\x00\x00\x00\x00\x00\x01\x00\x13\x040\ +\x00\x00\x14\xd0\x00\x00\x00\x00\x00\x01\x00\x12\xef\x06\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0d\xc2\x00\x04\x00\x00\x00\x01\x00!\x01t\ +\x00\x00\x0d\xc2\x00\x04\x00\x00\x00\x01\x00 \xecJ\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x09\xa0\x00\x04\x00\x00\x00\x01\x00\x15?\xef\ +\x00\x00\x09\xa0\x00\x04\x00\x00\x00\x01\x00\x15*\xc5\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x02\x1c\x00\x04\x00\x00\x00\x01\x00\x0d\xa9g\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0fl\x00\x00\x00\x00\x00\x01\x00!R[\ +\x00\x00\x0fl\x00\x00\x00\x00\x00\x01\x00!=1\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0c>\x00\x04\x00\x00\x00\x01\x00 dG\ +\x00\x00\x0c>\x00\x04\x00\x00\x00\x01\x00 O\x1d\ \x00\x00\x01\x9b\x1b\xa0I\x8e\ \x00\x00\x14p\x00\x00\x00\x00\x00\x01\x00\x10\xb2\x82\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x07\xfe\x00\x04\x00\x00\x00\x01\x00\x14.\xbe\ +\x00\x00\x07\xfe\x00\x04\x00\x00\x00\x01\x00\x14\x19\x94\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x00\xb4\x00\x04\x00\x00\x00\x01\x00\x0d{\x8c\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0f\xbe\x00\x04\x00\x00\x00\x01\x00!dc\ +\x00\x00\x0f\xbe\x00\x04\x00\x00\x00\x01\x00!O9\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x02\x94\x00\x04\x00\x00\x00\x01\x00\x0d\xf0\x97\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0cb\x00\x04\x00\x00\x00\x01\x00 u\x89\ +\x00\x00\x0cb\x00\x04\x00\x00\x00\x01\x00 `_\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x17\xca\x00\x04\x00\x00\x00\x01\x00 \xf9\x15\ +\x00\x00\x17\xca\x00\x04\x00\x00\x00\x01\x00 \xe3\xeb\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x17v\x00\x00\x00\x00\x00\x01\x00 \xd0\xeb\ +\x00\x00\x17v\x00\x00\x00\x00\x00\x01\x00 \xbb\xc1\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0f\xd8\x00\x04\x00\x00\x00\x01\x00!m\x0e\ +\x00\x00\x0f\xd8\x00\x04\x00\x00\x00\x01\x00!W\xe4\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x06:\x00\x04\x00\x00\x00\x01\x00\x11\xb7#\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0eD\x00\x04\x00\x00\x00\x01\x00!\x14\x0c\ +\x00\x00\x0eD\x00\x04\x00\x00\x00\x01\x00 \xfe\xe2\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x16v\x00\x00\x00\x00\x00\x01\x00\x1a\xdf\x9b\ +\x00\x00\x16v\x00\x00\x00\x00\x00\x01\x00\x1a\xcaq\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x14\xe2\x00\x04\x00\x00\x00\x01\x00\x13\xee\xc1\ +\x00\x00\x14\xe2\x00\x04\x00\x00\x00\x01\x00\x13\xd9\x97\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x162\x00\x00\x00\x00\x00\x01\x00\x1a\xa7\xa4\ +\x00\x00\x162\x00\x00\x00\x00\x00\x01\x00\x1a\x92z\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0f.\x00\x04\x00\x00\x00\x01\x00!3w\ +\x00\x00\x0f.\x00\x04\x00\x00\x00\x01\x00!\x1eM\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x18T\x00\x04\x00\x00\x00\x01\x00!\xb9\xba\ +\x00\x00\x18T\x00\x04\x00\x00\x00\x01\x00!\xa4\x90\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x01\xd2\x00\x04\x00\x00\x00\x01\x00\x0d\x8f\xc3\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x13\xec\x00\x00\x00\x00\x00\x01\x00\x0eH(\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x16\xa0\x00\x04\x00\x00\x00\x01\x00\x1b\xcf/\ +\x00\x00\x16\xa0\x00\x04\x00\x00\x00\x01\x00\x1b\xba\x05\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x13\xbc\x00\x00\x00\x00\x00\x01\x00\x0d\xf9A\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x05T\x00\x04\x00\x00\x00\x01\x00\x0f\x88\xf6\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x14\xaa\x00\x00\x00\x00\x00\x01\x00\x11\xfa\x95\ +\x00\x00\x14\xaa\x00\x00\x00\x00\x00\x01\x00\x11\xe5k\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0e\xc2\x00\x04\x00\x00\x00\x01\x00!$u\ +\x00\x00\x0e\xc2\x00\x04\x00\x00\x00\x01\x00!\x0fK\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x17\xe8\x00\x04\x00\x00\x00\x01\x00!\x0e&\ +\x00\x00\x17\xe8\x00\x04\x00\x00\x00\x01\x00 \xf8\xfc\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0b\x96\x00\x04\x00\x00\x00\x01\x00\x1b\xbfX\ +\x00\x00\x0b\x96\x00\x04\x00\x00\x00\x01\x00\x1b\xaa.\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x14V\x00\x00\x00\x00\x00\x01\x00\x0f\x90\xa1\ \x00\x00\x01\x89\xdf\x7f?d\ @@ -140671,35 +140330,33 @@ qt_resource_struct = b"\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x00\xec\x00\x04\x00\x00\x00\x01\x00\x0dp\xfb\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x15$\x00\x00\x00\x00\x00\x01\x00\x146\xf9\ +\x00\x00\x15$\x00\x00\x00\x00\x00\x01\x00\x14!\xcf\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x17\x94\x00\x04\x00\x00\x00\x01\x00 \xe8\xfc\ +\x00\x00\x17\x94\x00\x04\x00\x00\x00\x01\x00 \xd3\xd2\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x15\xde\x00\x04\x00\x00\x00\x01\x00\x1a\x807\ +\x00\x00\x15\xde\x00\x04\x00\x00\x00\x01\x00\x1ak\x0d\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x03.\x00\x04\x00\x00\x00\x01\x00\x0e08\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x09\xf4\x00\x04\x00\x00\x00\x01\x00\x15\xb0\xdb\ +\x00\x00\x09\xf4\x00\x04\x00\x00\x00\x01\x00\x15\x9b\xb1\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x06\x8a\x00\x04\x00\x00\x00\x01\x00\x11\xd0A\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x06\x8a\x00\x04\x00\x00\x00\x01\x00\x11\xe5k\ -\x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x09f\x00\x04\x00\x00\x00\x01\x00\x150\xea\ +\x00\x00\x09f\x00\x04\x00\x00\x00\x01\x00\x15\x1b\xc0\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x16\xba\x00\x00\x00\x00\x00\x01\x00\x1b\xeb\xcb\ +\x00\x00\x16\xba\x00\x00\x00\x00\x00\x01\x00\x1b\xd6\xa1\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0f\x9e\x00\x04\x00\x00\x00\x01\x00!A.\ +\x00\x00\x0f\x9e\x00\x04\x00\x00\x00\x01\x00!,\x04\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x15\xb0\x00\x00\x00\x00\x00\x01\x00\x15\xe2\x8c\ +\x00\x00\x15\xb0\x00\x00\x00\x00\x00\x01\x00\x15\xcdb\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0a\x10\x00\x04\x00\x00\x00\x01\x00\x15\xa2H\ +\x00\x00\x0a\x10\x00\x04\x00\x00\x00\x01\x00\x15\x8d\x1e\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0b\x08\x00\x04\x00\x00\x00\x01\x00\x1a\xc8\x84\ +\x00\x00\x0b\x08\x00\x04\x00\x00\x00\x01\x00\x1a\xb3Z\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x13x\x00\x04\x00\x00\x00\x01\x00\x0d\xb9.\ \x00\x00\x01\x9b\x1b\xa0I\x8f\ -\x00\x00\x0a\x5c\x00\x04\x00\x00\x00\x01\x00\x15\xd6\x0a\ +\x00\x00\x0a\x5c\x00\x04\x00\x00\x00\x01\x00\x15\xc0\xe0\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x02\xd0\x00\x04\x00\x00\x00\x01\x00\x0e\x05\xb5\ \x00\x00\x01\x9b\x1b\xa0I\x8e\ @@ -140709,25 +140366,25 @@ qt_resource_struct = b"\ \x00\x00\x01\x9b\x1b\xa0I\x8f\ \x00\x00\x14\x8e\x00\x04\x00\x00\x00\x01\x00\x11\xc5\xe1\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0b\xd0\x00\x04\x00\x00\x00\x01\x00\x1b\xd9\x8f\ +\x00\x00\x0b\xd0\x00\x04\x00\x00\x00\x01\x00\x1b\xc4e\ \x00\x00\x01\x89\xdf\x7f?`\ \x00\x00\x13Z\x00\x00\x00\x00\x00\x01\x00\x0c\x9f1\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x18*\x00\x04\x00\x00\x00\x01\x00!\xaa[\ +\x00\x00\x18*\x00\x04\x00\x00\x00\x01\x00!\x951\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x05\xf2\x00\x04\x00\x00\x00\x01\x00\x11\xa9Y\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x18\x0a\x00\x04\x00\x00\x00\x01\x00!\x8c\xc5\ +\x00\x00\x18\x0a\x00\x04\x00\x00\x00\x01\x00!w\x9b\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x0f\xf4\x00\x04\x00\x00\x00\x01\x00!{\xa8\ +\x00\x00\x0f\xf4\x00\x04\x00\x00\x00\x01\x00!f~\ \x00\x00\x01\x89\xdf\x7f?d\ \x00\x00\x05\x9e\x00\x04\x00\x00\x00\x01\x00\x10\xa4\xd0\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x09\x0e\x00\x04\x00\x00\x00\x01\x00\x15\x1a.\ +\x00\x00\x09\x0e\x00\x04\x00\x00\x00\x01\x00\x15\x05\x04\ \x00\x00\x01\x89\xdf\x7f?d\ -\x00\x00\x10\x18\x00\x04\x00\x00\x00\x01\x00!\x94\x89\ +\x00\x00\x10\x18\x00\x04\x00\x00\x00\x01\x00!\x7f_\ \x00\x00\x01\x89\xdf\x7f?`\ -\x00\x00\x0a\x82\x00\x04\x00\x00\x00\x01\x00\x1am\x80\ +\x00\x00\x0a\x82\x00\x04\x00\x00\x00\x01\x00\x1aXV\ \x00\x00\x01\x89\xdf\x7f?`\ " diff --git a/mac-requirements.txt b/mac-requirements.txt index b435bace..e809b3c5 100644 --- a/mac-requirements.txt +++ b/mac-requirements.txt @@ -1,3 +1,3 @@ -rrequirements.txt -PyQt5==5.15.11 +PyQt5==6.10.1 diff --git a/resources/resources.qrc b/resources/resources.qrc index de152599..8b93244f 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -24,7 +24,6 @@ icons/connection-new-hover.svg icons/console.svg icons/console_edit.svg - icons/command_line.svg icons/aux-console.svg icons/command_line.svg icons/delete.svg diff --git a/scripts/build_pyqt.py b/scripts/build_pyqt.py index 31626533..ddfff5fe 100755 --- a/scripts/build_pyqt.py +++ b/scripts/build_pyqt.py @@ -5,7 +5,7 @@ Script to build all the PyQt user interfaces and resources for this project. """ import os -import sys +import platform import stat import shutil import subprocess @@ -13,21 +13,11 @@ import argparse parser = argparse.ArgumentParser() parser.add_argument("--force", help="force rebuild all files", action="store_true") -parser.add_argument("--ressources", help="force rebuild resources", action="store_true") +parser.add_argument("--resources", help="force rebuild resources", action="store_true") args = parser.parse_args() -if sys.platform.startswith('win'): - PATH = os.path.join(os.path.dirname(sys.executable), "Lib\\site-packages\\PyQt5") - if os.access(os.path.join(PATH, "bin"), os.R_OK): - PATH = os.path.join(PATH, "bin") - PYUIC = os.path.join(PATH, "pyuic5") - PYRCC = os.path.join(PATH, "pyrcc5") - - if not os.path.exists(PYUIC): - PYUIC = "pyuic5.exe" -else: - PYUIC = shutil.which("pyuic5") - PYRCC = shutil.which("pyrcc5") +PYUIC = shutil.which("pyuic6") +PYRCC = shutil.which("pyside6-rcc") # Using PySide6's rcc as PyQt6's pyrcc6 does not exist def build_ui(path): @@ -36,36 +26,38 @@ def build_ui(path): if source.endswith(".ui"): target = os.path.join(path, file.replace(".ui", "_ui.py")) if not os.access(target, os.F_OK) or (os.stat(source)[stat.ST_MTIME] > os.stat(target)[stat.ST_MTIME]) or args.force: - command = [PYUIC, "--from-imports", "-o", target, source] + command = [PYUIC, "-o", target, source] print("Building UI {}".format(source)) if args.force and os.access(target, os.F_OK): os.remove(target) + subprocess.call(command) - if sys.platform.startswith('win'): - for i, arg in enumerate(command): - command[i] = '"' + arg.replace('"', '"""') + '"' - command = ' '.join(command) - subprocess.call(command, shell=True) - else: - subprocess.call(command) - + if target == os.path.join(path, "main_window_ui.py"): + # Patch the main_window_ui.py to import resources_rc + # could potentially use https://github.com/domarm-comat/pyqt6rc instead + print("Patching UI {} to import resources".format(target)) + with open(target, "a") as f: + f.write("from . import resources_rc") def build_resources(path, target): for file in os.listdir(path): source = os.path.join(path, file) if source.endswith(".qrc"): target = os.path.join(target, file.replace(".qrc", "_rc.py")) - if not os.access(target, os.F_OK) or (os.stat(source)[stat.ST_MTIME] > os.stat(target)[stat.ST_MTIME]) or args.force or args.ressources: - command = [PYRCC, "-compress", "9", "-o", target, source] + if not os.access(target, os.F_OK) or (os.stat(source)[stat.ST_MTIME] > os.stat(target)[stat.ST_MTIME]) or args.force or args.resources: + command = [PYRCC, "-o", target, source] print("Building resources {}".format(source)) if args.force and os.access(target, os.F_OK): os.remove(target) - if sys.platform.startswith('win'): - for i, arg in enumerate(command): - command[i] = '"' + arg.replace('"', '"""') + '"' - command = ' '.join(command) subprocess.call(command) + # patch the .py resource file to replace PySide6 by PyQt6 (as we used pyside6-rcc) + print("Patching resources {}".format(target)) + with open(target, "r") as f: + content = f.read() + content = content.replace("PySide6", "PyQt6") + with open(target, "w") as f: + f.write(content) def recursive(function, path): for root, dirs, _ in os.walk(path): @@ -75,8 +67,11 @@ def recursive(function, path): if __name__ == '__main__': + if platform.system() != "Linux": + raise SystemExit("This script can only be run on Linux.") + if not PYUIC or not PYRCC: - raise SystemExit("pyuic5 or pyrcc5 could't be found, please install PyQt5 development tools (e.g. pyqt5-dev-tools)") + raise SystemExit("pyuic6 or pyside6-rcc couldn't be found, please install PyQt6 development tools (e.g. pyqt6-dev-tools) and PySide6") cwd = os.path.dirname(os.path.abspath(__file__)) gns3_path = os.path.abspath(os.path.join(cwd, "../gns3/")) diff --git a/win-requirements.txt b/win-requirements.txt index 01e96d29..1156e947 100644 --- a/win-requirements.txt +++ b/win-requirements.txt @@ -1,4 +1,4 @@ -rrequirements.txt -PyQt5==5.15.11 # pyup: ignore +PyQt6==6.10.1 # pyup: ignore pywin32==311 # pyup: ignore