Finalizing PyQt6 migration

This commit is contained in:
grossmj
2025-12-15 19:27:55 +08:00
parent e6a083eb0e
commit 1cdec97a12
22 changed files with 157 additions and 511 deletions

View File

@@ -17,7 +17,7 @@ Please see <https://docs.gns3.com/>
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)

View File

@@ -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):

View File

@@ -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):

View File

@@ -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()

View File

@@ -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"])

View File

@@ -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()

View File

@@ -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()

View File

@@ -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"

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -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(),

View File

@@ -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

View File

@@ -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"
}

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>512</width>
<width>556</width>
<height>652</height>
</rect>
</property>
@@ -1016,13 +1016,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="uiHdpiCheckBox">
<property name="text">
<string>Enable HDPI mode (this may crash on Linux, restart required)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="uiMultiProfilesCheckBox">
<property name="text">
@@ -1126,7 +1119,6 @@
<tabstop>uiCrashReportCheckBox</tabstop>
<tabstop>uiOverlayNotificationsCheckBox</tabstop>
<tabstop>uiExperimentalFeaturesCheckBox</tabstop>
<tabstop>uiHdpiCheckBox</tabstop>
<tabstop>uiMultiProfilesCheckBox</tabstop>
<tabstop>uiDirectFileUpload</tabstop>
<tabstop>uiRestoreDefaultsPushButton</tabstop>

View File

@@ -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)"))

View File

@@ -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\x16<wO\xe9[\xcb\xb4\x01\xa1\x0f\xff\
\x81L\xd4ZG\xcc\xc5\x1f&\xd2\xad\xbc\x8f\xb8`z\
\xd7\xd3\xdej\xda\xf6\x1e%\xeev\xb0\x0de\x8cM\xf9\
\xb6\xbd1x\x12\x13i\x8eh\x9cu\x8f\x1d\x06\x83\xed\
\xcf:\xb6(\xdczq\x95\xeeM\x13\x13\xd7\x86\xa8\x5c\
\x86z\xc3\x0di\x88K\x94\xf5&zp\xf7\x8a\x0a\x91\
\xcc\xd0\x98\xb7\xc7I\xc9\x0f\x9c\x15\x8a\xf7V\xaeM\x89\
\xeb\x91{\xdf\xa5\xd36\x18\xd5\x86Hx\x07nj[\
)\xc5\x03\xe2\xf8\x8cv\xa43\xfa'27.\xf7/\
\xf14{\x98\xd6\xff\x97\x85\xc6m\xcfw\xbd\xfdz$\
\xab9\x13\xce\xa0D\xb9\x85\xa6\xa0\x0b\xac\xbe\x17\xceP\
\xfd\xe1\xfbk\xe4\xff^\x17\xcbw\xfc\xdc*BG\x0e\
\x04\xeb\x87\x0a\x84v1\xb8\x11\x9f\x8en'\x07\xb4\xb4\
\xb8\xa4\xd1p\x22~\x0b\xbe\x1c\x0a\xb7t\xd2Q\x111\
Z\xc7W\x0f\xe5\xcd\xab\x14\x83\x0f9\xcc\xd6|}\xc8\
\xc1\x9di\xac2\xe2+\xf5\x84\xbf<sZ\xd9-9\
\xc4\xf8&\xc3\xf9\xc3?\xb4\xb0\xebz\xf6%\x1f$\xe1\
\x9cjk\xda\xeaN\x17\x1f@\x13\x8a\x0d\xd0(7+\
\x02]I\x9bQ\xb6\x97\x0c1\x08\xdc/\x7fc\x0cY\
\x9c\xaaR\xa2:s\x89\xd3\xf2\xd5\xd3\xfc\xbc]U\xc1\
\x09\xe7\x10\xde\x5c\x9f9\xbbx\xe2\xf9zg\xce\x11\xba\
5(ag\xc0\x0f\xa5K\xc0.\xe6\xad\x9b[)\xda\
\xad\x9dx\xe4\xd8\x00\x04\x225u\x9b\x89\x84r\xf8\xb8\
\xa8j=\xaa5\xcbY \xe8V\xc6\xaf\xa5\xb5S_\
RH\x09\xf5hlv9\xcdvO\x0e\x03b\xd0\x98\
\x0ei\x1c\x03~\xb0P1\xcb\xfd k\xd9]\xdb\x12\
\xaf\xa5\xe2\xd8\x0c\xe6\xcdK\x1e\x9e-\x94zd\xe4\xce\
j\x86,\xc4<\xaf\x9f\xa2M\xd5\xef\xb4\xa5\xa5\x9f\xa4\
\x01\x9a\x7f7\xc3\xf7\xdb8w\x5c\x95\xd3\x1c\xc4;\xe8\
\xef\xa4I:x\xb8\xff@\xa1kv\xf2\x9e\xd0\xaa\xb8\
\xf8Z\xccL\xc06\xe6\xcdT\x09\xb31\xfa\xd6\xff\x80\
V~A$\xb0\x1b\x9f\xac\xfb\xf8\xc9\xa4#\xd1>1\
\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<Y$d\x06\xd9\
\xb7\xb3\xce[\xf1\x19\xdf\x85)\xb89R\xa0q\xafc\
@\x17\xd5\x03\xbd*2\x9a\x9b\xb1-\xa2!\xfe\xd7\xac\
Rz\xb5\x0e\x80\xb4\x8b\x09\xfb\xc1\xa2c3\xdfQ%\
\x17\x10*%\x92C:j\x89\x9e\x85~3_\xc1X\
\xa4\x12\x0c\xaa*8\x08R\xc1\x89\xb4<\xe8}\x97\xeb\
}\x91\x07p\xd1~UI~TV\xe8\x88\x96KE\
\x07\xd4=\xa7\xd4~\xca\x95W\xe7\x89\x97\xf5(o\x8d\
\xa5r:\x09\xf4'\xaf\xcc\x17x\xe1\xefg\xcd\x86\xb6\
\xeap\x026\xc5\xdcs\x036X\xd7M\x91\xb4\xe9\x0d\
\x1d\xddh\xa2q\x5c\xc8\xdbyr\x86\x85\xca\x81Iw\
\xc8\x13\xae\xed\xbf\xd1!\xd5[(!\xb9/\xd4I\
\x02\x05\x5c-\xa0\xa8atr\x16\x9b\xc5\x22\x85Vr\
P\x16A\xb1\xffc{\x08GC\x93\xc6\xb1\x030\xe7\
\xd3\xd9\xf1\xdfI2y<\x93%\xf3\x10\xb5)\x87O\
6d\x99\xb5`e 7\x1f\x86T\xd7\x80\xb0\xcd\x22\
\xbf\x85+\xfdKD\xb0\xff\x015N\xbfz,\x5c\xb1\
Q\xa8\x9f\xfb\x00\xf3}\xfe$p\xc5\xac\x04\xce\xc2\xe1\
\xcf\x97\x15e\x97\xbfB$\xf1\x9c\xc1f\xd9s\xba\x92\
\x22\x1a\xb0\x09\xc0\xdabS\x15\xfe\x04r\xe8\x004b\
L{\x004Ve,\x06K\x89\xacC\x04\xf0\x94 \
4\xf1B\xeaK\xa4/\x03\xab\x953D\xf8ky\x1e\
\xcd\xc6\xff5A0f\x90o\x89 ~\xb8\x00_`\
\x17'\xacK\xbc\xaa\xfc\xfc\xc8\xd3\x8bk\xc7\xcf\xa7\x8a\
L\xc2XCGL\xff!4p\xa5\x22u\xdbA\xfb\
\xe2[\xaa/\xed\xa4\x871V;\xbb`^\xfb\x89\xa4\
\xf6\xa2\xe2\xb8\xffY\xe7\xe9y\x0d\xf0\xfeT\xc6Q\xb5\
\xca\x8d\xa615\x01\x15\x9a\xc7G\x1b\xb1\xc3\x9f5\xd7\
\xd9(\x0e\x8f\x9eV\xacu\x0d_\xfc\x82\xbc\x03\x05\x97\
\x9a*\x99\xad\x9a\xb5\x8e@\xdc\xe2\xda\x8a\x8e\x9d\xac1\
\x93~\xbfg\xe2l\xe8Q}r\x8a0\xcf\xbf\x17\xe7\
\xe3F\x079\x95\x97h\x84_U}b\x22\x14\x96\xb0\
\x07\xcfU#^\xc2Xo|\x0c8\xc42\x067W\
\xa0Ja\xee\x9d\xb4cVT\xec\xa1\x94\xe4\x80O\xa9\
\xa0U\x17\xaf\xba%\xe2\x1e\xe2\x16\xbbP\xdc\x89(\x06\
\xc0c\xe3\x82\xc2\x18\xbeM\xe1D\x1c\x94\xf4u\x93\xda\
\xa6\xa7\x83m\xff(\x02(\xc9U\x83\x0f\xf1.\xbd0\
\x0b\x9aQ3!)\xa8\x0c\xcaZg\x03\xb0sq\xcd\
\x9d\xd1\xab\xa4(\x01\xa3\xe8\xe5\xd68\x9f4\xd9\xcf\x81\
\x22mXn9\xe5\xf9\xf8\xaa\xd1\x03^\xa3Ek)\
\x92\x0f\x94\x9cJ\x06\x02L\xad\xc3\xa0$\xa5\xa1\x99\x16\
\xec$\xe08\x1c'\x08\x06\x07I\x9b\xe0o{\xbc\x05\
\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\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?`\
"

View File

@@ -1,3 +1,3 @@
-rrequirements.txt
PyQt5==5.15.11
PyQt5==6.10.1

View File

@@ -24,7 +24,6 @@
<file>icons/connection-new-hover.svg</file>
<file>icons/console.svg</file>
<file>icons/console_edit.svg</file>
<file>icons/command_line.svg</file>
<file>icons/aux-console.svg</file>
<file>icons/command_line.svg</file>
<file>icons/delete.svg</file>

View File

@@ -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)
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/"))

View File

@@ -1,4 +1,4 @@
-rrequirements.txt
PyQt5==5.15.11 # pyup: ignore
PyQt6==6.10.1 # pyup: ignore
pywin32==311 # pyup: ignore