Compare commits

...

18 Commits

Author SHA1 Message Date
grossmj
fcf62fc507 Release v2.2.54 2025-04-21 17:15:26 +07:00
grossmj
c811c270ec Merge branch 'master' into 2.2 2025-04-21 17:08:42 +07:00
grossmj
dbc519e0af Development on 2.2.54.dev1 2025-04-18 15:05:37 +07:00
grossmj
bcbf8be182 Replace "Docker hub" by "Docker repository" because it is possible to use different repositories 2025-04-16 17:42:44 +07:00
grossmj
43df10520f Upgrade dependencies 2025-04-16 17:08:13 +07:00
grossmj
55b37716a3 Fix bring console in front when clicking on "Open all consoles". Fixes #3706 2025-04-16 16:55:11 +07:00
grossmj
e08253e362 Add -F arg to wmctrl. Ref #3706 2025-02-16 00:10:10 +10:00
Jeremy Grossmann
b9a59183a1 Merge pull request #3699 from GNS3/release/v2.2.53
Release v2.2.53
2025-01-21 09:46:53 +07:00
grossmj
342ca95bd2 Release v2.2.53 2025-01-21 11:52:12 +10:00
grossmj
187ef561fd Update file browser filters for all files and IOU images 2025-01-07 11:32:17 +07:00
grossmj
97070718fa Upgrade dependencies 2024-12-30 10:49:40 +07:00
grossmj
9466b2a1fb Merge branch 'master' into 2.2 2024-12-28 18:03:26 +07:00
grossmj
3edde1274b Fix Linux Mint default terminal configuration 2024-12-25 22:14:25 +07:00
Jeremy Grossmann
e17e7fc033 Merge pull request #3672 from ob7/enable-css-grid-colors
Add CSS Grid Color Customization Support
2024-12-02 19:56:29 +10:00
ob7
bfe11d7976 apply grid color via css property 2024-12-02 00:13:01 -09:00
Jeremy Grossmann
2b98d51ff7 Merge pull request #3668 from GNS3/release/v2.2.52
release/v2.2.52
2024-12-02 11:35:42 +10:00
grossmj
f6fb0100e2 Development on 2.2.53.dev1 2024-12-02 11:34:00 +10:00
Jeremy Grossmann
5efb3019f4 Merge pull request #3656 from GNS3/release/v2.2.51
release/v2.2.51
2024-11-07 23:13:11 +10:00
21 changed files with 92 additions and 30 deletions

View File

@@ -1,5 +1,18 @@
# Change Log
## 2.2.54 21/04/2025
* Replace "Docker hub" by "Docker repository" because it is possible to use different repositories
* Upgrade dependencies
* Fix bring console in front when clicking on "Open all consoles". Fixes #3706
* Add -F arg to wmctrl. Ref #3706
## 2.2.53 21/01/2025
* Update file browser filters for all files and IOU images
* Upgrade dependencies
* Fix Linux Mint default terminal configuration
## 2.2.52 02/12/2024
* Add iol extension filter. Ref #3664

View File

@@ -50,7 +50,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://8a3db3ada69cd1c9817eafd87b400846@o19455.ingest.us.sentry.io/38506"
DSN = "https://62d45083e8fee6a3f5c28d4710ef2cb6@o19455.ingest.us.sentry.io/38506"
_instance = None
def __init__(self):

View File

@@ -184,7 +184,7 @@ class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog):
def _symbolBrowserSlot(self):
# supported image file formats
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm *.gif);;All files (*.*)"
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm *.gif);;All files (*)"
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Image", SymbolSelectionDialog._symbols_dir, file_formats)
if not path:
return

View File

@@ -74,6 +74,10 @@ class GraphicsView(QtWidgets.QGraphicsView):
:param parent: parent widget
"""
# Class-level constants for default colors
DEFAULT_DRAWING_GRID_COLOR = QtGui.QColor(208, 208, 208) # #D0D0D0
DEFAULT_NODE_GRID_COLOR = QtGui.QColor(190, 190, 190) # #BEBEBE
def __init__(self, parent):
# Our parent is the central widget which parent is the main window.
@@ -92,6 +96,8 @@ class GraphicsView(QtWidgets.QGraphicsView):
self._dragging = False
self._grid_size = 75
self._drawing_grid_size = 25
self._drawing_grid_color = self.DEFAULT_DRAWING_GRID_COLOR
self._node_grid_color = self.DEFAULT_NODE_GRID_COLOR
self._last_mouse_position = None
self._topology = Topology.instance()
self._background_warning_msgbox = QtWidgets.QErrorMessage(self)
@@ -1249,7 +1255,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
path, _ = QtWidgets.QFileDialog.getOpenFileName(self,
"Import {}".format(os.path.basename(config_file)),
self._import_config_directory,
"All files (*.*);;Config files (*.cfg)",
"All files (*);;Config files (*.cfg)",
"Config files (*.cfg)")
if not path:
continue
@@ -1296,7 +1302,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
for item in items:
for config_file in item.node().configFiles():
path, ok = QtWidgets.QFileDialog.getSaveFileName(self, "Export file", os.path.join(self._export_config_directory, item.node().name() + "_" + os.path.basename(config_file)), "All files (*.*);;Config files (*.cfg)")
path, ok = QtWidgets.QFileDialog.getSaveFileName(self, "Export file", os.path.join(self._export_config_directory, item.node().name() + "_" + os.path.basename(config_file)), "All files (*);;Config files (*.cfg)")
if not path:
continue
self._export_config_directory = os.path.dirname(path)
@@ -1659,11 +1665,39 @@ class GraphicsView(QtWidgets.QGraphicsView):
self._topology.addDrawing(item)
return item
@QtCore.Property(QtGui.QColor)
def drawingGridColor(self):
"""Returns the drawing grid color"""
return self._drawing_grid_color
@drawingGridColor.setter
def drawingGridColor(self, color):
"""Sets the drawing grid color"""
self._drawing_grid_color = color
self.viewport().update()
@QtCore.Property(QtGui.QColor)
def nodeGridColor(self):
"""Returns the node grid color"""
return self._node_grid_color
@nodeGridColor.setter
def nodeGridColor(self, color):
"""Sets the node grid color"""
self._node_grid_color = color
self.viewport().update()
def resetGridColors(self):
"""Reset grid colors to defaults"""
self._drawing_grid_color = self.DEFAULT_DRAWING_GRID_COLOR
self._node_grid_color = self.DEFAULT_NODE_GRID_COLOR
self.viewport().update()
def drawBackground(self, painter, rect):
super().drawBackground(painter, rect)
if self._main_window.uiShowGridAction.isChecked():
grids = [(self.drawingGridSize(), QtGui.QColor(208, 208, 208)),
(self.nodeGridSize(), QtGui.QColor(190, 190, 190))]
grids = [(self.drawingGridSize(), self._drawing_grid_color),
(self.nodeGridSize(), self._node_grid_color)]
painter.save()
for (grid, colour) in grids:
if not grid:

View File

@@ -428,7 +428,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
if not os.path.exists(self._appliance_dir):
directory = Topology.instance().projectsDirPath()
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Import appliance", directory,
"All files (*.*);;GNS3 Appliance (*.gns3appliance *.gns3a)",
"All files (*);;GNS3 Appliance (*.gns3appliance *.gns3a)",
"GNS3 Appliance (*.gns3appliance *.gns3a)")
if path:
self.loadPath(path)
@@ -447,7 +447,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
if self._project_dir is None or not os.path.exists(self._project_dir):
directory = Topology.instance().projectsDirPath()
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open project", directory,
"All files (*.*);;GNS3 Project (*.gns3);;GNS3 Portable Project (*.gns3project *.gns3p);;NET files (*.net)",
"All files (*);;GNS3 Project (*.gns3);;GNS3 Portable Project (*.gns3project *.gns3p);;NET files (*.net)",
"GNS3 Project (*.gns3)")
if path:
self.loadPath(path)
@@ -920,7 +920,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
Slot called when inserting an image on the scene.
"""
# supported image file formats
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.gif *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*.*)"
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.gif *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*)"
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Image", self._pictures_dir, file_formats)
if not path:
@@ -1449,7 +1449,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
if not os.path.exists(directory):
directory = Topology.instance().projectsDirPath()
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open portable project", directory,
"All files (*.*);;GNS3 Portable Project (*.gns3project *.gns3p)",
"All files (*);;GNS3 Portable Project (*.gns3project *.gns3p)",
"GNS3 Portable Project (*.gns3project *.gns3p)")
if path:
Topology.instance().importProject(path)

View File

@@ -93,7 +93,7 @@
<string>Docker Virtual Machine</string>
</property>
<property name="subTitle">
<string>Please choose a Docker virtual machine from the list or provide an image name on Docker hub.</string>
<string>Please choose a Docker virtual machine from the list or provide an image name on a Docker repository.</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>

View File

@@ -205,7 +205,7 @@ class Ui_DockerVMWizard(object):
self.uiRemoteServersGroupBox.setTitle(_translate("DockerVMWizard", "Remote server"))
self.uiRemoteServersLabel.setText(_translate("DockerVMWizard", "Run on:"))
self.uiImageWizardPage.setTitle(_translate("DockerVMWizard", "Docker Virtual Machine"))
self.uiImageWizardPage.setSubTitle(_translate("DockerVMWizard", "Please choose a Docker virtual machine from the list or provide an image name on Docker hub."))
self.uiImageWizardPage.setSubTitle(_translate("DockerVMWizard", "Please choose a Docker virtual machine from the list or provide an image name on a Docker repository."))
self.uiExistingImageRadioButton.setText(_translate("DockerVMWizard", "Existing image"))
self.uiNewImageRadioButton.setText(_translate("DockerVMWizard", "New image"))
self.uiImageListLabel.setText(_translate("DockerVMWizard", "Image list:"))

View File

@@ -51,7 +51,7 @@ class DynamipsPreferencesPage(QtWidgets.QWidget, Ui_DynamipsPreferencesPageWidge
file_filter = ""
if sys.platform.startswith("win"):
file_filter = "Executable (*.exe);;All files (*.*)"
file_filter = "Executable (*.exe);;All files (*)"
dynamips_path = shutil.which("dynamips")
if sys.platform.startswith("darwin") and dynamips_path is None:

View File

@@ -229,7 +229,7 @@ class IOSRouterPreferencesPage(QtWidgets.QWidget, Ui_IOSRouterPreferencesPageWid
path, _ = QtWidgets.QFileDialog.getOpenFileName(parent,
"Select an IOS image",
cls._default_images_dir,
"All files (*.*);;IOS image (*.bin *.image)",
"All files (*);;IOS image (*.bin *.image)",
"IOS image (*.bin *.image)")
if not path:

View File

@@ -291,8 +291,8 @@ class IOUDevicePreferencesPage(QtWidgets.QWidget, Ui_IOUDevicePreferencesPageWid
path, _ = QtWidgets.QFileDialog.getOpenFileName(parent,
"Select an IOU image",
cls._default_images_dir,
"All file (*);;IOU image (*.bin *.image *.iol)",
"IOU image (*.bin *.image *.iol)")
"All file (*);;IOU image (x86_64* i86bi* *.bin *.image *.iol)",
"IOU image (x86_64* i86bi* *.bin *.image *.iol)")
if not path:
return

View File

@@ -51,7 +51,7 @@ class TraceNGPreferencesPage(QtWidgets.QWidget, Ui_TraceNGPreferencesPageWidget)
filter = ""
if sys.platform.startswith("win"):
filter = "Executable (*.exe);;All files (*.*)"
filter = "Executable (*.exe);;All files (*)"
traceng_path = shutil.which("traceng")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select TraceNG", traceng_path, filter)
if not path:

View File

@@ -51,7 +51,7 @@ class VPCSPreferencesPage(QtWidgets.QWidget, Ui_VPCSPreferencesPageWidget):
filter = ""
if sys.platform.startswith("win"):
filter = "Executable (*.exe);;All files (*.*)"
filter = "Executable (*.exe);;All files (*)"
vpcs_path = shutil.which("vpcs")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select VPCS", vpcs_path, filter)
if not path:

View File

@@ -725,6 +725,9 @@ class Node(BaseNode):
if "console_type" in self.settings():
console_type = self.consoleType()
if aux is False and self.bringToFront() is True:
return
if console_type == "telnet":
from .telnet_console import nodeTelnetConsole
nodeTelnetConsole(self, console_port, command)
@@ -748,7 +751,7 @@ class Node(BaseNode):
if wmctrl_path:
try:
# use wmctrl to raise the window based on the node name (this doesn't work well with window having multiple tabs)
subprocess.run([wmctrl_path, "-a", self.name()], check=True, env=os.environ)
subprocess.run([wmctrl_path, "-Fa", self.name()], check=True, env=os.environ)
return True
except subprocess.CalledProcessError:
log.debug("Could not find window title '{}' to bring it to front".format(self.name()))

View File

@@ -195,7 +195,7 @@ class GeneralPreferencesPage(QtWidgets.QWidget, Ui_GeneralPreferencesPageWidget)
configuration_file_path = LocalConfig.instance().configFilePath()
directory = os.path.dirname(configuration_file_path)
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Import configuration file", directory, "Configuration file (*.ini *.conf);;All files (*.*)")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Import configuration file", directory, "Configuration file (*.ini *.conf);;All files (*)")
if not path:
return
@@ -240,7 +240,7 @@ class GeneralPreferencesPage(QtWidgets.QWidget, Ui_GeneralPreferencesPageWidget)
configuration_file_path = LocalConfig.instance().configFilePath()
directory = os.path.dirname(configuration_file_path)
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export configuration file", directory, "Configuration file (*.ini *.conf);;All files (*.*)")
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export configuration file", directory, "Configuration file (*.ini *.conf);;All files (*)")
if not path:
return

View File

@@ -106,7 +106,7 @@ class ServerPreferencesPage(QtWidgets.QWidget, Ui_ServerPreferencesPageWidget):
filter = ""
if sys.platform.startswith("win"):
filter = "Executable (*.exe);;All files (*.*)"
filter = "Executable (*.exe);;All files (*)"
server_path = shutil.which("gns3server")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select the local server", server_path, filter)
if not path:
@@ -121,7 +121,7 @@ class ServerPreferencesPage(QtWidgets.QWidget, Ui_ServerPreferencesPageWidget):
filter = ""
if sys.platform.startswith("win"):
filter = "Executable (*.exe);;All files (*.*)"
filter = "Executable (*.exe);;All files (*)"
ubridge_path = shutil.which("ubridge")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select ubridge executable", ubridge_path, filter)

View File

@@ -146,7 +146,7 @@
},
"image": {
"type": "string",
"title": "Docker image in the Docker Hub"
"title": "Docker image on the Docker repository"
},
"start_command": {
"type": "string",

View File

@@ -168,7 +168,7 @@ else:
if sys.platform.startswith("linux"):
distro_name = distro.name()
if distro_name == "Debian" or distro_name == "Ubuntu" or distro_name == "LinuxMint":
if distro_name == "Debian" or distro_name == "Ubuntu" or distro_name == "Linux Mint":
if shutil.which("mate-terminal"):
DEFAULT_TELNET_CONSOLE_COMMAND = PRECONFIGURED_TELNET_CONSOLE_COMMANDS["Mate Terminal"]
else:

View File

@@ -47,6 +47,10 @@ class Style:
Sets the legacy GUI style.
"""
graphics_view = self._mw.uiGraphicsView
if hasattr(graphics_view, 'resetGridColors'):
graphics_view.resetGridColors()
self._mw.setStyleSheet("")
self._mw.uiNewProjectAction.setIcon(QtGui.QIcon(":/icons/new-project.svg"))
self._mw.uiOpenProjectAction.setIcon(QtGui.QIcon(":/icons/open.svg"))
@@ -99,6 +103,10 @@ class Style:
Sets the classic GUI style.
"""
graphics_view = self._mw.uiGraphicsView
if hasattr(graphics_view, 'resetGridColors'):
graphics_view.resetGridColors()
self._mw.setStyleSheet("")
self._mw.uiNewProjectAction.setIcon(self._getStyleIcon(":/classic_icons/new-project.svg", ":/classic_icons/new-project-hover.svg"))
self._mw.uiOpenProjectAction.setIcon(self._getStyleIcon(":/classic_icons/open.svg", ":/classic_icons/open-hover.svg"))
@@ -155,6 +163,10 @@ class Style:
Sets the charcoal GUI style.
"""
graphics_view = self._mw.uiGraphicsView
if hasattr(graphics_view, 'resetGridColors'):
graphics_view.resetGridColors()
style_file = QtCore.QFile(":/styles/charcoal.css")
style_file.open(QtCore.QFile.ReadOnly)
style = QtCore.QTextStream(style_file).readAll()

View File

@@ -110,7 +110,7 @@ class ConsoleThread(QtCore.QThread):
proc.wait() # wait for the terminal to open
try:
# use wmctrl to raise the window based on the node name
subprocess.run([wmctrl_path, "-a", self._name], env=os.environ)
subprocess.run([wmctrl_path, "-Fa", self._name], env=os.environ)
except OSError as e:
self.consoleError.emit("Count not focus on terminal window: '{}'".format(e))

View File

@@ -23,8 +23,8 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.52"
__version_info__ = (2, 2, 52, 0)
__version__ = "2.2.54"
__version_info__ = (2, 2, 54, 0)
if "dev" in __version__:
try:

View File

@@ -1,6 +1,6 @@
jsonschema>=4.23,<4.24
sentry-sdk>=2.17,<2.18 # optional dependency
psutil>=6.1.0
sentry-sdk>=2.26.1,<2.27 # optional dependency
psutil>=7.0.0
distro>=1.9.0
truststore>=0.10.0; python_version >= '3.10'
importlib-resources>=1.3; python_version < '3.9'