From c0ecf3ccc4892189cbb936333170cf836beae4e4 Mon Sep 17 00:00:00 2001 From: grossmj Date: Mon, 21 Jan 2019 16:41:46 +0700 Subject: [PATCH 1/4] Automatically resize SVG symbols that are too big. Ref #2674. (cherry picked from commit 8f381a4720e60dc17957fb10384831d83bc6cd14) --- gns3/dialogs/symbol_selection_dialog.py | 2 +- gns3/items/node_item.py | 5 ++++ gns3/qt/qimage_svg_renderer.py | 40 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/gns3/dialogs/symbol_selection_dialog.py b/gns3/dialogs/symbol_selection_dialog.py index 4440bd3e7..57df9234c 100644 --- a/gns3/dialogs/symbol_selection_dialog.py +++ b/gns3/dialogs/symbol_selection_dialog.py @@ -186,7 +186,7 @@ def _symbolBrowserSlot(self): def _finishSymbolUpload(self, path, result, error=False, **kwargs): if error: - log.error("Error while uploading symbol: {}".format(path)) + log.error("Error while uploading symbol: {}: {}".format(path, result.get("message", "unknown"))) return self.uiSymbolLineEdit.clear() self.uiSymbolLineEdit.setText(path) diff --git a/gns3/items/node_item.py b/gns3/items/node_item.py index bbff229ba..4610e65ce 100644 --- a/gns3/items/node_item.py +++ b/gns3/items/node_item.py @@ -144,9 +144,14 @@ def symbol(self): @qslot def _symbolLoadedCallback(self, path, *args): + renderer = QImageSvgRenderer(path, fallback=":/icons/cancel.svg") renderer.setObjectName(path) self.setSharedRenderer(renderer) + if renderer.defaultSize().height() > 80 or renderer.defaultSize().width() > 80: + # resize the SVG + renderer.resize(80) + self.setSharedRenderer(renderer) if self._node.settings().get("symbol") != self._symbol: self.updateNode() if not self._initialized: diff --git a/gns3/qt/qimage_svg_renderer.py b/gns3/qt/qimage_svg_renderer.py index 49c720c45..8d03ac561 100644 --- a/gns3/qt/qimage_svg_renderer.py +++ b/gns3/qt/qimage_svg_renderer.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import os +import re import xml.etree.ElementTree as ET from . import QtCore @@ -35,12 +36,14 @@ class QImageSvgRenderer(QtSvg.QSvgRenderer): """ def __init__(self, path_or_data=None, fallback=None): + super().__init__() self._fallback = fallback self._svg = """""" self.load(path_or_data) def load(self, path_or_data): + try: path_exists = os.path.exists(path_or_data) except ValueError: # On windows we can get an error because the path is too long (it's the svg data) @@ -92,6 +95,43 @@ def load(self, path_or_data): res = super().load(self._svg.encode()) return res + def resize(self, new_height, new_width=None): + + if not self.isValid(): + log.error("QSvgRenderer is not valid") + return + + size = self.defaultSize() + data = self._svg.encode() + height = size.height() + width = size.width() + + if not new_width: + new_width = round(width / height * new_height) + + add_attr = [] + svg_header, svg_tag, svg_data = re.split(b'(]*>)', data, maxsplit=1) + + attr = 'height="{}"'.format(new_height).encode() + svg_tag, count = re.subn(b'height="[^"]*"', attr, svg_tag, count=1) + if not count: + add_attr.append(attr) + + attr = 'width="{}"'.format(new_width).encode() + svg_tag, count = re.subn(b'width="[^"]*"', attr, svg_tag, count=1) + if not count: + add_attr.append(attr) + + if b'viewBox="' not in svg_tag: + add_attr.append('viewBox="0 0 {} {}"'.format(width, height).encode()) + + if add_attr: + svg_tag = svg_tag.replace(b' Date: Mon, 21 Jan 2019 17:22:03 +0700 Subject: [PATCH 2/4] Resize SVG node symbol only when height is above 80px. Ref #2674 Work on str instead of binary when resizing SVG symbol. (cherry picked from commit 938e9129cd22c99f251ea0c8de024c7cdfa5da55) --- gns3/items/node_item.py | 2 +- gns3/qt/qimage_svg_renderer.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gns3/items/node_item.py b/gns3/items/node_item.py index 4610e65ce..19210dd11 100644 --- a/gns3/items/node_item.py +++ b/gns3/items/node_item.py @@ -148,7 +148,7 @@ def _symbolLoadedCallback(self, path, *args): renderer = QImageSvgRenderer(path, fallback=":/icons/cancel.svg") renderer.setObjectName(path) self.setSharedRenderer(renderer) - if renderer.defaultSize().height() > 80 or renderer.defaultSize().width() > 80: + if renderer.defaultSize().height() > 80: # resize the SVG renderer.resize(80) self.setSharedRenderer(renderer) diff --git a/gns3/qt/qimage_svg_renderer.py b/gns3/qt/qimage_svg_renderer.py index 8d03ac561..ca1265ca8 100644 --- a/gns3/qt/qimage_svg_renderer.py +++ b/gns3/qt/qimage_svg_renderer.py @@ -102,7 +102,6 @@ def resize(self, new_height, new_width=None): return size = self.defaultSize() - data = self._svg.encode() height = size.height() width = size.width() @@ -110,25 +109,26 @@ def resize(self, new_height, new_width=None): new_width = round(width / height * new_height) add_attr = [] - svg_header, svg_tag, svg_data = re.split(b'(]*>)', data, maxsplit=1) + svg_header, svg_tag, svg_data = re.split(r'(]*>)', self._svg, maxsplit=1) - attr = 'height="{}"'.format(new_height).encode() - svg_tag, count = re.subn(b'height="[^"]*"', attr, svg_tag, count=1) + attr = 'height="{}"'.format(new_height) + svg_tag, count = re.subn(r'height="[^"]*"', attr, svg_tag, count=1) if not count: add_attr.append(attr) - attr = 'width="{}"'.format(new_width).encode() - svg_tag, count = re.subn(b'width="[^"]*"', attr, svg_tag, count=1) + attr = 'width="{}"'.format(new_width) + svg_tag, count = re.subn(r'width="[^"]*"', attr, svg_tag, count=1) if not count: add_attr.append(attr) - if b'viewBox="' not in svg_tag: - add_attr.append('viewBox="0 0 {} {}"'.format(width, height).encode()) + if 'viewBox="' not in svg_tag: + add_attr.append('viewBox="0 0 {} {}"'.format(width, height)) if add_attr: - svg_tag = svg_tag.replace(b' Date: Mon, 21 Jan 2019 18:11:26 +0700 Subject: [PATCH 3/4] Option to limit the size of node symbols (activated by default). Ref #2674. (cherry picked from commit 6b38b58633b86d4894e34cb45b787cede1190b08) --- gns3/items/node_item.py | 2 +- gns3/settings.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gns3/items/node_item.py b/gns3/items/node_item.py index 19210dd11..cac82e705 100644 --- a/gns3/items/node_item.py +++ b/gns3/items/node_item.py @@ -148,7 +148,7 @@ def _symbolLoadedCallback(self, path, *args): renderer = QImageSvgRenderer(path, fallback=":/icons/cancel.svg") renderer.setObjectName(path) self.setSharedRenderer(renderer) - if renderer.defaultSize().height() > 80: + if self._settings["limit_size_node_symbols"] is True and renderer.defaultSize().height() > 80: # resize the SVG renderer.resize(80) self.setSharedRenderer(renderer) diff --git a/gns3/settings.py b/gns3/settings.py index a28329d48..adcfd4824 100644 --- a/gns3/settings.py +++ b/gns3/settings.py @@ -308,7 +308,8 @@ "snap_to_grid": False, "show_grid": False, "show_interface_labels": False, - "show_interface_labels_on_new_project": False + "show_interface_labels_on_new_project": False, + "limit_size_node_symbols": True } LOCAL_SERVER_SETTINGS = { From c6594d4845005995f2753cdcb42f725708b1b80d Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 22 Jan 2019 22:16:45 +0700 Subject: [PATCH 4/4] Checkbox to activate/deactivate the size limit of node symbols. --- gns3/pages/general_preferences_page.py | 2 ++ gns3/ui/general_preferences_page.ui | 15 +++++++++++---- gns3/ui/general_preferences_page_ui.py | 14 +++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/gns3/pages/general_preferences_page.py b/gns3/pages/general_preferences_page.py index 76eec8966..99cb9a5c4 100644 --- a/gns3/pages/general_preferences_page.py +++ b/gns3/pages/general_preferences_page.py @@ -320,6 +320,7 @@ def _populateGraphicsViewSettingWidgets(self, settings): self.uiRectangleSelectedItemCheckBox.setChecked(settings["draw_rectangle_selected_item"]) self.uiDrawLinkStatusPointsCheckBox.setChecked(settings["draw_link_status_points"]) self.uiShowInterfaceLabelsOnNewProject.setChecked(settings["show_interface_labels_on_new_project"]) + self.uiLimitSizeNodeSymbolCheckBox.setChecked(settings["limit_size_node_symbols"]) qt_font = QtGui.QFont() if qt_font.fromString(settings["default_label_font"]): @@ -384,6 +385,7 @@ def savePreferences(self): "draw_rectangle_selected_item": self.uiRectangleSelectedItemCheckBox.isChecked(), "draw_link_status_points": self.uiDrawLinkStatusPointsCheckBox.isChecked(), "show_interface_labels_on_new_project": self.uiShowInterfaceLabelsOnNewProject.isChecked(), + "limit_size_node_symbols": self.uiLimitSizeNodeSymbolCheckBox.isChecked(), "default_label_font": self.uiDefaultLabelStylePlainTextEdit.font().toString(), "default_label_color": self._default_label_color.name()} MainWindow.instance().uiGraphicsView.setSettings(new_graphics_view_settings) diff --git a/gns3/ui/general_preferences_page.ui b/gns3/ui/general_preferences_page.ui index 68a39366d..afd4147e8 100755 --- a/gns3/ui/general_preferences_page.ui +++ b/gns3/ui/general_preferences_page.ui @@ -664,7 +664,7 @@ - + @@ -721,7 +721,7 @@ - + Default label style: @@ -738,7 +738,7 @@ - + @@ -760,7 +760,7 @@ - + Qt::Vertical @@ -822,6 +822,13 @@ + + + + Limit the size of node symbols + + + diff --git a/gns3/ui/general_preferences_page_ui.py b/gns3/ui/general_preferences_page_ui.py index 1b088639c..984321041 100644 --- a/gns3/ui/general_preferences_page_ui.py +++ b/gns3/ui/general_preferences_page_ui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/general_preferences_page.ui' # -# Created by: PyQt5 UI code generator 5.5.1 +# Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! @@ -324,7 +324,7 @@ def setupUi(self, GeneralPreferencesPageWidget): self.horizontalLayout_5.addWidget(self.uiDefaultLabelColorPushButton) spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem6) - self.gridLayout_8.addLayout(self.horizontalLayout_5, 11, 0, 1, 2) + self.gridLayout_8.addLayout(self.horizontalLayout_5, 12, 0, 1, 2) self.uiSceneHeightLabel = QtWidgets.QLabel(self.uiSceneTab) self.uiSceneHeightLabel.setObjectName("uiSceneHeightLabel") self.gridLayout_8.addWidget(self.uiSceneHeightLabel, 2, 0, 1, 1) @@ -337,7 +337,7 @@ def setupUi(self, GeneralPreferencesPageWidget): self.gridLayout_8.addWidget(self.uiSceneHeightSpinBox, 3, 0, 1, 2) self.uiLabelPreviewLabel = QtWidgets.QLabel(self.uiSceneTab) self.uiLabelPreviewLabel.setObjectName("uiLabelPreviewLabel") - self.gridLayout_8.addWidget(self.uiLabelPreviewLabel, 9, 0, 1, 1) + self.gridLayout_8.addWidget(self.uiLabelPreviewLabel, 10, 0, 1, 1) self.uiDrawLinkStatusPointsCheckBox = QtWidgets.QCheckBox(self.uiSceneTab) self.uiDrawLinkStatusPointsCheckBox.setChecked(True) self.uiDrawLinkStatusPointsCheckBox.setObjectName("uiDrawLinkStatusPointsCheckBox") @@ -351,9 +351,9 @@ def setupUi(self, GeneralPreferencesPageWidget): self.uiDefaultLabelStylePlainTextEdit.setMaximumSize(QtCore.QSize(16777215, 50)) self.uiDefaultLabelStylePlainTextEdit.setReadOnly(True) self.uiDefaultLabelStylePlainTextEdit.setObjectName("uiDefaultLabelStylePlainTextEdit") - self.gridLayout_8.addWidget(self.uiDefaultLabelStylePlainTextEdit, 10, 0, 1, 2) + self.gridLayout_8.addWidget(self.uiDefaultLabelStylePlainTextEdit, 11, 0, 1, 2) spacerItem7 = QtWidgets.QSpacerItem(20, 5, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_8.addItem(spacerItem7, 12, 0, 1, 1) + self.gridLayout_8.addItem(spacerItem7, 13, 0, 1, 1) self.uiSceneWidthSpinBox = QtWidgets.QSpinBox(self.uiSceneTab) self.uiSceneWidthSpinBox.setMinimum(500) self.uiSceneWidthSpinBox.setMaximum(1000000) @@ -374,6 +374,9 @@ def setupUi(self, GeneralPreferencesPageWidget): self.uiGridSizeSpinBox.setProperty("value", 75) self.uiGridSizeSpinBox.setObjectName("uiGridSizeSpinBox") self.gridLayout_8.addWidget(self.uiGridSizeSpinBox, 5, 0, 1, 2) + self.uiLimitSizeNodeSymbolCheckBox = QtWidgets.QCheckBox(self.uiSceneTab) + self.uiLimitSizeNodeSymbolCheckBox.setObjectName("uiLimitSizeNodeSymbolCheckBox") + self.gridLayout_8.addWidget(self.uiLimitSizeNodeSymbolCheckBox, 9, 0, 1, 1) self.uiMiscTabWidget.addTab(self.uiSceneTab, "") self.uiMiscTab = QtWidgets.QWidget() self.uiMiscTab.setObjectName("uiMiscTab") @@ -513,6 +516,7 @@ def retranslateUi(self, GeneralPreferencesPageWidget): self.uiSceneWidthSpinBox.setSuffix(_translate("GeneralPreferencesPageWidget", " pixels")) self.uiShowInterfaceLabelsOnNewProject.setText(_translate("GeneralPreferencesPageWidget", "Show interface labels on new project")) self.uiGridSizeLabel.setText(_translate("GeneralPreferencesPageWidget", "Grid size:")) + self.uiLimitSizeNodeSymbolCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Limit the size of node symbols")) self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiSceneTab), _translate("GeneralPreferencesPageWidget", "Topology view")) self.uiCheckForUpdateCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Automatically check for update")) self.uiCrashReportCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Send anonymous crash reports"))