diff --git a/gns3/controller.py b/gns3/controller.py index fa55ff16..b9758dba 100644 --- a/gns3/controller.py +++ b/gns3/controller.py @@ -19,6 +19,7 @@ import os import hashlib import tempfile import json +import pathlib from .qt import QtCore, QtNetwork, QtGui, QtWidgets, QtWebSockets, qpartial, qslot from .symbol import Symbol @@ -46,7 +47,7 @@ class Controller(QtCore.QObject): self._connected = False self._connecting = False self._version = None - self._cache_directory = tempfile.mkdtemp() + self._cache_directory = tempfile.TemporaryDirectory(suffix="-gns3") self._http_client = None self._first_error = True self._error_dialog = None @@ -274,12 +275,11 @@ class Controller(QtCore.QObject): if not self._http_client: return - path = self.getStaticCachedPath(url) if os.path.exists(path): callback(path) - elif path in self._static_asset_download_queue: + if path in self._static_asset_download_queue: self._static_asset_download_queue[path].append((callback, fallback, )) else: self._static_asset_download_queue[path] = [(callback, fallback, )] @@ -313,8 +313,8 @@ class Controller(QtCore.QObject): def getStaticCachedPath(self, url): """ Returns static cached (hashed) path + :param url: - :return: """ m = hashlib.md5() m.update(url.encode()) @@ -322,9 +322,22 @@ class Controller(QtCore.QObject): extension = ".svg" else: extension = ".png" - path = os.path.join(self._cache_directory, m.hexdigest() + extension) + path = os.path.join(self._cache_directory.name, m.hexdigest() + extension) return path + def clearStaticCache(self): + """ + Clear the cache directory. + """ + + for filename in os.listdir(self._cache_directory.name): + if filename.endswith(".svg") or filename.endswith(".png"): + try: + os.remove(os.path.join(self._cache_directory.name, filename)) + except OSError as e: + log.debug("Error deleting cached symbol '{}':{}".format(filename, e)) + continue + def getSymbolIcon(self, symbol_id, callback, fallback=None): """ Get a QIcon for a symbol from the controller @@ -341,10 +354,31 @@ class Controller(QtCore.QObject): self.getStatic(Symbol(symbol_id).url(), qpartial(self._getIconCallback, callback), fallback=fallback) def _getIconCallback(self, callback, path): + + pixmap = QtGui.QPixmap(path) + if pixmap.isNull(): + log.debug("Invalid symbol {}".format(path)) + path = ":/icons/cancel.svg" icon = QtGui.QIcon() icon.addFile(path) callback(icon) + def uploadSymbol(self, symbol_id, path): + + self.post("/symbols/" + symbol_id + "/raw", + qpartial(self._finishSymbolUpload, path), + body=pathlib.Path(path), progressText="Uploading {}".format(symbol_id), timeout=None) + + def _finishSymbolUpload(self, path, result, error=False, **kwargs): + + if error: + log.error("Error while uploading symbol: {}: {}".format(path, result.get("message", "unknown"))) + return + + # Refresh the templates list + from .template_manager import TemplateManager + TemplateManager.instance().templates_changed_signal.emit() + def getSymbols(self, callback): self.get('/symbols', callback=callback) diff --git a/gns3/dialogs/new_template_wizard.py b/gns3/dialogs/new_template_wizard.py index e9901a7a..89632d2d 100644 --- a/gns3/dialogs/new_template_wizard.py +++ b/gns3/dialogs/new_template_wizard.py @@ -19,6 +19,7 @@ import sys import tempfile import json import sip +import os from gns3.qt import QtCore, QtWidgets, qpartial from gns3.controller import Controller @@ -59,6 +60,7 @@ class NewTemplateWizard(QtWidgets.QWizard, Ui_NewTemplateWizard): """ ApplianceManager.instance().refresh(update=True) + Controller.instance().clearStaticCache() def _appliancesChangedSlot(self): """ @@ -266,6 +268,7 @@ class NewTemplateWizard(QtWidgets.QWizard, Ui_NewTemplateWizard): super().done(result) if result: + ApplianceManager.instance().appliances_changed_signal.disconnect(self._appliancesChangedSlot) from gns3.main_window import MainWindow if self.currentPage() == self.uiApplianceFromServerWizardPage: items = self.uiAppliancesTreeWidget.selectedItems() @@ -274,6 +277,10 @@ class NewTemplateWizard(QtWidgets.QWizard, Ui_NewTemplateWizard): json.dump(item.data(0, QtCore.Qt.UserRole), f) f.close() MainWindow.instance().loadPath(f.name) + try: + os.remove(f.name) + except OSError: + pass elif self.uiCreateTemplateManuallyRadioButton.isChecked(): MainWindow.instance().preferencesActionSlot() elif self.uiImportApplianceFromFileRadioButton.isChecked(): diff --git a/gns3/dialogs/preferences_dialog.py b/gns3/dialogs/preferences_dialog.py index 2390999d..9e24eb2e 100644 --- a/gns3/dialogs/preferences_dialog.py +++ b/gns3/dialogs/preferences_dialog.py @@ -128,7 +128,7 @@ class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog): # Class name, changed signal widget_to_watch = { - QtWidgets.QLineEdit: "textChanged", + #QtWidgets.QLineEdit: "textChanged", QtWidgets.QPlainTextEdit: "textChanged", # QtWidgets.QTreeWidget: "itemChanged", QtWidgets.QComboBox: "currentIndexChanged", diff --git a/gns3/dialogs/symbol_selection_dialog.py b/gns3/dialogs/symbol_selection_dialog.py index 57df9234..dbc4d5ae 100644 --- a/gns3/dialogs/symbol_selection_dialog.py +++ b/gns3/dialogs/symbol_selection_dialog.py @@ -25,7 +25,6 @@ import pathlib from ..qt import QtCore, QtGui, QtWidgets, qpartial, sip_is_deleted from ..qt.qimage_svg_renderer import QImageSvgRenderer from ..ui.symbol_selection_dialog_ui import Ui_SymbolSelectionDialog -from ..local_server import LocalServer from ..controller import Controller from ..symbol import Symbol @@ -56,7 +55,6 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): self.uiCustomSymbolRadioButton.toggled.connect(self._customSymbolToggledSlot) self.uiBuiltInSymbolRadioButton.toggled.connect(self._builtInSymbolToggledSlot) self.uiSearchLineEdit.textChanged.connect(self._searchTextChangedSlot) - self.uiBuiltinSymbolOnlyCheckBox.toggled.connect(self._builtinSymbolOnlyToggledSlot) if not SymbolSelectionDialog._symbols_dir: SymbolSelectionDialog._symbols_dir = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.PicturesLocation) @@ -64,9 +62,10 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).hide() self.uiBuiltInSymbolRadioButton.setChecked(True) - self.uiSymbolListWidget.setFocus() - self.uiSymbolListWidget.setIconSize(QtCore.QSize(64, 64)) + self.uiSymbolTreeWidget.setFocus() + self.uiSymbolTreeWidget.setIconSize(QtCore.QSize(64, 64)) self._symbol_items = [] + self._parents = {} Controller.instance().get("/symbols", self._listSymbolsCallback) @@ -78,17 +77,24 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): self._symbol_items = [] for symbol in result: symbol = Symbol(**symbol) - name = os.path.splitext(symbol.filename())[0] - item = QtWidgets.QListWidgetItem(self.uiSymbolListWidget) - item.setData(QtCore.Qt.UserRole, symbol) - self._symbol_items.append(item) - item.setText(name) + theme = symbol.theme() + if theme not in self._parents: + parent = QtWidgets.QTreeWidgetItem(self.uiSymbolTreeWidget) + parent.setText(0, theme) + font = parent.font(0) + font.setBold(True) + parent.setFont(0, font) + parent.setFlags(parent.flags() & ~QtCore.Qt.ItemIsSelectable) + self._parents[theme] = parent + else: + parent = self._parents[theme] - image = QtGui.QImage(64, 64, QtGui.QImage.Format_ARGB32) - # Set the ARGB to 0 to prevent rendering artifacts - image.fill(0x00000000) - icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image)) - item.setIcon(icon) + name = os.path.splitext(symbol.filename())[0] + item = QtWidgets.QTreeWidgetItem(parent) + item.setData(0, QtCore.Qt.UserRole, symbol) + item.setToolTip(0, symbol.id()) + self._symbol_items.append(item) + item.setText(0, name) def render(item, path): if sip_is_deleted(item): @@ -99,14 +105,11 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): image.fill(0x00000000) svg_renderer.render(QtGui.QPainter(image)) icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image)) - item.setIcon(icon) + item.setIcon(0, icon) Controller.instance().getStatic(symbol.url(), qpartial(render, item)) self.adjustSize() - def _builtinSymbolOnlyToggledSlot(self, checked): - self._filter() - def _searchTextChangedSlot(self, text): self._filter() @@ -116,10 +119,10 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): """ text = self.uiSearchLineEdit.text() for item in self._symbol_items: - if self.uiBuiltinSymbolOnlyCheckBox.isChecked() and not item.data(QtCore.Qt.UserRole).builtin(): + if not item.data(0, QtCore.Qt.UserRole).builtin(): item.setHidden(True) else: - if len(text.strip()) == 0 or text.strip().lower() in item.text().lower(): + if len(text.strip()) == 0 or text.strip().lower() in item.text(0).lower(): item.setHidden(False) else: item.setHidden(True) @@ -164,10 +167,10 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog): def getSymbol(self): - if self.uiSymbolListWidget.isEnabled(): - current = self.uiSymbolListWidget.currentItem() + if self.uiSymbolTreeWidget.isEnabled(): + current = self.uiSymbolTreeWidget.currentItem() if current: - return current.data(QtCore.Qt.UserRole).id() + return current.data(0, QtCore.Qt.UserRole).id() else: return os.path.basename(self.uiSymbolLineEdit.text()) return None diff --git a/gns3/items/link_item.py b/gns3/items/link_item.py index 188df69b..7da331da 100644 --- a/gns3/items/link_item.py +++ b/gns3/items/link_item.py @@ -36,7 +36,8 @@ class SvgIconItem(QtSvg.QGraphicsSvgItem): def mousePressEvent(self, event): - self.parentItem().mousePressEvent(event) + if self.parentItem(): + self.parentItem().mousePressEvent(event) event.accept() diff --git a/gns3/registry/appliance_to_template.py b/gns3/registry/appliance_to_template.py index a8f25df2..dcf6b92d 100644 --- a/gns3/registry/appliance_to_template.py +++ b/gns3/registry/appliance_to_template.py @@ -168,37 +168,38 @@ class ApplianceToTemplate: return os.path.basename(path) - def _set_symbol(self, symbol, controller_symbols): + def _set_symbol(self, symbol_id, controller_symbols): """ Check if exists on controller or download symbol from the web if needed """ # GNS3 builtin symbol - if symbol.startswith(":/symbols/"): - return symbol + if symbol_id.startswith(":/symbols/"): + return symbol_id - path = os.path.join(Config().symbols_dir, symbol) + path = os.path.join(Config().symbols_dir, symbol_id) if os.path.exists(path): return os.path.basename(path) if controller_symbols: - is_symbol_on_controller = len([s for s in controller_symbols - if s['symbol_id'] == symbol]) > 0 + is_symbol_on_controller = len([s for s in controller_symbols if s['symbol_id'] == symbol_id]) > 0 if is_symbol_on_controller: - cached = Controller.instance().getStaticCachedPath(symbol) + cached = Controller.instance().getStaticCachedPath(symbol_id) if os.path.exists(cached): try: shutil.copy(cached, path) except IOError as e: - log.warning("Cannot copy cached symbol from `{}` to `{}` due `{}`".format( - cached, path, str(e) - )) - return symbol + log.warning("Cannot copy cached symbol from `{}` to `{}` due `{}`".format(cached, path, e)) + return symbol_id - url = "https://raw.githubusercontent.com/GNS3/gns3-registry/master/symbols/{}".format(symbol) + url = "https://raw.githubusercontent.com/GNS3/gns3-registry/master/symbols/{}".format(symbol_id) try: urllib.request.urlretrieve(url, path) + controller = Controller.instance() + controller.clearStaticCache() + if controller.isRemote(): + controller.uploadSymbol(symbol_id, path) return os.path.basename(path) except (OSError, CertificateError): return None diff --git a/gns3/symbol.py b/gns3/symbol.py index bb1b7fe7..9c6ba137 100644 --- a/gns3/symbol.py +++ b/gns3/symbol.py @@ -19,10 +19,11 @@ import urllib.parse class Symbol: - def __init__(self, symbol_id=None, builtin=False, filename=None): + def __init__(self, symbol_id=None, builtin=False, filename=None, theme=None): self._id = symbol_id self._builtin = builtin self._filename = filename + self._theme = theme def id(self): return self._id @@ -33,6 +34,9 @@ class Symbol: def builtin(self): return self._builtin + def theme(self): + return self._theme + def url(self): return urllib.parse.quote("/symbols/" + self._id + "/raw") diff --git a/gns3/ui/new_template_wizard.ui b/gns3/ui/new_template_wizard.ui index 38021aba..406ffd5e 100644 --- a/gns3/ui/new_template_wizard.ui +++ b/gns3/ui/new_template_wizard.ui @@ -70,6 +70,9 @@ QAbstractItemView::ExtendedSelection + + 10 + true diff --git a/gns3/ui/new_template_wizard_ui.py b/gns3/ui/new_template_wizard_ui.py index 345e6486..0544919c 100644 --- a/gns3/ui/new_template_wizard_ui.py +++ b/gns3/ui/new_template_wizard_ui.py @@ -37,6 +37,7 @@ class Ui_NewTemplateWizard(object): self.verticalLayout_2.addWidget(self.uiFilterLineEdit) self.uiAppliancesTreeWidget = QtWidgets.QTreeWidget(self.uiApplianceFromServerWizardPage) self.uiAppliancesTreeWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + self.uiAppliancesTreeWidget.setIndentation(10) self.uiAppliancesTreeWidget.setObjectName("uiAppliancesTreeWidget") self.uiAppliancesTreeWidget.header().setSortIndicatorShown(True) self.verticalLayout_2.addWidget(self.uiAppliancesTreeWidget) diff --git a/gns3/ui/packet_capture_preferences_page.ui b/gns3/ui/packet_capture_preferences_page.ui index e19672b2..9e52a1c4 100755 --- a/gns3/ui/packet_capture_preferences_page.ui +++ b/gns3/ui/packet_capture_preferences_page.ui @@ -53,13 +53,6 @@ - - - - <html><head/><body><p>Command line replacements:</p><p>%c = capture file (PCAP format)</p></body></html> - - - @@ -80,9 +73,16 @@ - + + + + + <html><head/><body><p>Command line replacements:</p><p>%c = capture file (PCAP format)</p></body></html> + + + diff --git a/gns3/ui/packet_capture_preferences_page_ui.py b/gns3/ui/packet_capture_preferences_page_ui.py index 23e1962e..b2cb9804 100644 --- a/gns3/ui/packet_capture_preferences_page_ui.py +++ b/gns3/ui/packet_capture_preferences_page_ui.py @@ -36,9 +36,6 @@ class Ui_PacketCapturePreferencesPageWidget(object): self.uiCaptureReaderCommandLabel.setEnabled(True) self.uiCaptureReaderCommandLabel.setObjectName("uiCaptureReaderCommandLabel") self.gridLayout.addWidget(self.uiCaptureReaderCommandLabel, 2, 0, 1, 1) - self.uiCaptureReaderCommandLineEdit = QtWidgets.QLineEdit(self.uiSettingsGroupBox) - self.uiCaptureReaderCommandLineEdit.setObjectName("uiCaptureReaderCommandLineEdit") - self.gridLayout.addWidget(self.uiCaptureReaderCommandLineEdit, 3, 0, 1, 1) self.uiAutoStartCheckBox = QtWidgets.QCheckBox(self.uiSettingsGroupBox) self.uiAutoStartCheckBox.setEnabled(True) self.uiAutoStartCheckBox.setChecked(False) @@ -49,7 +46,10 @@ class Ui_PacketCapturePreferencesPageWidget(object): self.gridLayout.addWidget(self.uiCaptureAnalyzerCommandLabel, 5, 0, 1, 1) self.uiCaptureAnalyzerCommandLineEdit = QtWidgets.QLineEdit(self.uiSettingsGroupBox) self.uiCaptureAnalyzerCommandLineEdit.setObjectName("uiCaptureAnalyzerCommandLineEdit") - self.gridLayout.addWidget(self.uiCaptureAnalyzerCommandLineEdit, 6, 0, 1, 1) + self.gridLayout.addWidget(self.uiCaptureAnalyzerCommandLineEdit, 6, 0, 1, 2) + self.uiCaptureReaderCommandLineEdit = QtWidgets.QLineEdit(self.uiSettingsGroupBox) + self.uiCaptureReaderCommandLineEdit.setObjectName("uiCaptureReaderCommandLineEdit") + self.gridLayout.addWidget(self.uiCaptureReaderCommandLineEdit, 3, 0, 1, 2) self.verticalLayout.addWidget(self.uiSettingsGroupBox) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") @@ -72,8 +72,8 @@ class Ui_PacketCapturePreferencesPageWidget(object): self.uiPreconfiguredCaptureReaderCommandLabel.setText(_translate("PacketCapturePreferencesPageWidget", "Preconfigured packet capture reader commands:")) self.uiPreconfiguredCaptureReaderCommandPushButton.setText(_translate("PacketCapturePreferencesPageWidget", "&Set")) self.uiCaptureReaderCommandLabel.setText(_translate("PacketCapturePreferencesPageWidget", "Packet capture reader command:")) - self.uiCaptureReaderCommandLineEdit.setToolTip(_translate("PacketCapturePreferencesPageWidget", "

Command line replacements:

%c = capture file (PCAP format)

")) self.uiAutoStartCheckBox.setText(_translate("PacketCapturePreferencesPageWidget", "Automatically start the packet capture application")) self.uiCaptureAnalyzerCommandLabel.setText(_translate("PacketCapturePreferencesPageWidget", "Packet capture analyzer command:")) + self.uiCaptureReaderCommandLineEdit.setToolTip(_translate("PacketCapturePreferencesPageWidget", "

Command line replacements:

%c = capture file (PCAP format)

")) self.uiRestoreDefaultsPushButton.setText(_translate("PacketCapturePreferencesPageWidget", "Restore defaults")) diff --git a/gns3/ui/symbol_selection_dialog.ui b/gns3/ui/symbol_selection_dialog.ui index 781c4713..b2e4dbac 100755 --- a/gns3/ui/symbol_selection_dialog.ui +++ b/gns3/ui/symbol_selection_dialog.ui @@ -6,8 +6,8 @@ 0 0 - 718 - 626 + 610 + 700 @@ -16,7 +16,7 @@ true - + @@ -85,36 +85,36 @@ Symbols - - - - - Show only built-in symbols - - - - - - - - - Filter: - - - - - - - - - - + + + 0 300 + + 10 + + + false + + + + 1 + + + + + + + + + + + Filter: + diff --git a/gns3/ui/symbol_selection_dialog_ui.py b/gns3/ui/symbol_selection_dialog_ui.py index 65a5099a..75892c40 100644 --- a/gns3/ui/symbol_selection_dialog_ui.py +++ b/gns3/ui/symbol_selection_dialog_ui.py @@ -11,10 +11,10 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_SymbolSelectionDialog(object): def setupUi(self, SymbolSelectionDialog): SymbolSelectionDialog.setObjectName("SymbolSelectionDialog") - SymbolSelectionDialog.resize(718, 626) + SymbolSelectionDialog.resize(610, 700) SymbolSelectionDialog.setModal(True) - self.verticalLayout_2 = QtWidgets.QVBoxLayout(SymbolSelectionDialog) - self.verticalLayout_2.setObjectName("verticalLayout_2") + self.verticalLayout = QtWidgets.QVBoxLayout(SymbolSelectionDialog) + self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.uiCustomSymbolRadioButton = QtWidgets.QRadioButton(SymbolSelectionDialog) @@ -26,7 +26,7 @@ class Ui_SymbolSelectionDialog(object): self.horizontalLayout_2.addWidget(self.uiBuiltInSymbolRadioButton) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) + self.verticalLayout.addLayout(self.horizontalLayout_2) self.uiCustomSymbolGroupBox = QtWidgets.QGroupBox(SymbolSelectionDialog) self.uiCustomSymbolGroupBox.setObjectName("uiCustomSymbolGroupBox") self.gridLayout = QtWidgets.QGridLayout(self.uiCustomSymbolGroupBox) @@ -41,28 +41,25 @@ class Ui_SymbolSelectionDialog(object): self.uiSymbolLabel = QtWidgets.QLabel(self.uiCustomSymbolGroupBox) self.uiSymbolLabel.setObjectName("uiSymbolLabel") self.gridLayout.addWidget(self.uiSymbolLabel, 0, 0, 1, 1) - self.verticalLayout_2.addWidget(self.uiCustomSymbolGroupBox) + self.verticalLayout.addWidget(self.uiCustomSymbolGroupBox) self.uiBuiltInGroupBox = QtWidgets.QGroupBox(SymbolSelectionDialog) self.uiBuiltInGroupBox.setObjectName("uiBuiltInGroupBox") - self.verticalLayout = QtWidgets.QVBoxLayout(self.uiBuiltInGroupBox) - self.verticalLayout.setObjectName("verticalLayout") - self.uiBuiltinSymbolOnlyCheckBox = QtWidgets.QCheckBox(self.uiBuiltInGroupBox) - self.uiBuiltinSymbolOnlyCheckBox.setObjectName("uiBuiltinSymbolOnlyCheckBox") - self.verticalLayout.addWidget(self.uiBuiltinSymbolOnlyCheckBox) - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.uiSearchLabel = QtWidgets.QLabel(self.uiBuiltInGroupBox) - self.uiSearchLabel.setObjectName("uiSearchLabel") - self.horizontalLayout_3.addWidget(self.uiSearchLabel) + self.gridLayout_2 = QtWidgets.QGridLayout(self.uiBuiltInGroupBox) + self.gridLayout_2.setObjectName("gridLayout_2") + self.uiSymbolTreeWidget = QtWidgets.QTreeWidget(self.uiBuiltInGroupBox) + self.uiSymbolTreeWidget.setMinimumSize(QtCore.QSize(0, 300)) + self.uiSymbolTreeWidget.setIndentation(10) + self.uiSymbolTreeWidget.setObjectName("uiSymbolTreeWidget") + self.uiSymbolTreeWidget.headerItem().setText(0, "1") + self.uiSymbolTreeWidget.header().setVisible(False) + self.gridLayout_2.addWidget(self.uiSymbolTreeWidget, 1, 0, 1, 2) self.uiSearchLineEdit = QtWidgets.QLineEdit(self.uiBuiltInGroupBox) self.uiSearchLineEdit.setObjectName("uiSearchLineEdit") - self.horizontalLayout_3.addWidget(self.uiSearchLineEdit) - self.verticalLayout.addLayout(self.horizontalLayout_3) - self.uiSymbolListWidget = QtWidgets.QListWidget(self.uiBuiltInGroupBox) - self.uiSymbolListWidget.setMinimumSize(QtCore.QSize(0, 300)) - self.uiSymbolListWidget.setObjectName("uiSymbolListWidget") - self.verticalLayout.addWidget(self.uiSymbolListWidget) - self.verticalLayout_2.addWidget(self.uiBuiltInGroupBox) + self.gridLayout_2.addWidget(self.uiSearchLineEdit, 0, 1, 1, 1) + self.uiSearchLabel = QtWidgets.QLabel(self.uiBuiltInGroupBox) + self.uiSearchLabel.setObjectName("uiSearchLabel") + self.gridLayout_2.addWidget(self.uiSearchLabel, 0, 0, 1, 1) + self.verticalLayout.addWidget(self.uiBuiltInGroupBox) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) @@ -72,7 +69,7 @@ class Ui_SymbolSelectionDialog(object): self.uiButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.uiButtonBox.setObjectName("uiButtonBox") self.horizontalLayout.addWidget(self.uiButtonBox) - self.verticalLayout_2.addLayout(self.horizontalLayout) + self.verticalLayout.addLayout(self.horizontalLayout) self.uiBuiltInGroupBox.raise_() self.uiCustomSymbolGroupBox.raise_() @@ -90,7 +87,6 @@ class Ui_SymbolSelectionDialog(object): self.uiSymbolToolButton.setText(_translate("SymbolSelectionDialog", "&Browse...")) self.uiSymbolLabel.setText(_translate("SymbolSelectionDialog", "Path:")) self.uiBuiltInGroupBox.setTitle(_translate("SymbolSelectionDialog", "Symbols")) - self.uiBuiltinSymbolOnlyCheckBox.setText(_translate("SymbolSelectionDialog", "Show only built-in symbols")) self.uiSearchLabel.setText(_translate("SymbolSelectionDialog", "Filter:")) from . import resources_rc