mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-29 23:10:31 +03:00
Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b5713df03 | ||
|
|
6df7dc4730 | ||
|
|
e84ef8bf13 | ||
|
|
f7703e3fa2 | ||
|
|
de8b9bc8f1 | ||
|
|
f21a530729 | ||
|
|
be2b5eecf6 | ||
|
|
2d4f6e6ecf | ||
|
|
c152de84de | ||
|
|
d34e7b377c | ||
|
|
74c55241cf | ||
|
|
6edb9c9303 | ||
|
|
5d14dd9ab8 | ||
|
|
0c7cae2222 | ||
|
|
9b882924c0 | ||
|
|
fccfc01f2e | ||
|
|
46872c664d | ||
|
|
89166b9d35 | ||
|
|
d0421e8b1f | ||
|
|
b35ce7303d | ||
|
|
47432568e6 | ||
|
|
42ea34ca6c | ||
|
|
9f3598d36d | ||
|
|
8df248a1e6 | ||
|
|
7196aeb3cf | ||
|
|
38657f4112 | ||
|
|
84017fa0f1 | ||
|
|
3aa5a5369f | ||
|
|
0ed791b946 | ||
|
|
133732b7ae | ||
|
|
2ed48def9f | ||
|
|
279a91d402 | ||
|
|
4906678d13 | ||
|
|
a5ff9318f0 | ||
|
|
faa802d59c | ||
|
|
01b5b8bfa8 | ||
|
|
b22c5c8442 | ||
|
|
141e7d8307 | ||
|
|
1e80354e4e | ||
|
|
d340b1f50a | ||
|
|
d7bb195610 | ||
|
|
d963dd4746 | ||
|
|
60addccd95 | ||
|
|
80b654ba53 | ||
|
|
b67a8c87a7 | ||
|
|
53ece94a08 | ||
|
|
a6c7e0be59 | ||
|
|
fcea25dcbb | ||
|
|
f29c065164 | ||
|
|
c6b5494ce6 | ||
|
|
02b14f6aea | ||
|
|
e2cc378aee | ||
|
|
812aedebe3 | ||
|
|
2f0d2063cf | ||
|
|
ce0515f0ae | ||
|
|
bc10c69a2d | ||
|
|
3707758388 | ||
|
|
8aaefac91b | ||
|
|
19157ab49d | ||
|
|
38b98cd883 | ||
|
|
e9419924c5 | ||
|
|
cf3c5c09fa | ||
|
|
9e89cf5ad5 | ||
|
|
131ef09b55 | ||
|
|
2df18ee04e | ||
|
|
854e1fded6 | ||
|
|
31711a9d4e | ||
|
|
fd2e236927 | ||
|
|
21409a899d | ||
|
|
25be9e7ec7 | ||
|
|
1260c2bc2d | ||
|
|
1441e38876 | ||
|
|
3c8cff20b7 | ||
|
|
f831d71c3f | ||
|
|
f71b6dcda1 | ||
|
|
62289e7be3 | ||
|
|
7447e9b7d4 | ||
|
|
c5961f400e | ||
|
|
6ca61905b2 | ||
|
|
130e91da76 | ||
|
|
bbc5b3e4ac | ||
|
|
2a72ad5e0b | ||
|
|
88ed9407b9 | ||
|
|
18be274fed | ||
|
|
fefda50378 | ||
|
|
3df374e784 | ||
|
|
04fb449b44 | ||
|
|
fc54b76ee1 | ||
|
|
59b284e18b | ||
|
|
1d4492c911 | ||
|
|
9d8b6a172e | ||
|
|
8c3ef7a968 | ||
|
|
947733aada | ||
|
|
a199fef03b |
@@ -10,7 +10,7 @@ jobs:
|
||||
name: Add issue to project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.4.0
|
||||
- uses: actions/add-to-project@v1.0.1
|
||||
with:
|
||||
project-url: https://github.com/orgs/GNS3/projects/3
|
||||
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}
|
||||
|
||||
73
.github/workflows/codeql.yml
vendored
73
.github/workflows/codeql.yml
vendored
@@ -15,62 +15,79 @@ on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '27 6 * * 2'
|
||||
- cron: '17 22 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
include:
|
||||
- language: python
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
2
.github/workflows/testing.yml
vendored
2
.github/workflows/testing.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build and run Docker image
|
||||
run: |
|
||||
docker build -t gns3-gui-test .
|
||||
|
||||
64
CHANGELOG
64
CHANGELOG
@@ -1,5 +1,69 @@
|
||||
# Change Log
|
||||
|
||||
## 2.2.50 21/10/2024
|
||||
|
||||
* Fix issue when pid file contains invalid data
|
||||
* Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423
|
||||
* Improve information provided when uploading invalid appliance image. Fixes #3637
|
||||
* Use "experimental features" option to force listening for HTTP notification streams. Ref #3579
|
||||
* Fix to allow packet capture on more than 6 links. Fixes #3594
|
||||
* Support for configuring MAC address in Docker containers
|
||||
* Add KRDC to pre-configured VNC console commands
|
||||
|
||||
## 2.2.49 06/08/2024
|
||||
|
||||
* Upgrade jsonschema and sentry-sdk packages
|
||||
* Upgrade to PyQt5 v5.15.11
|
||||
* Add shortcuts info dialog
|
||||
* Added Key Shortcuts
|
||||
|
||||
## 2.2.48.1 12/07/2024
|
||||
|
||||
* No changes
|
||||
|
||||
## 2.2.48 08/07/2024
|
||||
|
||||
* Use "experimental features" to allow bypassing hostname validation. Ref #3524
|
||||
* Update appliance_v8.json. Ref https://github.com/GNS3/gns3-registry/pull/897
|
||||
* Option to keep the compute IDs unchanged when exporting a project
|
||||
* Upgrade sentry-sdk and psutil packages
|
||||
* Switch to PyQt5 5.15.10 for macOS build
|
||||
|
||||
## 2.2.47 15/05/2024
|
||||
|
||||
* Remove maximum size for capture dialog. Ref #3576
|
||||
* Change sentry-sdk version
|
||||
* Upgrade aiohttp, sentry-sdk and truststore
|
||||
* Upgrade jsonschema and aiohttp
|
||||
* Drop Python 3.7
|
||||
* Remove dev requirements for Python 3.6
|
||||
* Add NAT symbols
|
||||
* Only show log message if event has "message"
|
||||
|
||||
## 2.2.46 26/02/2024
|
||||
|
||||
* Add GNS3 console command "env" to show what environment variables are used. Ref https://github.com/GNS3/gns3-server/issues/2306
|
||||
* Add CTRL+C shortcut to copy status bar message. Ref #3561
|
||||
* Key modifier (ALT) to ignore snap to grid. Fixes #3538
|
||||
* Increase timeout to 5s for status bar messages. The coordinates message has no timeout and can be reset when clicking on the scene. Ref #3561
|
||||
* Add reset GUI state feature. Ref #3549
|
||||
* Fix for hiding Windows terminal. Ref #3290
|
||||
* Drop support for Python 3.6
|
||||
* Upgrade sentry-sdk, psutil and distro dependencies
|
||||
|
||||
## 2.2.45 12/01/2024
|
||||
|
||||
* Add missing console_type values in appliance_v8.json. Ref https://github.com/GNS3/gns3-registry/issues/849
|
||||
* Handle moved project notifications on controller stream
|
||||
* Add debug for PATH env variable
|
||||
* Add custom executable paths on Windows
|
||||
* Add --suppressApplicationTitle for Windows terminal. Fixes https://github.com/GNS3/gns3-gui/issues/3544
|
||||
* Upgrade sentry-sdk and aiohttp
|
||||
|
||||
## 2.2.44.1 07/11/2023
|
||||
|
||||
* No changes
|
||||
|
||||
## 2.2.44 06/11/2023
|
||||
|
||||
* Fix timeout issue when creating Qemu disk image. Fixes https://github.com/GNS3/gns3-server/issues/2313
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Run tests inside a container
|
||||
FROM ubuntu:18.04
|
||||
FROM ubuntu:latest
|
||||
MAINTAINER GNS3 Team
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y --force-yes python3.6 python3-pyqt5 python3-pip python3-pyqt5.qtsvg python3-pyqt5.qtwebsockets python3.6-dev xvfb
|
||||
RUN apt-get install -y --force-yes python3 python3-pyqt5 python3-pip python3-pyqt5.qtsvg python3-pyqt5.qtwebsockets python3-dev xvfb
|
||||
RUN apt-get clean
|
||||
|
||||
ADD dev-requirements.txt /dev-requirements.txt
|
||||
ADD requirements.txt /requirements.txt
|
||||
RUN pip3 install --no-cache-dir -r /dev-requirements.txt
|
||||
RUN python3 -m pip install --break-system-packages --no-cache-dir -r /dev-requirements.txt
|
||||
|
||||
ADD . /src
|
||||
WORKDIR /src
|
||||
|
||||
CMD xvfb-run python3.6 -m pytest -vv
|
||||
CMD xvfb-run python3 -m pytest -vv
|
||||
|
||||
20
appveyor.yml
20
appveyor.yml
@@ -1,20 +0,0 @@
|
||||
version: '{build}-{branch}'
|
||||
|
||||
image: Visual Studio 2022
|
||||
|
||||
platform: x64
|
||||
|
||||
environment:
|
||||
PYTHON: "C:\\Python38-x64"
|
||||
DISTUTILS_USE_SDK: "1"
|
||||
|
||||
install:
|
||||
- cinst nmap
|
||||
- "%PYTHON%\\python.exe -m pip install -U pip setuptools" # upgrade pip & setuptools first
|
||||
- "%PYTHON%\\python.exe -m pip install -r dev-requirements.txt"
|
||||
- "%PYTHON%\\python.exe -m pip install -r win-requirements.txt"
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- "%PYTHON%\\python.exe -m pytest -v"
|
||||
@@ -1,6 +1,4 @@
|
||||
-rrequirements.txt
|
||||
|
||||
pytest==7.2.0; python_version >= '3.7'
|
||||
pytest==7.0.1; python_version < '3.7' # v7.0.1 is the last version to support Python 3.6
|
||||
flake8==5.0.4
|
||||
pytest-timeout==2.1.0
|
||||
pytest==8.3.2
|
||||
pytest-timeout==2.3.1
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
Handles commands typed in the GNS3 console.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import cmd
|
||||
import struct
|
||||
@@ -34,6 +35,14 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class ConsoleCmd(cmd.Cmd):
|
||||
|
||||
def do_env(self, args):
|
||||
"""
|
||||
Show the environment variables used by GNS3.
|
||||
"""
|
||||
|
||||
for key, val in os.environ.items():
|
||||
print("{}={}".format(key, val))
|
||||
|
||||
def do_version(self, args):
|
||||
"""
|
||||
Show the version of GNS3 and its dependencies.
|
||||
|
||||
@@ -25,6 +25,8 @@ from .qt import QtCore, QtNetwork, QtGui, QtWidgets, QtWebSockets, qpartial, qsl
|
||||
from .symbol import Symbol
|
||||
from .local_server_config import LocalServerConfig
|
||||
from .settings import LOCAL_SERVER_SETTINGS
|
||||
|
||||
from gns3.local_config import LocalConfig
|
||||
from gns3.utils import parse_version
|
||||
|
||||
import logging
|
||||
@@ -416,19 +418,23 @@ class Controller(QtCore.QObject):
|
||||
self._notification_stream = None
|
||||
|
||||
# Qt websocket before Qt 5.6 doesn't support auth
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0"):
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0") or LocalConfig.instance().experimental():
|
||||
|
||||
self._notification_stream = Controller.instance().createHTTPQuery("GET", "/notifications", self._endListenNotificationCallback,
|
||||
downloadProgressCallback=self._event_received,
|
||||
networkManager=self._notification_network_manager,
|
||||
timeout=None,
|
||||
showProgress=False,
|
||||
ignoreErrors=True)
|
||||
url = self._http_client.url() + '/notifications'
|
||||
log.info("Listening for controller notifications on '{}'".format(url))
|
||||
|
||||
else:
|
||||
self._notification_stream = self._http_client.connectWebSocket(self._websocket, "/notifications/ws")
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
log.info("Listening for controller notifications on '{}'".format(self._notification_stream.requestUrl().toString()))
|
||||
|
||||
def stopListenNotifications(self):
|
||||
if self._notification_stream:
|
||||
@@ -479,11 +485,21 @@ class Controller(QtCore.QObject):
|
||||
elif result["action"] == "compute.created" or result["action"] == "compute.updated":
|
||||
from .compute_manager import ComputeManager
|
||||
ComputeManager.instance().computeDataReceivedCallback(result["event"])
|
||||
elif result["action"] == "log.error":
|
||||
log.error(result["event"]["message"])
|
||||
elif result["action"] == "log.warning":
|
||||
log.warning(result["event"]["message"])
|
||||
elif result["action"] == "log.info":
|
||||
log.info(result["event"]["message"], extra={"show": True})
|
||||
elif result["action"] == "project.closed":
|
||||
from .topology import Topology
|
||||
project = Topology.instance().project()
|
||||
if project and project.id() == result["event"]["project_id"]:
|
||||
Topology.instance().setProject(None)
|
||||
elif result["action"] == "project.updated":
|
||||
from .topology import Topology
|
||||
project = Topology.instance().project()
|
||||
if project and project.id() == result["event"]["project_id"]:
|
||||
project.projectUpdatedCallback(result["event"])
|
||||
elif result["action"] == "log.error" and result["event"].get("message"):
|
||||
log.error(result["event"].get("message"))
|
||||
elif result["action"] == "log.warning" and result["event"].get("message"):
|
||||
log.warning(result["event"].get("message"))
|
||||
elif result["action"] == "log.info" and result["event"].get("message"):
|
||||
log.info(result["event"].get("message"), extra={"show": True})
|
||||
elif result["action"] == "ping":
|
||||
pass
|
||||
|
||||
@@ -50,7 +50,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://5c5fb544e56f9d41179e57bfff78e151@o19455.ingest.sentry.io/38506"
|
||||
DSN = "https://2f7ebda845810e764bfd049a40cc09e3@o19455.ingest.us.sentry.io/38506"
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -543,9 +543,19 @@ Usage: {}
|
||||
image = Image(self._appliance.template_type(), path, filename=disk["filename"])
|
||||
try:
|
||||
if "md5sum" in disk and image.md5sum != disk["md5sum"]:
|
||||
reply = QtWidgets.QMessageBox.question(self, "Add appliance",
|
||||
"This is not the correct file. The MD5 sum is {} and should be {}.\nDo you want to accept it at your own risks?".format(image.md5sum, disk["md5sum"]),
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
||||
reply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
"Add appliance",
|
||||
"This is not the correct file.\n\n"
|
||||
"MD5 checksum\n"
|
||||
f"actual:\t{image.md5sum}\n"
|
||||
f"expected:\t{disk['md5sum']}\n\n"
|
||||
"File size\n"
|
||||
f"actual:\t{image.filesize} bytes\n"
|
||||
f"expected:\t{disk['filesize']} bytes\n\n"
|
||||
"Do you want to accept it at your own risks?",
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
|
||||
)
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
except OSError as e:
|
||||
|
||||
@@ -126,20 +126,18 @@ class ExportProjectWizard(QtWidgets.QWizard, Ui_ExportProjectWizard):
|
||||
"""
|
||||
|
||||
if result:
|
||||
include_images = include_snapshots = reset_mac_addresses = keep_compute_ids = "no"
|
||||
if self.uiIncludeImagesCheckBox.isChecked():
|
||||
include_images = "yes"
|
||||
else:
|
||||
include_images = "no"
|
||||
if self.uiIncludeSnapshotsCheckBox.isChecked():
|
||||
include_snapshots = "yes"
|
||||
else:
|
||||
include_snapshots = "no"
|
||||
if self.uiResetMacAddressesCheckBox.isChecked():
|
||||
reset_mac_addresses = "yes"
|
||||
else:
|
||||
reset_mac_addresses = "no"
|
||||
if self.uiKeepComputeIdsCheckBox.isChecked():
|
||||
keep_compute_ids = "yes"
|
||||
|
||||
compression = self.uiCompressionComboBox.currentData()
|
||||
export_worker = ExportProjectWorker(self._project, self._path, include_images, include_snapshots, reset_mac_addresses, compression)
|
||||
export_worker = ExportProjectWorker(self._project, self._path, include_images, include_snapshots, reset_mac_addresses, keep_compute_ids, compression)
|
||||
progress_dialog = ProgressDialog(export_worker, "Exporting project", "Exporting portable project files...", "Cancel", parent=self, create_thread=False)
|
||||
progress_dialog.show()
|
||||
progress_dialog.exec_()
|
||||
|
||||
@@ -438,6 +438,8 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
item = self.itemAt(event.pos())
|
||||
if item and sip.isdeleted(item):
|
||||
return
|
||||
elif not item:
|
||||
self._main_window.uiStatusBar.clearMessage() # reset the status bar message when clicking on the scene
|
||||
|
||||
if item and (isinstance(item, LinkItem) or isinstance(item.parentItem(), LinkItem)):
|
||||
is_not_link = False
|
||||
@@ -595,7 +597,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
if factor < 0.10 or factor > 10:
|
||||
return
|
||||
self.scale(scale_factor, scale_factor)
|
||||
self._main_window.uiStatusBar.showMessage("Zoom: {}%".format(round(self.transform().m11() * 100)), 2000)
|
||||
self._main_window.uiStatusBar.showMessage("Zoom: {}%".format(round(self.transform().m11() * 100)), 5000)
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""
|
||||
@@ -640,7 +642,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
if item:
|
||||
# show item coords in the status bar
|
||||
coords = "X: {} Y: {} Z: {}".format(item.x(), item.y(), item.zValue())
|
||||
self._main_window.uiStatusBar.showMessage(coords, 2000)
|
||||
self._main_window.uiStatusBar.showMessage(coords)
|
||||
|
||||
# force the children to redraw because of a problem with QGraphicsEffect
|
||||
for item in self.scene().selectedItems():
|
||||
@@ -1030,7 +1032,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
if not new_hostname.strip():
|
||||
QtWidgets.QMessageBox.critical(self, "Change hostname", "Hostname cannot be blank")
|
||||
continue
|
||||
if hasattr(item.node(), "validateHostname"):
|
||||
if hasattr(item.node(), "validateHostname") and not LocalConfig.instance().experimental():
|
||||
if not item.node().validateHostname(new_hostname):
|
||||
QtWidgets.QMessageBox.critical(self, "Change hostname", "Invalid name detected for this node: {}".format(new_hostname))
|
||||
continue
|
||||
|
||||
@@ -44,6 +44,7 @@ class DrawingItem:
|
||||
def __init__(self, project=None, pos=None, drawing_id=None, svg=None, z=0, locked=False, rotation=0, **kws):
|
||||
self._id = drawing_id
|
||||
self._deleting = False
|
||||
self._allow_snap_to_grid = True
|
||||
self._locked = locked
|
||||
if self._id is None:
|
||||
self._id = str(uuid.uuid4())
|
||||
@@ -135,6 +136,9 @@ class DrawingItem:
|
||||
if self.rotation() < 360.0:
|
||||
self.setRotation(self.rotation() + 1)
|
||||
return True
|
||||
elif modifiers & QtCore.Qt.AltModifier:
|
||||
self._allow_snap_to_grid = False
|
||||
return True
|
||||
return False
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
@@ -147,6 +151,15 @@ class DrawingItem:
|
||||
if not self.handleKeyPressEvent(event):
|
||||
QtWidgets.QGraphicsItem.keyPressEvent(self, event)
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
"""
|
||||
Handles all key release events
|
||||
|
||||
:param event: QKeyEvent
|
||||
"""
|
||||
|
||||
self._allow_snap_to_grid = True
|
||||
|
||||
def __json__(self):
|
||||
data = {
|
||||
"drawing_id": self._id,
|
||||
@@ -213,7 +226,8 @@ class DrawingItem:
|
||||
|
||||
def itemChange(self, change, value):
|
||||
|
||||
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked():
|
||||
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked() \
|
||||
and self._allow_snap_to_grid:
|
||||
grid_size = self._graphics_view.drawingGridSize()
|
||||
mid_x = self.boundingRect().width() / 2
|
||||
value.setX((grid_size * round((value.x() + mid_x) / grid_size)) - mid_x)
|
||||
|
||||
@@ -51,6 +51,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
self._links = []
|
||||
self._symbol = None
|
||||
self._locked = False
|
||||
self._allow_snap_to_grid = True
|
||||
|
||||
# says if the attached node has been initialized
|
||||
# by the server.
|
||||
@@ -469,7 +470,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
:param value: value of the change
|
||||
"""
|
||||
|
||||
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked():
|
||||
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked() \
|
||||
and self._allow_snap_to_grid:
|
||||
grid_size = self._main_window.uiGraphicsView.nodeGridSize()
|
||||
mid_x = self.boundingRect().width() / 2
|
||||
value.setX((grid_size * round((value.x() + mid_x) / grid_size)) - mid_x)
|
||||
@@ -531,6 +533,27 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
for link in self._links:
|
||||
link.adjust()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""
|
||||
Handles all key press events
|
||||
|
||||
:param event: QKeyEvent
|
||||
"""
|
||||
|
||||
if event.modifiers() & QtCore.Qt.AltModifier:
|
||||
self._allow_snap_to_grid = False
|
||||
else:
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
"""
|
||||
Handles all key release events
|
||||
|
||||
:param event: QKeyEvent
|
||||
"""
|
||||
|
||||
self._allow_snap_to_grid = True
|
||||
|
||||
def locked(self):
|
||||
|
||||
return self._locked
|
||||
|
||||
@@ -23,7 +23,7 @@ import re
|
||||
from .qt import sip
|
||||
import uuid
|
||||
|
||||
from .qt import QtCore
|
||||
from .qt import QtCore, QtNetwork
|
||||
from .controller import Controller
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ class Link(QtCore.QObject):
|
||||
self._deleting = False
|
||||
self._capture_file_path = None
|
||||
self._capture_file = None
|
||||
self._network_manager = None
|
||||
self._response_stream = None
|
||||
self._capture_compute_id = None
|
||||
self._initialized = False
|
||||
@@ -117,12 +118,15 @@ class Link(QtCore.QObject):
|
||||
else:
|
||||
self._capture_file = QtCore.QFile(self._capture_file_path)
|
||||
self._capture_file.open(QtCore.QFile.WriteOnly)
|
||||
if self._network_manager is None:
|
||||
self._network_manager = QtNetwork.QNetworkAccessManager(self)
|
||||
self._response_stream = Controller.instance().get("/projects/{project_id}/links/{link_id}/pcap".format(project_id=self.project().id(), link_id=self._link_id),
|
||||
None,
|
||||
showProgress=False,
|
||||
downloadProgressCallback=self._downloadPcapProgress,
|
||||
ignoreErrors=True, # If something is wrong avoid disconnect us from server
|
||||
timeout=None)
|
||||
timeout=None,
|
||||
networkManager=self._network_manager)
|
||||
log.debug("Has successfully started capturing packets on link {} to '{}'".format(self._link_id, self._capture_file_path))
|
||||
else:
|
||||
self._response_stream = None
|
||||
|
||||
@@ -483,7 +483,7 @@ class LocalConfig(QtCore.QObject):
|
||||
|
||||
if os.path.exists(pid_path):
|
||||
try:
|
||||
with open(pid_path) as f:
|
||||
with open(pid_path, encoding="utf-8") as f:
|
||||
pid = int(f.read())
|
||||
if pid != my_pid:
|
||||
try:
|
||||
@@ -498,9 +498,17 @@ class LocalConfig(QtCore.QObject):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
except (OSError, ValueError) as e:
|
||||
except OSError as e:
|
||||
log.critical("Can't read pid file %s: %s", pid_path, str(e))
|
||||
return False
|
||||
except ValueError as e:
|
||||
log.warning("Invalid data in pid file %s: %s", pid_path, str(e))
|
||||
try:
|
||||
# try removing the file since it contains invalid data
|
||||
os.remove(pid_path)
|
||||
except OSError:
|
||||
log.critical("Can't remove pid file %s", pid_path)
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(pid_path, 'w+') as f:
|
||||
|
||||
14
gns3/main.py
14
gns3/main.py
@@ -142,6 +142,7 @@ def main():
|
||||
frozen_dirs = [
|
||||
frozen_dir,
|
||||
os.path.normpath(os.path.join(frozen_dir, 'dynamips')),
|
||||
os.path.normpath(os.path.join(frozen_dir, 'ubridge')),
|
||||
os.path.normpath(os.path.join(frozen_dir, 'vpcs')),
|
||||
os.path.normpath(os.path.join(frozen_dir, 'traceng'))
|
||||
]
|
||||
@@ -151,6 +152,7 @@ def main():
|
||||
if options.project:
|
||||
os.chdir(frozen_dir)
|
||||
|
||||
|
||||
def exceptionHook(exception, value, tb):
|
||||
|
||||
if exception == KeyboardInterrupt:
|
||||
@@ -182,9 +184,9 @@ def main():
|
||||
# catch exceptions to write them in a file
|
||||
sys.excepthook = exceptionHook
|
||||
|
||||
# we only support Python 3 version >= 3.4
|
||||
if sys.version_info < (3, 4):
|
||||
raise SystemExit("Python 3.4 or higher is required")
|
||||
# we only support Python 3 version >= 3.8
|
||||
if sys.version_info < (3, 8):
|
||||
raise SystemExit("Python 3.8 or higher is required")
|
||||
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.5.0"):
|
||||
raise SystemExit("Requirement is PyQt5 version 5.5.0 or higher, got version {}".format(QtCore.QT_VERSION_STR))
|
||||
@@ -219,8 +221,11 @@ def main():
|
||||
# hide the console
|
||||
# win32console.AllocConsole()
|
||||
console_window = win32console.GetConsoleWindow()
|
||||
if console_window:
|
||||
parent_window = win32gui.GetParent(console_window)
|
||||
if not parent_window and console_window:
|
||||
win32gui.ShowWindow(console_window, win32con.SW_HIDE)
|
||||
elif parent_window:
|
||||
win32gui.ShowWindow(parent_window, win32con.SW_HIDE)
|
||||
else:
|
||||
log.warning("Could not get the console window")
|
||||
except win32console.error as e:
|
||||
@@ -260,6 +265,7 @@ def main():
|
||||
log.info("GNS3 GUI version {}".format(__version__))
|
||||
log.info("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
|
||||
log.info("Application started with {}".format(" ".join(sys.argv)))
|
||||
log.debug("PATH={}".format(os.environ["PATH"]))
|
||||
|
||||
# update the exception file path to have it in the same directory as the settings file.
|
||||
exception_file_path = os.path.join(LocalConfig.instance().configDirectory(), exception_file_path)
|
||||
|
||||
@@ -136,6 +136,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
self._appliance_manager = ApplianceManager().instance()
|
||||
|
||||
# restore the geometry and state of the main window.
|
||||
self._save_gui_state_geometry = True
|
||||
self.restoreGeometry(QtCore.QByteArray().fromBase64(self._settings["geometry"].encode()))
|
||||
self.restoreState(QtCore.QByteArray().fromBase64(self._settings["state"].encode()))
|
||||
|
||||
@@ -232,6 +233,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
self.uiShowGridAction.triggered.connect(self._showGridActionSlot)
|
||||
self.uiSnapToGridAction.triggered.connect(self._snapToGridActionSlot)
|
||||
self.uiLockAllAction.triggered.connect(self._lockActionSlot)
|
||||
self.uiResetGUIStateAction.triggered.connect(self._resetGUIState)
|
||||
self.uiResetDocksAction.triggered.connect(self._resetDocksSlot)
|
||||
|
||||
# tool menu connections
|
||||
@@ -266,6 +268,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
self.uiExportDebugInformationAction.triggered.connect(self._exportDebugInformationSlot)
|
||||
self.uiDoctorAction.triggered.connect(self._doctorSlot)
|
||||
self.uiAcademyAction.triggered.connect(self._academyActionSlot)
|
||||
self.uiShortcutsAction.triggered.connect(self._shortcutsActionSlot)
|
||||
|
||||
# browsers tool bar connections
|
||||
self.uiBrowseRoutersAction.triggered.connect(self._browseRoutersActionSlot)
|
||||
@@ -366,6 +369,18 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
item.updateNode()
|
||||
item.update()
|
||||
|
||||
def _resetGUIState(self):
|
||||
"""
|
||||
Reset the GUI state.
|
||||
"""
|
||||
|
||||
self._save_gui_state_geometry = False
|
||||
self.close()
|
||||
if hasattr(sys, "frozen"):
|
||||
QtCore.QProcess.startDetached(os.path.abspath(sys.executable), sys.argv)
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, "GUI state","The GUI state has been reset, please restart the application")
|
||||
|
||||
def _resetDocksSlot(self):
|
||||
"""
|
||||
Reset the dock widgets.
|
||||
@@ -965,6 +980,15 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
# start and connect to the local server if needed
|
||||
LocalServer.instance().localServerAutoStartIfRequired()
|
||||
|
||||
def _shortcutsActionSlot(self):
|
||||
|
||||
shortcuts_text = ""
|
||||
for action in self.findChildren(QtWidgets.QAction):
|
||||
shortcut = action.shortcut().toString()
|
||||
if shortcut:
|
||||
shortcuts_text += f"{action.toolTip()}: {shortcut}\n"
|
||||
QtWidgets.QMessageBox.information(self, "Shortcuts", shortcuts_text)
|
||||
|
||||
def _aboutQtActionSlot(self):
|
||||
"""
|
||||
Slot to display the Qt About dialog.
|
||||
@@ -1113,6 +1137,10 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
if self.uiAddLinkAction.isChecked() and key == QtCore.Qt.Key_Escape:
|
||||
self.uiAddLinkAction.setChecked(False)
|
||||
self._addLinkActionSlot()
|
||||
elif key == QtCore.Qt.Key_C and event.modifiers() & QtCore.Qt.ControlModifier:
|
||||
status_bar_message = self.uiStatusBar.currentMessage()
|
||||
if status_bar_message:
|
||||
QtWidgets.QApplication.clipboard().setText(status_bar_message)
|
||||
else:
|
||||
super().keyPressEvent(event)
|
||||
|
||||
@@ -1149,8 +1177,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
|
||||
log.debug("_finish_application_closing")
|
||||
|
||||
self._settings["geometry"] = bytes(self.saveGeometry().toBase64()).decode()
|
||||
self._settings["state"] = bytes(self.saveState().toBase64()).decode()
|
||||
if self._save_gui_state_geometry:
|
||||
self._settings["geometry"] = bytes(self.saveGeometry().toBase64()).decode()
|
||||
self._settings["state"] = bytes(self.saveState().toBase64()).decode()
|
||||
else:
|
||||
self._settings["geometry"] = ""
|
||||
self._settings["state"] = ""
|
||||
self.setSettings(self._settings)
|
||||
|
||||
Controller.instance().stopListenNotifications()
|
||||
|
||||
@@ -73,7 +73,7 @@ class Nat(Node):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/cloud.svg"
|
||||
return ":/symbols/nat.svg"
|
||||
|
||||
@staticmethod
|
||||
def categories():
|
||||
|
||||
@@ -42,6 +42,7 @@ class DockerVM(Node):
|
||||
docker_vm_settings = {"image": "",
|
||||
"usage": "",
|
||||
"adapters": DOCKER_CONTAINER_SETTINGS["adapters"],
|
||||
"mac_address": DOCKER_CONTAINER_SETTINGS["mac_address"],
|
||||
"custom_adapters": DOCKER_CONTAINER_SETTINGS["custom_adapters"],
|
||||
"start_command": DOCKER_CONTAINER_SETTINGS["start_command"],
|
||||
"environment": DOCKER_CONTAINER_SETTINGS["environment"],
|
||||
@@ -88,6 +89,9 @@ class DockerVM(Node):
|
||||
port_name=port.name(),
|
||||
port_description=port.description())
|
||||
|
||||
if port.macAddress():
|
||||
port_info += " MAC address is {mac_address}\n".format(mac_address=port.macAddress())
|
||||
|
||||
usage = "\n" + self._settings.get("usage")
|
||||
return info + port_info + usage
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
Configuration page for Docker images.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.node import Node
|
||||
from gns3.dialogs.custom_adapters_configuration_dialog import CustomAdaptersConfigurationDialog
|
||||
@@ -69,15 +71,25 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
|
||||
if self._node:
|
||||
adapters = self._settings["adapters"]
|
||||
base_mac_address = self._settings["mac_address"]
|
||||
else:
|
||||
adapters = self.uiAdapterSpinBox.value()
|
||||
mac = self.uiMacAddrLineEdit.text()
|
||||
if mac != ":::::":
|
||||
if not re.search(r"""^([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}$""", mac):
|
||||
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hh:hh:hh:hh:hh:hh)")
|
||||
return
|
||||
else:
|
||||
base_mac_address = mac
|
||||
else:
|
||||
base_mac_address = ""
|
||||
|
||||
ports = []
|
||||
for adapter_number in range(0, adapters):
|
||||
port_name = "eth{}".format(adapter_number)
|
||||
ports.append(port_name)
|
||||
|
||||
dialog = CustomAdaptersConfigurationDialog(ports, self._custom_adapters, parent=self)
|
||||
dialog = CustomAdaptersConfigurationDialog(ports, self._custom_adapters, "TAP", {"TAP": "Default"}, base_mac_address, parent=self)
|
||||
dialog.show()
|
||||
dialog.exec_()
|
||||
|
||||
@@ -150,6 +162,13 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
self.uiSymbolLineEdit.hide()
|
||||
self.uiSymbolToolButton.hide()
|
||||
|
||||
# load the MAC address setting
|
||||
self.uiMacAddrLineEdit.setInputMask("HH:HH:HH:HH:HH:HH;_")
|
||||
if settings["mac_address"]:
|
||||
self.uiMacAddrLineEdit.setText(settings["mac_address"])
|
||||
else:
|
||||
self.uiMacAddrLineEdit.clear()
|
||||
|
||||
self.uiUsageTextEdit.setPlainText(settings["usage"])
|
||||
|
||||
def _networkConfigEditSlot(self):
|
||||
@@ -199,6 +218,18 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
else:
|
||||
settings["name"] = name
|
||||
|
||||
# check and save the MAC address
|
||||
mac = self.uiMacAddrLineEdit.text()
|
||||
if mac != ":::::":
|
||||
if not re.search(r"""^([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}$""", mac):
|
||||
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hh:hh:hh:hh:hh:hh)")
|
||||
if node:
|
||||
raise ConfigurationError()
|
||||
else:
|
||||
settings["mac_address"] = mac
|
||||
else:
|
||||
settings["mac_address"] = None
|
||||
|
||||
if not node:
|
||||
# these are template settings
|
||||
settings["category"] = self.uiCategoryComboBox.itemData(self.uiCategoryComboBox.currentIndex())
|
||||
|
||||
@@ -35,6 +35,7 @@ DOCKER_CONTAINER_SETTINGS = {
|
||||
"name": "",
|
||||
"image": "",
|
||||
"adapters": 1,
|
||||
"mac_address": "",
|
||||
"custom_adapters": [],
|
||||
"environment": "",
|
||||
"console_type": "telnet",
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>938</width>
|
||||
<height>872</height>
|
||||
<width>504</width>
|
||||
<height>560</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -103,27 +103,37 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="uiMacAddrLabel">
|
||||
<property name="text">
|
||||
<string>Base MAC:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="uiMacAddrLineEdit"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="uiCustomAdaptersLabel">
|
||||
<property name="text">
|
||||
<string>Custom adapters:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QPushButton" name="uiCustomAdaptersConfigurationPushButton">
|
||||
<property name="text">
|
||||
<string>&Configure custom adapters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="uiConsoleTypeLabel">
|
||||
<property name="text">
|
||||
<string>Console type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
@@ -166,14 +176,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="uiConsoleResolutionLabel">
|
||||
<property name="text">
|
||||
<string>VNC console resolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="uiConsoleResolutionComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -227,14 +237,14 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>HTTP port in the container:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="uiConsoleHttpPortSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
@@ -244,17 +254,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>HTTP path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QLineEdit" name="uiHttpConsolePathLineEdit"/>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="uiEnvironmentLabel">
|
||||
<property name="text">
|
||||
<string>Environment variables:
|
||||
@@ -268,17 +278,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="QTextEdit" name="uiEnvironmentTextEdit"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="uiNetworkConfigLabel">
|
||||
<property name="text">
|
||||
<string>Network configuration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QPushButton" name="uiNetworkConfigEditButton">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/docker/ui/docker_vm_configuration_page.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_dockerVMConfigPageWidget(object):
|
||||
def setupUi(self, dockerVMConfigPageWidget):
|
||||
dockerVMConfigPageWidget.setObjectName("dockerVMConfigPageWidget")
|
||||
dockerVMConfigPageWidget.resize(938, 872)
|
||||
dockerVMConfigPageWidget.resize(504, 560)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(dockerVMConfigPageWidget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.uiTabWidget = QtWidgets.QTabWidget(dockerVMConfigPageWidget)
|
||||
@@ -67,15 +67,21 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiAdapterSpinBox.setMinimum(1)
|
||||
self.uiAdapterSpinBox.setObjectName("uiAdapterSpinBox")
|
||||
self.gridLayout.addWidget(self.uiAdapterSpinBox, 5, 1, 1, 1)
|
||||
self.uiMacAddrLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiMacAddrLabel.setObjectName("uiMacAddrLabel")
|
||||
self.gridLayout.addWidget(self.uiMacAddrLabel, 6, 0, 1, 1)
|
||||
self.uiMacAddrLineEdit = QtWidgets.QLineEdit(self.tab)
|
||||
self.uiMacAddrLineEdit.setObjectName("uiMacAddrLineEdit")
|
||||
self.gridLayout.addWidget(self.uiMacAddrLineEdit, 6, 1, 1, 1)
|
||||
self.uiCustomAdaptersLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiCustomAdaptersLabel.setObjectName("uiCustomAdaptersLabel")
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersLabel, 6, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersLabel, 7, 0, 1, 1)
|
||||
self.uiCustomAdaptersConfigurationPushButton = QtWidgets.QPushButton(self.tab)
|
||||
self.uiCustomAdaptersConfigurationPushButton.setObjectName("uiCustomAdaptersConfigurationPushButton")
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersConfigurationPushButton, 6, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersConfigurationPushButton, 7, 1, 1, 1)
|
||||
self.uiConsoleTypeLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiConsoleTypeLabel.setObjectName("uiConsoleTypeLabel")
|
||||
self.gridLayout.addWidget(self.uiConsoleTypeLabel, 7, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleTypeLabel, 8, 0, 1, 1)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
@@ -90,10 +96,10 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiConsoleAutoStartCheckBox = QtWidgets.QCheckBox(self.tab)
|
||||
self.uiConsoleAutoStartCheckBox.setObjectName("uiConsoleAutoStartCheckBox")
|
||||
self.horizontalLayout.addWidget(self.uiConsoleAutoStartCheckBox)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 8, 1, 1, 1)
|
||||
self.uiConsoleResolutionLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiConsoleResolutionLabel.setObjectName("uiConsoleResolutionLabel")
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionLabel, 8, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionLabel, 9, 0, 1, 1)
|
||||
self.uiConsoleResolutionComboBox = QtWidgets.QComboBox(self.tab)
|
||||
self.uiConsoleResolutionComboBox.setObjectName("uiConsoleResolutionComboBox")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
@@ -106,35 +112,35 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionComboBox, 8, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionComboBox, 9, 1, 1, 1)
|
||||
self.label = QtWidgets.QLabel(self.tab)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout.addWidget(self.label, 9, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.label, 10, 0, 1, 1)
|
||||
self.uiConsoleHttpPortSpinBox = QtWidgets.QSpinBox(self.tab)
|
||||
self.uiConsoleHttpPortSpinBox.setMinimum(1)
|
||||
self.uiConsoleHttpPortSpinBox.setMaximum(65535)
|
||||
self.uiConsoleHttpPortSpinBox.setObjectName("uiConsoleHttpPortSpinBox")
|
||||
self.gridLayout.addWidget(self.uiConsoleHttpPortSpinBox, 9, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleHttpPortSpinBox, 10, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(self.tab)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 10, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.label_2, 11, 0, 1, 1)
|
||||
self.uiHttpConsolePathLineEdit = QtWidgets.QLineEdit(self.tab)
|
||||
self.uiHttpConsolePathLineEdit.setObjectName("uiHttpConsolePathLineEdit")
|
||||
self.gridLayout.addWidget(self.uiHttpConsolePathLineEdit, 10, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiHttpConsolePathLineEdit, 11, 1, 1, 1)
|
||||
self.uiEnvironmentLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiEnvironmentLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.uiEnvironmentLabel.setWordWrap(False)
|
||||
self.uiEnvironmentLabel.setObjectName("uiEnvironmentLabel")
|
||||
self.gridLayout.addWidget(self.uiEnvironmentLabel, 11, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiEnvironmentLabel, 12, 0, 1, 1)
|
||||
self.uiEnvironmentTextEdit = QtWidgets.QTextEdit(self.tab)
|
||||
self.uiEnvironmentTextEdit.setObjectName("uiEnvironmentTextEdit")
|
||||
self.gridLayout.addWidget(self.uiEnvironmentTextEdit, 11, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiEnvironmentTextEdit, 12, 1, 1, 1)
|
||||
self.uiNetworkConfigLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiNetworkConfigLabel.setObjectName("uiNetworkConfigLabel")
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigLabel, 12, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigLabel, 13, 0, 1, 1)
|
||||
self.uiNetworkConfigEditButton = QtWidgets.QPushButton(self.tab)
|
||||
self.uiNetworkConfigEditButton.setObjectName("uiNetworkConfigEditButton")
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigEditButton, 12, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigEditButton, 13, 1, 1, 1)
|
||||
self.uiTabWidget.addTab(self.tab, "")
|
||||
self.tab_2 = QtWidgets.QWidget()
|
||||
self.tab_2.setObjectName("tab_2")
|
||||
@@ -186,6 +192,7 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiSymbolToolButton.setText(_translate("dockerVMConfigPageWidget", "&Browse..."))
|
||||
self.uiCMDLabel.setText(_translate("dockerVMConfigPageWidget", "Start command:"))
|
||||
self.uiAdapterLabel.setText(_translate("dockerVMConfigPageWidget", "Adapters:"))
|
||||
self.uiMacAddrLabel.setText(_translate("dockerVMConfigPageWidget", "Base MAC:"))
|
||||
self.uiCustomAdaptersLabel.setText(_translate("dockerVMConfigPageWidget", "Custom adapters:"))
|
||||
self.uiCustomAdaptersConfigurationPushButton.setText(_translate("dockerVMConfigPageWidget", "&Configure custom adapters"))
|
||||
self.uiConsoleTypeLabel.setText(_translate("dockerVMConfigPageWidget", "Console type:"))
|
||||
|
||||
@@ -24,6 +24,7 @@ import re
|
||||
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from gns3.local_server import LocalServer
|
||||
from gns3.local_config import LocalConfig
|
||||
from gns3.dialogs.node_properties_dialog import ConfigurationError
|
||||
from gns3.dialogs.symbol_selection_dialog import SymbolSelectionDialog
|
||||
from gns3.controller import Controller
|
||||
@@ -488,7 +489,7 @@ class IOSRouterConfigurationPage(QtWidgets.QWidget, Ui_iosRouterConfigPageWidget
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "IOS router name cannot be empty!")
|
||||
elif node and not node.validateHostname(name):
|
||||
elif node and not node.validateHostname(name) and not LocalConfig.instance().experimental():
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Invalid name detected for IOS router: {}".format(name))
|
||||
else:
|
||||
settings["name"] = name
|
||||
|
||||
@@ -23,6 +23,7 @@ import os
|
||||
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.local_server import LocalServer
|
||||
from gns3.local_config import LocalConfig
|
||||
from gns3.dialogs.node_properties_dialog import ConfigurationError
|
||||
from gns3.dialogs.symbol_selection_dialog import SymbolSelectionDialog
|
||||
from gns3.node import Node
|
||||
@@ -245,7 +246,7 @@ class iouDeviceConfigurationPage(QtWidgets.QWidget, Ui_iouDeviceConfigPageWidget
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "IOU device name cannot be empty!")
|
||||
elif node and not node.validateHostname(name):
|
||||
elif node and not node.validateHostname(name) and not LocalConfig.instance().experimental():
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Invalid name detected for IOU device: {}".format(name))
|
||||
else:
|
||||
settings["name"] = name
|
||||
|
||||
@@ -475,9 +475,9 @@ class Project(QtCore.QObject):
|
||||
"variables": self._variables,
|
||||
"supplier": self._supplier
|
||||
}
|
||||
self.put("", self._projectUpdatedCallback, body=body)
|
||||
self.put("", self.projectUpdatedCallback, body=body)
|
||||
|
||||
def _projectUpdatedCallback(self, result, error=False, **kwargs):
|
||||
def projectUpdatedCallback(self, result, error=False, **kwargs):
|
||||
if error:
|
||||
self.project_creation_error_signal.emit(result["message"])
|
||||
return
|
||||
@@ -627,21 +627,24 @@ class Project(QtCore.QObject):
|
||||
return
|
||||
|
||||
# Qt websocket before Qt 5.6 doesn't support auth
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0"):
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0") or LocalConfig.instance().experimental():
|
||||
path = "/projects/{project_id}/notifications".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().createHTTPQuery("GET", path, self._endListenNotificationCallback,
|
||||
downloadProgressCallback=self._event_received,
|
||||
networkManager=self._notification_network_manager,
|
||||
timeout=None,
|
||||
showProgress=False,
|
||||
ignoreErrors=True)
|
||||
downloadProgressCallback=self._event_received,
|
||||
networkManager=self._notification_network_manager,
|
||||
timeout=None,
|
||||
showProgress=False,
|
||||
ignoreErrors=True)
|
||||
url = Controller.instance().getHttpClient().url() + path
|
||||
log.info("Listening for project notifications on '{}'".format(url))
|
||||
|
||||
else:
|
||||
path = "/projects/{project_id}/notifications/ws".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().httpClient().connectWebSocket(self._websocket, path)
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
path = "/projects/{project_id}/notifications/ws".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().httpClient().connectWebSocket(self._websocket, path)
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
log.info("Listening for project notifications on '{}'".format(self._notification_stream.requestUrl().toString()))
|
||||
|
||||
def _endListenNotificationCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
@@ -712,17 +715,20 @@ class Project(QtCore.QObject):
|
||||
drawing = Topology.instance().getDrawingFromUuid(result["event"]["drawing_id"])
|
||||
if drawing is not None:
|
||||
drawing.delete(skip_controller=True)
|
||||
# project.closed and project.updated notifications have been moved to the controller
|
||||
# because they are not project specific, keeping it there for backward compatibility
|
||||
# when connected to an older controller version
|
||||
elif result["action"] == "project.closed":
|
||||
Topology.instance().setProject(None)
|
||||
elif result["action"] == "project.updated":
|
||||
self._projectUpdatedCallback(result["event"])
|
||||
self.projectUpdatedCallback(result["event"])
|
||||
elif result["action"] == "snapshot.restored":
|
||||
Topology.instance().restoreSnapshot(result["event"]["project_id"])
|
||||
elif result["action"] == "log.error":
|
||||
log.error(result["event"]["message"])
|
||||
elif result["action"] == "log.warning":
|
||||
log.warning(result["event"]["message"])
|
||||
elif result["action"] == "log.info":
|
||||
log.info(result["event"]["message"], extra={"show": True})
|
||||
elif result["action"] == "log.error" and result["event"].get("message"):
|
||||
log.error(result["event"].get("message"))
|
||||
elif result["action"] == "log.warning" and result["event"].get("message"):
|
||||
log.warning(result["event"].get("message"))
|
||||
elif result["action"] == "log.info" and result["event"].get("message"):
|
||||
log.info(result["event"].get("message"), extra={"show": True})
|
||||
elif result["action"] == "ping":
|
||||
pass
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"enum": [
|
||||
"router",
|
||||
"multilayer_switch",
|
||||
"switch",
|
||||
"firewall",
|
||||
"guest"
|
||||
]
|
||||
@@ -57,7 +58,8 @@
|
||||
"telnet",
|
||||
"vnc",
|
||||
"http",
|
||||
"https"
|
||||
"https",
|
||||
"none"
|
||||
],
|
||||
"title": "Type of console"
|
||||
},
|
||||
@@ -502,7 +504,8 @@
|
||||
"telnet",
|
||||
"vnc",
|
||||
"spice",
|
||||
"spice+agent"
|
||||
"spice+agent",
|
||||
"none"
|
||||
],
|
||||
"title": "Type of console connection for the administration of the appliance"
|
||||
},
|
||||
@@ -718,174 +721,174 @@
|
||||
"template_properties"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"images": {
|
||||
"type": "array",
|
||||
"title": "Images for this appliance",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"title": "An image file",
|
||||
"properties": {
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"title": "Filename"
|
||||
},
|
||||
"images": {
|
||||
"type": "array",
|
||||
"title": "Images for this appliance",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"title": "An image file",
|
||||
"properties": {
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"title": "Filename"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"title": "Version of the image file"
|
||||
},
|
||||
"md5sum": {
|
||||
"type": "string",
|
||||
"title": "MD5 cheksum of the image file",
|
||||
"pattern": "^[a-f0-9]{32}$"
|
||||
},
|
||||
"checksum": {
|
||||
"type": "string",
|
||||
"title": "checksum of the image file"
|
||||
},
|
||||
"checksum_type": {
|
||||
"title": "checksum type of the image file",
|
||||
"enum": [
|
||||
"md5"
|
||||
]
|
||||
},
|
||||
"filesize": {
|
||||
"type": "integer",
|
||||
"title": "File size in bytes of the image file"
|
||||
},
|
||||
"download_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"title": "Download URL where you can download the image file from a browser"
|
||||
},
|
||||
"direct_download_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"title": "Optional. Non authenticated URL to the image file where you can download the image directly"
|
||||
},
|
||||
"compression": {
|
||||
"enum": [
|
||||
"bzip2",
|
||||
"gzip",
|
||||
"lzma",
|
||||
"xz",
|
||||
"rar",
|
||||
"zip",
|
||||
"7z"
|
||||
],
|
||||
"title": "Optional, compression type of direct download URL image."
|
||||
},
|
||||
"compression_target": {
|
||||
"type": "string",
|
||||
"title": "Optional, file name of the image file inside the compressed file."
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"title": "Version of the image file"
|
||||
},
|
||||
"md5sum": {
|
||||
"type": "string",
|
||||
"title": "MD5 cheksum of the image file",
|
||||
"pattern": "^[a-f0-9]{32}$"
|
||||
},
|
||||
"checksum": {
|
||||
"type": "string",
|
||||
"title": "checksum of the image file"
|
||||
},
|
||||
"checksum_type": {
|
||||
"title": "checksum type of the image file",
|
||||
"enum": [
|
||||
"md5"
|
||||
]
|
||||
},
|
||||
"filesize": {
|
||||
"type": "integer",
|
||||
"title": "File size in bytes of the image file"
|
||||
},
|
||||
"download_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"title": "Download URL where you can download the image file from a browser"
|
||||
},
|
||||
"direct_download_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"title": "Optional. Non authenticated URL to the image file where you can download the image directly"
|
||||
},
|
||||
"compression": {
|
||||
"enum": [
|
||||
"bzip2",
|
||||
"gzip",
|
||||
"lzma",
|
||||
"xz",
|
||||
"rar",
|
||||
"zip",
|
||||
"7z"
|
||||
],
|
||||
"title": "Optional, compression type of direct download URL image."
|
||||
},
|
||||
"compression_target": {
|
||||
"type": "string",
|
||||
"title": "Optional, file name of the image file inside the compressed file."
|
||||
}
|
||||
},
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"filename",
|
||||
"version",
|
||||
"md5sum",
|
||||
"filesize"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"filename",
|
||||
"version",
|
||||
"checksum",
|
||||
"filesize"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"type": "array",
|
||||
"title": "Versions of the appliance",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"title": "A version of the appliance",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Name of the version"
|
||||
},
|
||||
"settings": {
|
||||
"type": "string",
|
||||
"title": "Template settings to use to run the version"
|
||||
},
|
||||
"category": {
|
||||
"$ref": "#/definitions/categories",
|
||||
"title": "Category of the version"
|
||||
},
|
||||
"installation_instructions": {
|
||||
"type": "string",
|
||||
"title": "Optional installation instructions for the version"
|
||||
},
|
||||
"usage": {
|
||||
"type": "string",
|
||||
"title": "Optional instructions about using the version"
|
||||
},
|
||||
"default_username": {
|
||||
"type": "string",
|
||||
"title": "Default username for the version"
|
||||
},
|
||||
"default_password": {
|
||||
"type": "string",
|
||||
"title": "Default password for the version"
|
||||
},
|
||||
"symbol": {
|
||||
"type": "string",
|
||||
"title": "An optional symbol for the version"
|
||||
},
|
||||
"images": {
|
||||
"type": "object",
|
||||
"title": "Images used for this version",
|
||||
"properties": {
|
||||
"kernel_image": {
|
||||
"type": "string",
|
||||
"title": "Kernel image (Qemu only)"
|
||||
},
|
||||
"initrd": {
|
||||
"type": "string",
|
||||
"title": "Initrd disk image (Qemu only)"
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"title": "OS image (IOU and Dynamips only)"
|
||||
},
|
||||
"bios_image": {
|
||||
"type": "string",
|
||||
"title": "Bios image (Qemu only)"
|
||||
},
|
||||
"hda_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hda disk image (Qemu only)"
|
||||
},
|
||||
"hdb_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdc disk image (Qemu only)"
|
||||
},
|
||||
"hdc_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdd disk image (Qemu only)"
|
||||
},
|
||||
"hdd_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdd disk image (Qemu only)"
|
||||
},
|
||||
"cdrom_image": {
|
||||
"type": "string",
|
||||
"title": "cdrom image (Qemu only)"
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"filename",
|
||||
"version",
|
||||
"md5sum",
|
||||
"filesize"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"filename",
|
||||
"version",
|
||||
"checksum",
|
||||
"filesize"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"versions": {
|
||||
"type": "array",
|
||||
"title": "Versions of the appliance",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"title": "A version of the appliance",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Name of the version"
|
||||
},
|
||||
"settings": {
|
||||
"type": "string",
|
||||
"title": "Template settings to use to run the version"
|
||||
},
|
||||
"category": {
|
||||
"$ref": "#/definitions/categories",
|
||||
"title": "Category of the version"
|
||||
},
|
||||
"installation_instructions": {
|
||||
"type": "string",
|
||||
"title": "Optional installation instructions for the version"
|
||||
},
|
||||
"usage": {
|
||||
"type": "string",
|
||||
"title": "Optional instructions about using the version"
|
||||
},
|
||||
"default_username": {
|
||||
"type": "string",
|
||||
"title": "Default username for the version"
|
||||
},
|
||||
"default_password": {
|
||||
"type": "string",
|
||||
"title": "Default password for the version"
|
||||
},
|
||||
"symbol": {
|
||||
"type": "string",
|
||||
"title": "An optional symbol for the version"
|
||||
},
|
||||
"images": {
|
||||
"type": "object",
|
||||
"title": "Images used for this version",
|
||||
"properties": {
|
||||
"kernel_image": {
|
||||
"type": "string",
|
||||
"title": "Kernel image (Qemu only)"
|
||||
},
|
||||
"initrd": {
|
||||
"type": "string",
|
||||
"title": "Initrd disk image (Qemu only)"
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"title": "OS image (IOU and Dynamips only)"
|
||||
},
|
||||
"bios_image": {
|
||||
"type": "string",
|
||||
"title": "Bios image (Qemu only)"
|
||||
},
|
||||
"hda_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hda disk image (Qemu only)"
|
||||
},
|
||||
"hdb_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdc disk image (Qemu only)"
|
||||
},
|
||||
"hdc_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdd disk image (Qemu only)"
|
||||
},
|
||||
"hdd_disk_image": {
|
||||
"type": "string",
|
||||
"title": "Hdd disk image (Qemu only)"
|
||||
},
|
||||
"cdrom_image": {
|
||||
"type": "string",
|
||||
"title": "cdrom image (Qemu only)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -65,7 +65,7 @@ if sys.platform.startswith("win"):
|
||||
'SecureCRT (personal profile)': r'"{}\AppData\Local\VanDyke Software\SecureCRT\SecureCRT.exe" /T /N "{{name}}" /TELNET {{host}} {{port}}'.format(userprofile),
|
||||
'TeraTerm Pro': r'"{}\teraterm\ttermpro.exe" /W="{{name}}" /M="ttstart.macro" /T=1 {{host}} {{port}}'.format(program_files_x86),
|
||||
'Telnet': 'telnet {host} {port}',
|
||||
'Windows Terminal': 'wt.exe -w 1 new-tab --title {name} telnet {host} {port}',
|
||||
'Windows Terminal': 'wt.exe -w 1 new-tab --suppressApplicationTitle --title {name} telnet {host} {port}',
|
||||
'Xshell 4': r'"{}\NetSarang\Xshell 4\xshell.exe" -url telnet://{{host}}:{{port}}'.format(program_files_x86),
|
||||
'Xshell 5': r'"{}\NetSarang\Xshell 5\xshell.exe" -url telnet://{{host}}:{{port}} -newtab {{name}}'.format(program_files_x86),
|
||||
'ZOC 6': r'"{}\ZOC6\zoc.exe" "/TELNET:{{host}}:{{port}}" /TABBED "/TITLE:{{name}}"'.format(program_files_x86)}
|
||||
@@ -206,7 +206,8 @@ else:
|
||||
'TightVNC': 'vncviewer {host}:{port}',
|
||||
'Vinagre': 'vinagre {host}::{port}',
|
||||
'gvncviewer': 'gvncviewer {host}:{display}',
|
||||
'Remote Viewer': 'remote-viewer vnc://{host}:{port}'
|
||||
'Remote Viewer': 'remote-viewer vnc://{host}:{port}',
|
||||
'KRDC': 'krdc vnc://{host}:{port}'
|
||||
}
|
||||
|
||||
# default VNC console command on other systems
|
||||
@@ -287,7 +288,6 @@ GENERAL_SETTINGS = {
|
||||
"check_for_update": True,
|
||||
"overlay_notifications": True,
|
||||
"experimental_features": False,
|
||||
"stats_visitor_id": str(uuid.uuid4()), # An anonymous id for stats
|
||||
"last_check_for_update": 0,
|
||||
"telnet_console_command": DEFAULT_TELNET_CONSOLE_COMMAND,
|
||||
"vnc_console_command": DEFAULT_VNC_CONSOLE_COMMAND,
|
||||
|
||||
@@ -209,11 +209,11 @@ class Topology(QtCore.QObject):
|
||||
project.setId(project_settings["project_id"])
|
||||
self.setProject(project)
|
||||
project.load()
|
||||
self._main_window.uiStatusBar.showMessage("Project loaded", 2000)
|
||||
self._main_window.uiStatusBar.showMessage("Project loaded", 5000)
|
||||
else:
|
||||
self.setProject(project)
|
||||
project.create()
|
||||
self._main_window.uiStatusBar.showMessage("Project created", 2000)
|
||||
self._main_window.uiStatusBar.showMessage("Project created", 5000)
|
||||
return project
|
||||
|
||||
def restoreSnapshot(self, project_id):
|
||||
@@ -225,7 +225,7 @@ class Topology(QtCore.QObject):
|
||||
project = self._project
|
||||
self.setProject(project, snapshot=True)
|
||||
project.load()
|
||||
self._main_window.uiStatusBar.showMessage("Snapshot restored", 2000)
|
||||
self._main_window.uiStatusBar.showMessage("Snapshot restored", 5000)
|
||||
|
||||
def loadProject(self, path):
|
||||
"""
|
||||
@@ -241,7 +241,7 @@ class Topology(QtCore.QObject):
|
||||
from .project import Project
|
||||
self.setProject(Project())
|
||||
self._project.load(path)
|
||||
self._main_window.uiStatusBar.showMessage("Project loaded {}".format(path), 2000)
|
||||
self._main_window.uiStatusBar.showMessage("Project loaded {}".format(path), 5000)
|
||||
return True
|
||||
|
||||
def editReadme(self):
|
||||
|
||||
@@ -9,16 +9,10 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>147</height>
|
||||
<width>460</width>
|
||||
<height>142</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>147</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Packet capture</string>
|
||||
</property>
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/capture_dialog.ui'
|
||||
#
|
||||
# Created: Mon May 30 21:49:29 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_CaptureDialog(object):
|
||||
def setupUi(self, CaptureDialog):
|
||||
CaptureDialog.setObjectName("CaptureDialog")
|
||||
CaptureDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||
CaptureDialog.resize(500, 147)
|
||||
CaptureDialog.setMaximumSize(QtCore.QSize(500, 147))
|
||||
CaptureDialog.resize(460, 142)
|
||||
CaptureDialog.setModal(False)
|
||||
self.gridLayout = QtWidgets.QGridLayout(CaptureDialog)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
@@ -73,5 +74,4 @@ class Ui_CaptureDialog(object):
|
||||
self.uiLinkTypeLabel.setText(_translate("CaptureDialog", "Link type:"))
|
||||
self.uiFileNameLabel.setText(_translate("CaptureDialog", "File name:"))
|
||||
self.uiStartCommandCheckBox.setText(_translate("CaptureDialog", "Start the capture visualization program"))
|
||||
|
||||
from . import resources_rc
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
<width>602</width>
|
||||
<height>367</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -27,19 +27,6 @@
|
||||
<string>Please select the location, whether to include base images or not and the compression type.</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiPathLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
@@ -54,6 +41,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="uiResetMacAddressesCheckBox">
|
||||
<property name="text">
|
||||
<string>&Reset MAC addresses</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiPathLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiCompressionLabel">
|
||||
<property name="text">
|
||||
@@ -61,6 +68,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>247</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="uiCompressionComboBox"/>
|
||||
</item>
|
||||
@@ -78,23 +98,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>247</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="uiResetMacAddressesCheckBox">
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="uiKeepComputeIdsCheckBox">
|
||||
<property name="text">
|
||||
<string>&Reset MAC addresses</string>
|
||||
<string>&Keep the original compute IDs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/export_project_wizard.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.13.2
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@@ -14,20 +15,12 @@ class Ui_ExportProjectWizard(object):
|
||||
def setupUi(self, ExportProjectWizard):
|
||||
ExportProjectWizard.setObjectName("ExportProjectWizard")
|
||||
ExportProjectWizard.setWindowModality(QtCore.Qt.ApplicationModal)
|
||||
ExportProjectWizard.resize(900, 600)
|
||||
ExportProjectWizard.resize(602, 367)
|
||||
ExportProjectWizard.setOptions(QtWidgets.QWizard.HaveHelpButton)
|
||||
self.uiExportOptionsWizardPage = QtWidgets.QWizardPage()
|
||||
self.uiExportOptionsWizardPage.setObjectName("uiExportOptionsWizardPage")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiExportOptionsWizardPage)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiPathLabel = QtWidgets.QLabel(self.uiExportOptionsWizardPage)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPathLabel.sizePolicy().hasHeightForWidth())
|
||||
self.uiPathLabel.setSizePolicy(sizePolicy)
|
||||
self.uiPathLabel.setObjectName("uiPathLabel")
|
||||
self.gridLayout.addWidget(self.uiPathLabel, 0, 0, 1, 1)
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.uiPathLineEdit = QtWidgets.QLineEdit(self.uiExportOptionsWizardPage)
|
||||
@@ -37,9 +30,22 @@ class Ui_ExportProjectWizard(object):
|
||||
self.uiPathBrowserToolButton.setObjectName("uiPathBrowserToolButton")
|
||||
self.horizontalLayout_3.addWidget(self.uiPathBrowserToolButton)
|
||||
self.gridLayout.addLayout(self.horizontalLayout_3, 0, 1, 1, 2)
|
||||
self.uiResetMacAddressesCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
|
||||
self.uiResetMacAddressesCheckBox.setObjectName("uiResetMacAddressesCheckBox")
|
||||
self.gridLayout.addWidget(self.uiResetMacAddressesCheckBox, 5, 0, 1, 2)
|
||||
self.uiPathLabel = QtWidgets.QLabel(self.uiExportOptionsWizardPage)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPathLabel.sizePolicy().hasHeightForWidth())
|
||||
self.uiPathLabel.setSizePolicy(sizePolicy)
|
||||
self.uiPathLabel.setObjectName("uiPathLabel")
|
||||
self.gridLayout.addWidget(self.uiPathLabel, 0, 0, 1, 1)
|
||||
self.uiCompressionLabel = QtWidgets.QLabel(self.uiExportOptionsWizardPage)
|
||||
self.uiCompressionLabel.setObjectName("uiCompressionLabel")
|
||||
self.gridLayout.addWidget(self.uiCompressionLabel, 1, 0, 1, 1)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 247, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem, 7, 2, 1, 1)
|
||||
self.uiCompressionComboBox = QtWidgets.QComboBox(self.uiExportOptionsWizardPage)
|
||||
self.uiCompressionComboBox.setObjectName("uiCompressionComboBox")
|
||||
self.gridLayout.addWidget(self.uiCompressionComboBox, 1, 1, 1, 2)
|
||||
@@ -49,11 +55,9 @@ class Ui_ExportProjectWizard(object):
|
||||
self.uiIncludeSnapshotsCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
|
||||
self.uiIncludeSnapshotsCheckBox.setObjectName("uiIncludeSnapshotsCheckBox")
|
||||
self.gridLayout.addWidget(self.uiIncludeSnapshotsCheckBox, 4, 0, 1, 2)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 247, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem, 6, 2, 1, 1)
|
||||
self.uiResetMacAddressesCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
|
||||
self.uiResetMacAddressesCheckBox.setObjectName("uiResetMacAddressesCheckBox")
|
||||
self.gridLayout.addWidget(self.uiResetMacAddressesCheckBox, 5, 0, 1, 2)
|
||||
self.uiKeepComputeIdsCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
|
||||
self.uiKeepComputeIdsCheckBox.setObjectName("uiKeepComputeIdsCheckBox")
|
||||
self.gridLayout.addWidget(self.uiKeepComputeIdsCheckBox, 6, 0, 1, 3)
|
||||
ExportProjectWizard.addPage(self.uiExportOptionsWizardPage)
|
||||
self.uiProjectReadmeWizardPage = QtWidgets.QWizardPage()
|
||||
self.uiProjectReadmeWizardPage.setObjectName("uiProjectReadmeWizardPage")
|
||||
@@ -72,12 +76,13 @@ class Ui_ExportProjectWizard(object):
|
||||
ExportProjectWizard.setWindowTitle(_translate("ExportProjectWizard", "Export project"))
|
||||
self.uiExportOptionsWizardPage.setTitle(_translate("ExportProjectWizard", "Export project"))
|
||||
self.uiExportOptionsWizardPage.setSubTitle(_translate("ExportProjectWizard", "Please select the location, whether to include base images or not and the compression type."))
|
||||
self.uiPathLabel.setText(_translate("ExportProjectWizard", "Path:"))
|
||||
self.uiPathBrowserToolButton.setText(_translate("ExportProjectWizard", "Browse..."))
|
||||
self.uiResetMacAddressesCheckBox.setText(_translate("ExportProjectWizard", "&Reset MAC addresses"))
|
||||
self.uiPathLabel.setText(_translate("ExportProjectWizard", "Path:"))
|
||||
self.uiCompressionLabel.setText(_translate("ExportProjectWizard", "Compression:"))
|
||||
self.uiIncludeImagesCheckBox.setText(_translate("ExportProjectWizard", "&Include base images"))
|
||||
self.uiIncludeSnapshotsCheckBox.setText(_translate("ExportProjectWizard", "&Include snapshots"))
|
||||
self.uiResetMacAddressesCheckBox.setText(_translate("ExportProjectWizard", "&Reset MAC addresses"))
|
||||
self.uiKeepComputeIdsCheckBox.setText(_translate("ExportProjectWizard", "&Keep the original compute IDs"))
|
||||
self.uiProjectReadmeWizardPage.setTitle(_translate("ExportProjectWizard", "Readme file"))
|
||||
self.uiProjectReadmeWizardPage.setSubTitle(_translate("ExportProjectWizard", "Write a summary of the project."))
|
||||
self.uiReadmeTextEdit.setHtml(_translate("ExportProjectWizard", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
|
||||
@@ -1012,7 +1012,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="uiExperimentalFeaturesCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable experimental features (dangerous, restart required)</string>
|
||||
<string>Enable experimental features</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -598,7 +598,7 @@ class Ui_GeneralPreferencesPageWidget(object):
|
||||
self.uiCheckForUpdateCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Automatically check for update"))
|
||||
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 (dangerous, restart required)"))
|
||||
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"))
|
||||
|
||||
@@ -112,6 +112,7 @@ background-none;
|
||||
<addaction name="uiAcademyAction"/>
|
||||
<addaction name="uiDoctorAction"/>
|
||||
<addaction name="uiExportDebugInformationAction"/>
|
||||
<addaction name="uiShortcutsAction"/>
|
||||
<addaction name="uiAboutQtAction"/>
|
||||
<addaction name="uiAboutAction"/>
|
||||
</widget>
|
||||
@@ -138,6 +139,7 @@ background-none;
|
||||
<addaction name="uiShowPortNamesAction"/>
|
||||
<addaction name="uiLockAllAction"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="uiResetGUIStateAction"/>
|
||||
<addaction name="uiResetDocksAction"/>
|
||||
<addaction name="uiDocksMenu"/>
|
||||
</widget>
|
||||
@@ -643,6 +645,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Start/Resume all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+B</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiStopAllAction">
|
||||
<property name="enabled">
|
||||
@@ -662,6 +667,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Stop all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+E</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiConsoleAllAction">
|
||||
<property name="enabled">
|
||||
@@ -796,6 +804,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Suspend all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+J</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiAddNoteAction">
|
||||
<property name="checkable">
|
||||
@@ -1146,6 +1157,9 @@ background-none;
|
||||
<property name="text">
|
||||
<string>Fit in view</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiActionFullscreen">
|
||||
<property name="text">
|
||||
@@ -1300,6 +1314,16 @@ background-none;
|
||||
<string>Reset all console connections</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiResetGUIStateAction">
|
||||
<property name="text">
|
||||
<string>Reset GUI state</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiShortcutsAction">
|
||||
<property name="text">
|
||||
<string>&Shortcuts</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/main_window.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.14.1
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@@ -14,7 +15,7 @@ class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.setWindowModality(QtCore.Qt.NonModal)
|
||||
MainWindow.resize(986, 716)
|
||||
MainWindow.resize(986, 719)
|
||||
MainWindow.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||
MainWindow.setStyleSheet("#toolBar_Devices QToolButton {\n"
|
||||
"width: 50px;\n"
|
||||
@@ -450,11 +451,12 @@ class Ui_MainWindow(object):
|
||||
self.uiNewTemplateAction.setObjectName("uiNewTemplateAction")
|
||||
self.uiResetDocksAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiResetDocksAction.setObjectName("uiResetDocksAction")
|
||||
self.uiEditReadmeAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiEditReadmeAction.setIcon(icon31)
|
||||
self.uiEditReadmeAction.setObjectName("uiEditReadmeAction")
|
||||
self.uiResetConsoleAllAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiResetConsoleAllAction.setObjectName("uiResetConsoleAllAction")
|
||||
self.uiResetGUIStateAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiResetGUIStateAction.setObjectName("uiResetGUIStateAction")
|
||||
self.uiShortcutsAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiShortcutsAction.setObjectName("uiShortcutsAction")
|
||||
self.uiEditMenu.addAction(self.uiSelectAllAction)
|
||||
self.uiEditMenu.addAction(self.uiSelectNoneAction)
|
||||
self.uiEditMenu.addSeparator()
|
||||
@@ -479,6 +481,7 @@ class Ui_MainWindow(object):
|
||||
self.uiHelpMenu.addAction(self.uiAcademyAction)
|
||||
self.uiHelpMenu.addAction(self.uiDoctorAction)
|
||||
self.uiHelpMenu.addAction(self.uiExportDebugInformationAction)
|
||||
self.uiHelpMenu.addAction(self.uiShortcutsAction)
|
||||
self.uiHelpMenu.addAction(self.uiAboutQtAction)
|
||||
self.uiHelpMenu.addAction(self.uiAboutAction)
|
||||
self.uiViewMenu.addAction(self.uiActionFullscreen)
|
||||
@@ -495,6 +498,7 @@ class Ui_MainWindow(object):
|
||||
self.uiViewMenu.addAction(self.uiShowPortNamesAction)
|
||||
self.uiViewMenu.addAction(self.uiLockAllAction)
|
||||
self.uiViewMenu.addSeparator()
|
||||
self.uiViewMenu.addAction(self.uiResetGUIStateAction)
|
||||
self.uiViewMenu.addAction(self.uiResetDocksAction)
|
||||
self.uiViewMenu.addAction(self.uiDocksMenu.menuAction())
|
||||
self.uiControlMenu.addAction(self.uiStartAllAction)
|
||||
@@ -554,7 +558,7 @@ class Ui_MainWindow(object):
|
||||
self.uiAnnotationToolBar.addAction(self.uiScreenshotAction)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
self.uiQuitAction.triggered.connect(MainWindow.close)
|
||||
self.uiQuitAction.triggered.connect(MainWindow.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
MainWindow.setTabOrder(self.uiGraphicsView, self.uiNodesView)
|
||||
MainWindow.setTabOrder(self.uiNodesView, self.uiConsoleTextEdit)
|
||||
@@ -603,9 +607,11 @@ class Ui_MainWindow(object):
|
||||
self.uiStartAllAction.setText(_translate("MainWindow", "Start/Resume all nodes"))
|
||||
self.uiStartAllAction.setToolTip(_translate("MainWindow", "Start/Resume all nodes"))
|
||||
self.uiStartAllAction.setStatusTip(_translate("MainWindow", "Start/Resume all devices"))
|
||||
self.uiStartAllAction.setShortcut(_translate("MainWindow", "Ctrl+B"))
|
||||
self.uiStopAllAction.setText(_translate("MainWindow", "Stop all nodes"))
|
||||
self.uiStopAllAction.setToolTip(_translate("MainWindow", "Stop all nodes"))
|
||||
self.uiStopAllAction.setStatusTip(_translate("MainWindow", "Stop all devices"))
|
||||
self.uiStopAllAction.setShortcut(_translate("MainWindow", "Ctrl+E"))
|
||||
self.uiConsoleAllAction.setText(_translate("MainWindow", "Console connect to all nodes"))
|
||||
self.uiConsoleAllAction.setToolTip(_translate("MainWindow", "Console connect to all nodes"))
|
||||
self.uiConsoleAllAction.setStatusTip(_translate("MainWindow", "Console to all devices"))
|
||||
@@ -634,6 +640,7 @@ class Ui_MainWindow(object):
|
||||
self.uiSuspendAllAction.setText(_translate("MainWindow", "Suspend all nodes"))
|
||||
self.uiSuspendAllAction.setToolTip(_translate("MainWindow", "Suspend all nodes"))
|
||||
self.uiSuspendAllAction.setStatusTip(_translate("MainWindow", "Suspend all devices"))
|
||||
self.uiSuspendAllAction.setShortcut(_translate("MainWindow", "Ctrl+J"))
|
||||
self.uiAddNoteAction.setText(_translate("MainWindow", "Add note"))
|
||||
self.uiAddNoteAction.setToolTip(_translate("MainWindow", "Add a note"))
|
||||
self.uiAddNoteAction.setStatusTip(_translate("MainWindow", "Add a note"))
|
||||
@@ -701,6 +708,7 @@ class Ui_MainWindow(object):
|
||||
self.uiAddLinkAction.setToolTip(_translate("MainWindow", "Add a link"))
|
||||
self.uiAddLinkAction.setStatusTip(_translate("MainWindow", "Add a link"))
|
||||
self.uiFitInViewAction.setText(_translate("MainWindow", "Fit in view"))
|
||||
self.uiFitInViewAction.setShortcut(_translate("MainWindow", "Ctrl+1"))
|
||||
self.uiActionFullscreen.setText(_translate("MainWindow", "Fullscreen"))
|
||||
self.uiActionFullscreen.setShortcut(_translate("MainWindow", "Ctrl+F"))
|
||||
self.uiSetupWizard.setText(_translate("MainWindow", "&Setup Wizard"))
|
||||
@@ -721,9 +729,9 @@ class Ui_MainWindow(object):
|
||||
self.uiWebUIAction.setText(_translate("MainWindow", "Web UI - beta"))
|
||||
self.uiNewTemplateAction.setText(_translate("MainWindow", "New template"))
|
||||
self.uiResetDocksAction.setText(_translate("MainWindow", "Reset docks"))
|
||||
self.uiEditReadmeAction.setText(_translate("MainWindow", "Edit readme"))
|
||||
self.uiEditReadmeAction.setToolTip(_translate("MainWindow", "Edit readme"))
|
||||
self.uiResetConsoleAllAction.setText(_translate("MainWindow", "Reset all console connections"))
|
||||
self.uiResetGUIStateAction.setText(_translate("MainWindow", "Reset GUI state"))
|
||||
self.uiShortcutsAction.setText(_translate("MainWindow", "&Shortcuts"))
|
||||
from ..compute_summary_view import ComputeSummaryView
|
||||
from ..console_view import ConsoleView
|
||||
from ..graphics_view import GraphicsView
|
||||
|
||||
@@ -28,21 +28,24 @@ class ExportProjectWorker(QtCore.QObject):
|
||||
finished = QtCore.pyqtSignal()
|
||||
updated = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, project, path, include_images, include_snapshots, reset_mac_addresses, compression):
|
||||
def __init__(self, project, path, include_images, include_snapshots, reset_mac_addresses, keep_compute_ids, compression):
|
||||
super().__init__()
|
||||
self._project = project
|
||||
self._path = path
|
||||
self._include_images = include_images
|
||||
self._include_snapshots = include_snapshots
|
||||
self._reset_mac_addresses = reset_mac_addresses
|
||||
self._path = path
|
||||
self._keep_compute_ids = keep_compute_ids
|
||||
self._compression = compression
|
||||
|
||||
def run(self):
|
||||
if self._project:
|
||||
self._project.get("/export?include_images={}&include_snapshots={}&reset_mac_addresses={}&compression={}".format(self._include_images, self._include_snapshots, self._reset_mac_addresses, self._compression),
|
||||
self._exportReceived,
|
||||
downloadProgressCallback=self._downloadFileProgress,
|
||||
timeout=None)
|
||||
self._project.get(
|
||||
"/export?include_images={}&include_snapshots={}&reset_mac_addresses={}&keep_compute_ids={}&compression={}".format(self._include_images, self._include_snapshots, self._reset_mac_addresses, self._keep_compute_ids, self._compression),
|
||||
self._exportReceived,
|
||||
downloadProgressCallback=self._downloadFileProgress,
|
||||
timeout=None
|
||||
)
|
||||
|
||||
def _exportReceived(self, content, error=False, server=None, context={}, **kwargs):
|
||||
if error:
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.44"
|
||||
__version_info__ = (2, 2, 44, 0)
|
||||
__version__ = "2.2.50"
|
||||
__version_info__ = (2, 2, 50, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
-rrequirements.txt
|
||||
|
||||
PyQt5-Qt5==5.15.2
|
||||
PyQt5-sip==12.12.2
|
||||
PyQt5==5.15.9
|
||||
PyQt5==5.15.11
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
jsonschema>=4.17.3,<4.18; python_version >= '3.7' # v4.17.3 is the last version to support Python 3.7
|
||||
jsonschema==3.2.0; python_version < '3.7' # v3.2.0 is the last version to support Python 3.6
|
||||
sentry-sdk==1.34.0,<1.35
|
||||
psutil==5.9.6
|
||||
distro>=1.8.0
|
||||
truststore>=0.8.0; python_version >= '3.10'
|
||||
jsonschema>=4.23,<4.24
|
||||
sentry-sdk==2.12,<2.13 # optional dependency
|
||||
psutil==6.0.0
|
||||
distro>=1.9.0
|
||||
truststore>=0.9.1; python_version >= '3.10'
|
||||
importlib-resources>=1.3; python_version < '3.9'
|
||||
setuptools>=60.8.1; python_version >= '3.7'
|
||||
setuptools==59.6.0; python_version < '3.7' # v59.6.0 is the last version to support Python 3.6
|
||||
|
||||
207
resources/symbols/nat.svg
Normal file
207
resources/symbols/nat.svg
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
width="4.5009999cm"
|
||||
height="2.0009999cm"
|
||||
viewBox="0.2 0.149 4.7 2.151"
|
||||
id="svg2"
|
||||
sodipodi:docname="nat.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<sodipodi:namedview
|
||||
id="namedview30"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="cm"
|
||||
showgrid="false"
|
||||
inkscape:lockguides="true"
|
||||
inkscape:zoom="5.7444245"
|
||||
inkscape:cx="75.725602"
|
||||
inkscape:cy="42.040765"
|
||||
inkscape:window-width="1658"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="70"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<metadata
|
||||
id="metadata57">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jeremy Grossmann</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>GNS-3</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:description>Created for the GNS-3 project (www.gns3.net)</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs55" />
|
||||
<path
|
||||
d="m 3.7599791,0.61531938 -10e-4,-0.021 -0.003,-0.021 -0.007,-0.02 -0.009,-0.02 -0.011,-0.021 -0.013,-0.02 -0.017,-0.02 -0.018,-0.019 -0.021,-0.019 -0.023,-0.019 -0.024,-0.017 -0.028,-0.017 -0.03,-0.017 -0.031,-0.017 -0.033,-0.015 -0.035,-0.015 -0.037,-0.014 -0.038,-0.013 -0.04,-0.012 -0.041,-0.011 -0.043,-0.011 -0.045,-0.01 -0.044,-0.008 -0.046,-0.008 -0.048,-0.007 -0.047,-0.006 -0.048,-0.004 -0.049,-0.004 -0.05,-0.003 -0.049,-0.001 -0.049,-0.001 0,0 -0.05,0.001 -0.049,0.001 -0.05,0.003 -0.048,0.004 -0.049,0.004 -0.047,0.006 -0.047,0.007 -0.046,0.008 -0.045,0.008 -0.043,0.01 -0.043,0.011 -0.042,0.011 -0.04,0.012 -0.039,0.013 -0.036,0.014 -0.035,0.015 -0.033,0.015 -0.032,0.017 -0.029,0.017 -0.027,0.017 -0.026,0.017 -0.023,0.019 -0.02,0.019 -0.019,0.019 -0.016,0.02 -0.014,0.02 -0.01,0.021 -0.009,0.02 -0.006,0.02 -0.005,0.021 -0.001,0.021 0,0 0.001,0.02 0.005,0.022 0.006,0.02 0.009,0.021 0.01,0.02 0.014,0.019 0.016,0.02 0.019,0.02 0.02,0.019 0.023,0.018 0.026,0.018 0.027,0.017 0.029,0.017 0.032,0.016 0.033,0.016 0.035,0.014 0.036,0.014 0.039,0.013 0.04,0.013 0.042,0.011 0.043,0.01 0.043,0.011 0.045,0.008 0.046,0.007 0.047,0.007 0.047,0.006 0.049,0.005 0.048,0.003 0.05,0.003 0.049,10e-4 0.05,0.001 0,0 0.049,-0.001 0.049,-10e-4 0.05,-0.003 0.049,-0.003 0.048,-0.005 0.047,-0.006 0.048,-0.007 0.046,-0.007 0.044,-0.008 0.045,-0.011 0.043,-0.01 0.041,-0.011 0.04,-0.013 0.038,-0.013 0.037,-0.014 0.035,-0.014 0.033,-0.016 0.031,-0.016 0.03,-0.017 0.028,-0.017 0.024,-0.018 0.023,-0.018 0.021,-0.019 0.018,-0.02 0.017,-0.02 0.013,-0.019 0.011,-0.02 0.009,-0.021 0.007,-0.02 0.003,-0.022 10e-4,-0.02"
|
||||
id="path4"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 2.2259791,0.83031938 -10e-4,-0.021 -0.003,-0.02 -0.004,-0.021 -0.007,-0.02 -0.009,-0.021 -0.01,-0.02 -0.012,-0.02 -0.015,-0.018 -0.015,-0.019 -0.018,-0.019 -0.019,-0.018 -0.021,-0.017 -0.022,-0.017 -0.024,-0.016 -0.026,-0.015 -0.026,-0.015 -0.029,-0.014 -0.029,-0.013 -0.031,-0.013 -0.032,-0.011 -0.032,-0.011 -0.034,-0.009 -0.035,-0.009 -0.035,-0.008 -0.036,-0.006 -0.036,-0.006 -0.037,-0.005 -0.038,-0.004 -0.037,-0.002 -0.039,-0.002 -0.038,0 0,0 -0.037,0 -0.038,0.002 -0.038,0.002 -0.038,0.004 -0.037,0.005 -0.036,0.006 -0.036,0.006 -0.035,0.008 -0.035,0.009 -0.033,0.009 -0.033,0.011 -0.032,0.011 -0.03,0.013 -0.03,0.013 -0.028,0.014 -0.027,0.015 -0.025,0.015 -0.024,0.016 -0.023,0.017 -0.021,0.017 -0.018,0.018 -0.019,0.019 -0.015,0.019 -0.015,0.018 -0.012,0.02 -0.011,0.02 -0.008,0.021 -0.007,0.02 -0.005,0.021 -0.002,0.02 -0.001,0.021 0,0 0.001,0.021 0.002,0.021 0.005,0.02 0.007,0.021 0.008,0.02 0.011,0.02 0.012,0.02 0.015,0.019 0.015,0.019 0.019,0.018 0.018,0.018 0.021,0.018 0.023,0.016 0.024,0.016 0.025,0.016 0.027,0.014 0.028,0.015 0.03,0.012 0.03,0.013 0.032,0.012 0.033,0.01 0.033,0.01 0.035,0.008 0.035,0.008 0.036,0.007 0.036,0.005 0.037,0.005 0.038,0.004 0.038,0.002 0.038,0.002 0.037,0 0,0 0.038,0 0.039,-0.002 0.037,-0.002 0.038,-0.004 0.037,-0.005 0.036,-0.005 0.036,-0.007 0.035,-0.008 0.035,-0.008 0.034,-0.01 0.032,-0.01 0.032,-0.012 0.031,-0.013 0.029,-0.012 0.029,-0.015 0.026,-0.014 0.026,-0.016 0.024,-0.016 0.022,-0.016 0.021,-0.018 0.019,-0.018 0.018,-0.018 0.015,-0.019 0.015,-0.019 0.012,-0.02 0.01,-0.02 0.009,-0.02 0.007,-0.021 0.004,-0.02 0.003,-0.021 10e-4,-0.021"
|
||||
id="path6"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 1.2809791,1.2493194 -10e-4,-0.017 -0.001,-0.017 -0.004,-0.017 -0.005,-0.017 -0.005,-0.016 -0.007,-0.016 -0.009,-0.016 -0.009,-0.017 -0.011,-0.015 -0.012,-0.015 -0.012,-0.014 -0.014,-0.015 -0.015,-0.014 -0.017,-0.012 -0.017,-0.013 -0.018,-0.012 -0.019,-0.011 -0.02,-0.011 -0.02,-0.01 -0.022,-0.01 -0.022,-0.008 -0.023,-0.008 -0.023,-0.007 -0.024,-0.006 -0.024,-0.006 -0.025,-0.004 -0.024,-0.005 -0.026,-0.002 -0.025,-0.002 -0.025,-0.002 -0.026,0 0,0 -0.026,0 -0.026,0.002 -0.025,0.002 -0.025,0.002 -0.024,0.005 -0.026,0.004 -0.024,0.006 -0.023,0.006 -0.023,0.007 -0.023,0.008 -0.022,0.008 -0.022,0.01 -0.021,0.01 -0.019,0.011 -0.019,0.011 -0.018,0.012 -0.017,0.013 -0.017,0.012 -0.015,0.014 -0.014,0.015 -0.013,0.014 -0.011,0.015 -0.011,0.015 -0.01,0.017 -0.008,0.016 -0.007,0.016 -0.006,0.016 -0.004,0.017 -0.004,0.017 -0.002,0.017 0,0.017 0,0 0,0.016 0.002,0.018 0.004,0.016 0.004,0.017 0.006,0.017 0.007,0.016 0.008,0.016 0.01,0.015 0.011,0.016 0.011,0.015 0.013,0.015 0.014,0.014 0.015,0.014 0.017,0.013 0.017,0.012 0.018,0.012 0.019,0.012 0.019,0.01 0.021,0.01 0.022,0.01 0.022,0.008 0.023,0.008 0.023,0.007 0.023,0.007 0.024,0.005 0.026,0.005 0.024,0.004 0.025,0.003 0.025,10e-4 0.026,0.002 0.026,0.001 0,0 0.026,-0.001 0.025,-0.002 0.025,-10e-4 0.026,-0.003 0.024,-0.004 0.025,-0.005 0.024,-0.005 0.024,-0.007 0.023,-0.007 0.023,-0.008 0.022,-0.008 0.022,-0.01 0.02,-0.01 0.02,-0.01 0.019,-0.012 0.018,-0.012 0.017,-0.012 0.017,-0.013 0.015,-0.014 0.014,-0.014 0.012,-0.015 0.012,-0.015 0.011,-0.016 0.009,-0.015 0.009,-0.016 0.007,-0.016 0.005,-0.017 0.005,-0.017 0.004,-0.016 0.001,-0.018 10e-4,-0.016"
|
||||
id="path8"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 2.0969791,1.5713194 -0.002,-0.018 -0.003,-0.018 -0.004,-0.019 -0.007,-0.018 -0.009,-0.017 -0.01,-0.018 -0.013,-0.017 -0.015,-0.018 -0.016,-0.016 -0.017,-0.016 -0.019,-0.016 -0.021,-0.016 -0.024,-0.015 -0.024,-0.014 -0.026,-0.013 -0.027,-0.013 -0.028,-0.012 -0.031,-0.012 -0.03,-0.011 -0.032,-0.01 -0.034,-0.009 -0.035,-0.009 -0.034,-0.008 -0.036,-0.007 -0.036,-0.005 -0.038,-0.006 -0.037,-0.004 -0.038,-0.003 -0.038,-0.002 -0.039,-0.002 -0.038,0 0,0 -0.038,0 -0.039,0.002 -0.039,0.002 -0.038,0.003 -0.037,0.004 -0.037,0.006 -0.037,0.005 -0.035,0.007 -0.035,0.008 -0.034,0.009 -0.034,0.009 -0.032,0.01 -0.031,0.011 -0.03,0.012 -0.029,0.012 -0.027,0.013 -0.026,0.013 -0.024,0.014 -0.023,0.015 -0.021,0.016 -0.019,0.016 -0.018,0.016 -0.017,0.016 -0.014,0.018 -0.012,0.017 -0.01,0.018 -0.01,0.017 -0.006,0.018 -0.005,0.019 -0.003,0.018 -0.001,0.018 0,0 0.001,0.019 0.003,0.018 0.005,0.018 0.006,0.018 0.01,0.019 0.01,0.017 0.012,0.017 0.014,0.018 0.017,0.016 0.018,0.016 0.019,0.016 0.021,0.015 0.023,0.015 0.024,0.015 0.026,0.014 0.027,0.012 0.029,0.013 0.03,0.011 0.031,0.011 0.032,0.01 0.034,0.01 0.034,0.008 0.035,0.008 0.035,0.006 0.037,0.007 0.037,0.004 0.037,0.005 0.038,0.003 0.039,0.003 0.039,10e-4 0.038,0 0,0 0.038,0 0.039,-10e-4 0.038,-0.003 0.038,-0.003 0.037,-0.005 0.038,-0.004 0.036,-0.007 0.036,-0.006 0.034,-0.008 0.035,-0.008 0.034,-0.01 0.032,-0.01 0.03,-0.011 0.031,-0.011 0.028,-0.013 0.027,-0.012 0.026,-0.014 0.024,-0.015 0.024,-0.015 0.021,-0.015 0.019,-0.016 0.017,-0.016 0.016,-0.016 0.015,-0.018 0.013,-0.017 0.01,-0.017 0.009,-0.019 0.007,-0.018 0.004,-0.018 0.003,-0.018 0.002,-0.019"
|
||||
id="path10"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 3.9229791,1.7583194 -0.002,-0.021 -0.004,-0.022 -0.007,-0.022 -0.011,-0.021 -0.012,-0.021 -0.016,-0.021 -0.019,-0.021 -0.021,-0.02 -0.024,-0.02 -0.027,-0.02 -0.029,-0.018 -0.032,-0.019 -0.033,-0.017 -0.037,-0.017 -0.039,-0.016 -0.04,-0.016 -0.043,-0.014 -0.045,-0.014 -0.046,-0.013 -0.048,-0.012 -0.05,-0.01 -0.051,-0.011 -0.052,-0.009 -0.054,-0.008 -0.054,-0.007 -0.056,-0.006 -0.055,-0.005 -0.057,-0.004 -0.057,-0.002 -0.058,-0.002 -0.057,0 0,0 -0.057,0 -0.058,0.002 -0.057,0.002 -0.057,0.004 -0.056,0.005 -0.055,0.006 -0.054,0.007 -0.054,0.008 -0.052,0.009 -0.051,0.011 -0.05,0.01 -0.048,0.012 -0.047,0.013 -0.044,0.014 -0.043,0.014 -0.04,0.016 -0.039,0.016 -0.037,0.017 -0.034,0.017 -0.031,0.019 -0.029,0.018 -0.027,0.02 -0.024,0.02 -0.021,0.02 -0.018,0.021 -0.017,0.021 -0.012,0.021 -0.011,0.021 -0.007,0.022 -0.005,0.022 -10e-4,0.021 0,0 10e-4,0.023 0.005,0.021 0.007,0.022 0.011,0.021 0.012,0.022 0.017,0.02 0.018,0.021 0.021,0.02 0.024,0.02 0.027,0.02 0.029,0.018 0.031,0.018 0.034,0.018 0.037,0.017 0.039,0.016 0.04,0.016 0.043,0.015 0.044,0.013 0.047,0.013 0.048,0.012 0.05,0.011 0.051,0.01 0.052,0.009 0.054,0.009 0.054,0.007 0.055,0.005 0.056,0.005 0.057,0.004 0.057,0.003 0.058,0.002 0.057,0 0,0 0.057,0 0.058,-0.002 0.057,-0.003 0.057,-0.004 0.055,-0.005 0.056,-0.005 0.054,-0.007 0.054,-0.009 0.052,-0.009 0.051,-0.01 0.05,-0.011 0.048,-0.012 0.046,-0.013 0.045,-0.013 0.043,-0.015 0.04,-0.016 0.039,-0.016 0.037,-0.017 0.033,-0.018 0.032,-0.018 0.029,-0.018 0.027,-0.02 0.024,-0.02 0.021,-0.02 0.019,-0.021 0.016,-0.02 0.012,-0.022 0.011,-0.021 0.007,-0.022 0.004,-0.021 0.002,-0.023"
|
||||
id="path12"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 4.5529791,0.76631938 0,-0.016 -0.003,-0.016 -0.004,-0.017 -0.008,-0.016 -0.007,-0.016 -0.011,-0.016 -0.012,-0.015 -0.013,-0.015 -0.016,-0.015 -0.017,-0.015 -0.019,-0.013 -0.02,-0.014 -0.022,-0.013 -0.023,-0.013 -0.025,-0.012 -0.026,-0.011 -0.027,-0.012 -0.029,-0.01 -0.03,-0.01 -0.031,-0.009 -0.031,-0.008 -0.033,-0.008 -0.034,-0.007 -0.034,-0.006 -0.035,-0.005 -0.035,-0.005 -0.036,-0.003 -0.037,-0.003 -0.036,-0.002 -0.037,-0.001 -0.037,0 0,0 -0.037,0 -0.036,0.001 -0.038,0.002 -0.035,0.003 -0.036,0.003 -0.036,0.005 -0.034,0.005 -0.035,0.006 -0.034,0.007 -0.032,0.008 -0.032,0.008 -0.031,0.009 -0.03,0.01 -0.028,0.01 -0.028,0.012 -0.026,0.011 -0.025,0.012 -0.023,0.013 -0.022,0.013 -0.02,0.014 -0.019,0.013 -0.016,0.015 -0.016,0.015 -0.014,0.015 -0.012,0.015 -0.01,0.016 -0.009,0.016 -0.006,0.016 -0.005,0.017 -0.002,0.016 -10e-4,0.016 0,0 10e-4,0.016 0.002,0.016 0.005,0.017 0.006,0.016 0.009,0.016 0.01,0.016 0.012,0.016 0.014,0.014 0.016,0.016 0.016,0.014 0.019,0.014 0.02,0.013 0.022,0.014 0.023,0.013 0.025,0.012 0.026,0.011 0.028,0.011 0.028,0.011 0.03,0.009 0.031,0.009 0.032,0.009 0.032,0.007 0.034,0.007 0.035,0.006 0.034,0.006 0.036,0.004 0.036,0.003 0.035,0.003 0.038,0.003 0.036,0 0.037,10e-4 0,0 0.037,-10e-4 0.037,0 0.036,-0.003 0.037,-0.003 0.036,-0.003 0.035,-0.004 0.035,-0.006 0.034,-0.006 0.034,-0.007 0.033,-0.007 0.031,-0.009 0.031,-0.009 0.03,-0.009 0.029,-0.011 0.027,-0.011 0.026,-0.011 0.025,-0.012 0.023,-0.013 0.022,-0.014 0.02,-0.013 0.019,-0.014 0.017,-0.014 0.016,-0.016 0.013,-0.014 0.012,-0.016 0.011,-0.016 0.007,-0.016 0.008,-0.016 0.004,-0.017 0.003,-0.016 0,-0.016"
|
||||
id="path14"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 4.7599791,1.1813194 -10e-4,-0.016 -0.002,-0.016 -0.005,-0.017 -0.007,-0.016 -0.008,-0.016 -0.01,-0.016 -0.012,-0.016 -0.013,-0.014 -0.015,-0.015 -0.018,-0.015 -0.019,-0.014 -0.019,-0.013 -0.022,-0.013 -0.023,-0.014 -0.024,-0.011 -0.027,-0.012 -0.027,-0.011 -0.028,-0.01 -0.03,-0.01 -0.03,-0.009 -0.032,-0.008 -0.033,-0.008 -0.033,-0.007 -0.033,-0.005 -0.035,-0.006 -0.035,-0.004 -0.036,-0.004 -0.036,-0.003 -0.036,-0.002 -0.037,-0.001 -0.036,-0.001 0,0 -0.038,0.001 -0.036,0.001 -0.036,0.002 -0.036,0.003 -0.036,0.004 -0.035,0.004 -0.035,0.006 -0.033,0.005 -0.034,0.007 -0.032,0.008 -0.032,0.008 -0.03,0.009 -0.03,0.01 -0.028,0.01 -0.027,0.011 -0.027,0.012 -0.024,0.011 -0.022,0.014 -0.022,0.013 -0.021,0.013 -0.018,0.014 -0.018,0.015 -0.015,0.015 -0.013,0.014 -0.012,0.016 -0.01,0.016 -0.008,0.016 -0.007,0.016 -0.005,0.017 -0.002,0.016 -10e-4,0.016 0,0 10e-4,0.016 0.002,0.016 0.005,0.016 0.007,0.016 0.008,0.017 0.01,0.016 0.012,0.015 0.013,0.015 0.015,0.015 0.018,0.015 0.018,0.013 0.021,0.014 0.022,0.013 0.022,0.013 0.024,0.012 0.027,0.011 0.027,0.012 0.028,0.01 0.03,0.01 0.03,0.009 0.032,0.008 0.032,0.007 0.034,0.007 0.033,0.006 0.035,0.005 0.035,0.005 0.036,0.004 0.036,0.003 0.036,0.002 0.036,0.001 0.038,0 0,0 0.036,0 0.037,-0.001 0.036,-0.002 0.036,-0.003 0.036,-0.004 0.035,-0.005 0.035,-0.005 0.033,-0.006 0.033,-0.007 0.033,-0.007 0.032,-0.008 0.03,-0.009 0.03,-0.01 0.028,-0.01 0.027,-0.012 0.027,-0.011 0.024,-0.012 0.023,-0.013 0.022,-0.013 0.019,-0.014 0.019,-0.013 0.018,-0.015 0.015,-0.015 0.013,-0.015 0.012,-0.015 0.01,-0.016 0.008,-0.017 0.007,-0.016 0.005,-0.016 0.002,-0.016 10e-4,-0.016"
|
||||
id="path16"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 4.6189791,1.5243194 -10e-4,-0.027 -0.002,-0.027 -0.005,-0.026 -0.006,-0.027 -0.009,-0.026 -0.01,-0.026 -0.012,-0.025 -0.014,-0.025 -0.014,-0.025 -0.017,-0.023 -0.018,-0.024 -0.021,-0.022 -0.021,-0.022 -0.023,-0.02 -0.024,-0.021 -0.027,-0.018 -0.027,-0.018 -0.027,-0.018 -0.029,-0.015 -0.031,-0.015 -0.032,-0.013 -0.031,-0.013 -0.033,-0.011 -0.034,-0.01 -0.035,-0.009 -0.035,-0.007 -0.036,-0.006 -0.035,-0.005 -0.036,-0.003 -0.036,-0.002 -0.036,-0.001 0,0 -0.037,0.001 -0.036,0.002 -0.036,0.003 -0.036,0.005 -0.035,0.006 -0.035,0.007 -0.035,0.009 -0.034,0.01 -0.033,0.011 -0.032,0.013 -0.031,0.013 -0.031,0.015 -0.029,0.015 -0.028,0.018 -0.027,0.018 -0.026,0.018 -0.024,0.021 -0.023,0.02 -0.022,0.022 -0.019,0.022 -0.019,0.024 -0.017,0.023 -0.015,0.025 -0.014,0.025 -0.011,0.025 -0.01,0.026 -0.008,0.026 -0.007,0.027 -0.005,0.026 -0.002,0.027 -10e-4,0.027 0,0 10e-4,0.027 0.002,0.027 0.005,0.026 0.007,0.026 0.008,0.026 0.01,0.026 0.011,0.026 0.014,0.025 0.015,0.024 0.017,0.024 0.019,0.023 0.019,0.022 0.022,0.022 0.023,0.021 0.024,0.02 0.026,0.019 0.027,0.018 0.028,0.017 0.029,0.016 0.031,0.015 0.031,0.013 0.032,0.013 0.033,0.011 0.034,0.01 0.035,0.008 0.035,0.008 0.035,0.006 0.036,0.005 0.036,0.003 0.036,0.002 0.037,10e-4 0,0 0.036,-10e-4 0.036,-0.002 0.036,-0.003 0.035,-0.005 0.036,-0.006 0.035,-0.008 0.035,-0.008 0.034,-0.01 0.033,-0.011 0.031,-0.013 0.032,-0.013 0.031,-0.015 0.029,-0.016 0.027,-0.017 0.027,-0.018 0.027,-0.019 0.024,-0.02 0.023,-0.021 0.021,-0.022 0.021,-0.022 0.018,-0.023 0.017,-0.024 0.014,-0.024 0.014,-0.025 0.012,-0.026 0.01,-0.026 0.009,-0.026 0.006,-0.026 0.005,-0.026 0.002,-0.027 10e-4,-0.027"
|
||||
id="path18"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 2.7919791,0.61131938 0.965,-0.091 -0.013,-0.021 -0.014,-0.019 -0.017,-0.02 -0.019,-0.02 -0.022,-0.019 -0.024,-0.018 -0.026,-0.018 -0.028,-0.017 -0.031,-0.017 -0.032,-0.016 -0.034,-0.015 -0.036,-0.014 -0.038,-0.014 -0.039,-0.013 -0.042,-0.012 -0.042,-0.011 -0.043,-0.011 -0.045,-0.009 -0.046,-0.009 -0.047,-0.007 -0.048,-0.007 -0.048,-0.005 -0.049,-0.004 -0.049,-0.004 -0.049,-0.002 -0.051,-0.001 -0.05,0 -0.05,0 -0.049,0.003 -0.05,0.002 -0.049,0.004 -0.049,0.006 -0.047,0.006 -0.048,0.007 -0.046,0.008 -0.045,0.009 -0.044,0.01 -0.043,0.011 -0.041,0.012 -0.04,0.013 -0.038,0.013 -0.036,0.014 -0.036,0.016 -0.032,0.015 -0.032,0.017 -0.029,0.017 -0.026,0.018 -0.024,0.018 -0.024,0.019 -0.02,0.018 -0.018,0.02 -0.015,0.02 -0.012,0.021 -0.011,0.02 0.971,0.077"
|
||||
id="path22"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 3.7569791,0.51931938 -0.013,-0.021 -0.014,-0.019 -0.017,-0.02 -0.02,-0.019 -0.022,-0.019 -0.024,-0.018 -0.026,-0.018 -0.029,-0.018 -0.03,-0.016 -0.032,-0.016 -0.035,-0.016 -0.035,-0.014 -0.038,-0.014 -0.04,-0.012 -0.04,-0.013 -0.042,-0.011 -0.044,-0.01 -0.045,-0.01 -0.046,-0.008 -0.046,-0.008 -0.048,-0.006 -0.048,-0.005 -0.049,-0.004 -0.05,-0.004 -0.05,-0.002 -0.049,-0.001 -0.051,0 -0.049,0 -0.049,0.003 -0.051,0.002 -0.048,0.004 -0.049,0.006 -0.047,0.006 -0.048,0.007 -0.046,0.008 -0.045,0.009 -0.043,0.01 -0.043,0.011 -0.042,0.012 -0.039,0.013 -0.038,0.013 -0.036,0.014 -0.036,0.015 -0.033,0.015 -0.031,0.017 -0.028,0.018 -0.028,0.017 -0.024,0.018 -0.022,0.019 -0.021,0.019 -0.018,0.019 -0.016,0.02 -0.012,0.021 -0.011,0.02"
|
||||
id="path24"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 1.4819791,0.82631938 0.486,-0.317 -0.029,-0.013 -0.032,-0.012 -0.032,-0.012 -0.033,-0.01 -0.034,-0.01 -0.035,-0.008 -0.036,-0.008 -0.036,-0.006 -0.037,-0.006 -0.037,-0.005 -0.038,-0.003 -0.038,-0.003 -0.039,-0.001 -0.038,0 -0.038,0 -0.038,0.002 -0.038,0.003 -0.038,0.004 -0.037,0.005 -0.036,0.006 -0.037,0.007 -0.035,0.008 -0.034,0.009 -0.034,0.009 -0.033,0.011 -0.031,0.013 -0.031,0.012 -0.029,0.013 -0.028,0.015 -0.027,0.015 -0.026,0.015 -0.024,0.016 -0.022,0.018 -0.021,0.017 -0.018,0.018 -0.018,0.02 -0.016,0.018 -0.014,0.02 -0.012,0.02 -0.01,0.02 -0.008,0.02 -0.006,0.022 -0.005,0.02 -0.003,0.021 0,0.021 0.001,0.021 0.003,0.021 0.005,0.021 0.74600003,-0.067"
|
||||
id="path26"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 1.9659791,0.50831938 -0.03,-0.014 -0.031,-0.011 -0.033,-0.012 -0.033,-0.01 -0.035,-0.01 -0.034,-0.008 -0.036,-0.008 -0.036,-0.006 -0.037,-0.005 -0.037,-0.005 -0.038,-0.004 -0.038,-0.002 -0.039,-0.001 -0.038,0 -0.038,0 -0.038,0.003 -0.038,0.002 -0.038,0.004 -0.037,0.005 -0.036,0.007 -0.036,0.006 -0.035,0.009 -0.034,0.008 -0.034,0.011 -0.033,0.011 -0.032,0.011 -0.03,0.013 -0.029,0.013 -0.028,0.015 -0.027,0.015 -0.025,0.015 -0.024,0.016 -0.022,0.018 -0.02,0.017 -0.02,0.019 -0.017,0.018 -0.016,0.019 -0.013,0.02 -0.012,0.02 -0.01,0.02 -0.008,0.021 -0.006,0.02 -0.005,0.021 -0.003,0.02 0,0.022 0.002,0.021 0.002,0.02 0.006,0.021"
|
||||
id="path28"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 1.3459791,1.5683194 -0.78100003,-0.012 0,0.019 0.001,0.019 0.003,0.019 0.006,0.018 0.008,0.019 0.009,0.018 0.012,0.018 0.014,0.018 0.015,0.017 0.017,0.017 0.019,0.017 0.02,0.016 0.023,0.015 0.023,0.015 0.026,0.015 0.027,0.014 0.027,0.012 0.03,0.013 0.031,0.012 0.032,0.01 0.034,0.011 0.033,0.009 0.035,0.008 0.036,0.008 0.037,0.007 0.038,0.006 0.037,0.005 0.039,0.004 0.039,0.003 0.039,0.003 0.04,10e-4 0.039,0 0.039,-10e-4 0.039,-0.002 0.039,-0.002 0.039,-0.003 0.039,-0.005 0.037,-0.006 0.037,-0.005 0.037,-0.008 0.035,-0.008 0.035,-0.009 0.033,-0.009 0.033,-0.01 0.033,-0.011 0.03,-0.013 -0.513,-0.282"
|
||||
id="path30"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 0.56497907,1.5563194 -0.001,0.019 0.002,0.019 0.003,0.018 0.006,0.019 0.008,0.018 0.01,0.019 0.011,0.018 0.014,0.018 0.015,0.017 0.017,0.017 0.018,0.016 0.02,0.016 0.023,0.016 0.024,0.015 0.024,0.014 0.026,0.014 0.029,0.013 0.029,0.013 0.032,0.011 0.032,0.011 0.032,0.01 0.034,0.009 0.035,0.009 0.037,0.008 0.036,0.006 0.037,0.007 0.038,0.005 0.038,0.004 0.039,0.003 0.039,0.002 0.039,0.002 0.04,0 0.039,0 0.039,-0.003 0.039,-0.002 0.038,-0.003 0.038,-0.005 0.038,-0.004 0.038,-0.007 0.036,-0.007 0.036,-0.008 0.034,-0.009 0.034,-0.009 0.034,-0.01 0.031,-0.011 0.03,-0.012"
|
||||
id="path32"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 3.8359791,0.75931938 0.689,0.104 0.011,-0.016 0.01,-0.015 0.007,-0.016 0.006,-0.016 0.003,-0.016 0.002,-0.017 0,-0.016 -0.002,-0.017 -0.003,-0.016 -0.006,-0.016 -0.007,-0.016 -0.01,-0.016 -0.01,-0.016 -0.013,-0.015 -0.015,-0.015 -0.016,-0.015 -0.018,-0.014 -0.02,-0.014 -0.022,-0.014 -0.021,-0.012 -0.025,-0.013 -0.025,-0.012 -0.027,-0.011 -0.029,-0.011 -0.028,-0.01 -0.03,-0.009 -0.032,-0.009 -0.032,-0.008 -0.034,-0.007 -0.033,-0.006 -0.036,-0.006 -0.034,-0.005 -0.037,-0.004 -0.036,-0.003 -0.037,-0.003 -0.037,-0.001 -0.036,-0.001 -0.037,0 -0.037,0.001 -0.037,0.002 -0.036,0.002 -0.036,0.003 -0.036,0.004 -0.036,0.005 0.238,0.306"
|
||||
id="path34"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 4.4569791,0.92331938 0.067,-0.059 0.011,-0.016 0.009,-0.015 0.009,-0.016 0.005,-0.017 0.004,-0.016 0.002,-0.016 0.001,-0.016 -0.003,-0.017 -0.003,-0.016 -0.006,-0.017 -0.007,-0.015 -0.009,-0.016 -0.011,-0.016 -0.012,-0.015 -0.016,-0.015 -0.016,-0.015 -0.017,-0.014 -0.02,-0.014 -0.021,-0.014 -0.023,-0.013 -0.023,-0.012 -0.026,-0.012 -0.027,-0.011 -0.028,-0.011 -0.029,-0.011 -0.03,-0.009 -0.032,-0.008 -0.031,-0.008 -0.033,-0.008 -0.034,-0.006 -0.035,-0.006 -0.035,-0.005 -0.036,-0.004 -0.036,-0.003 -0.037,-0.002 -0.037,-0.002 -0.037,-0.001 -0.037,0 -0.037,0.001 -0.037,0.002 -0.036,0.002 -0.036,0.003 -0.036,0.004 -0.035,0.005"
|
||||
id="path36"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 3.9329791,1.1853194 0.775,0.132 0.016,-0.017 0.013,-0.017 0.012,-0.018 0.008,-0.018 0.008,-0.018 0.004,-0.019 10e-4,-0.018 0,-0.018 -0.003,-0.019 -0.004,-0.019 -0.008,-0.018 -0.009,-0.018 -0.012,-0.017 -0.014,-0.018 -0.016,-0.017 -0.018,-0.017 -0.02,-0.016 -0.023,-0.016 -0.024,-0.015 -0.686,0.20100002"
|
||||
id="path38"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 4.6121701,1.38473 0.098479,-0.059128 0.014482,-0.018039 0.013517,-0.018039 0.01062,-0.018039 0.00869,-0.018039 0.00772,-0.018039 0.00386,-0.018039 0.00193,-0.019041 0,-0.018039 -0.00386,-0.020044 -0.00386,-0.018039 -0.00676,-0.018039 -0.00965,-0.018039 -0.011586,-0.018039 -0.013517,-0.018039 -0.015448,-0.017037 -0.018344,-0.017037 -0.021241,-0.016035 -0.020275,-0.016035 -0.024137,-0.0160349 -0.1544773,-0.0591286"
|
||||
id="path40"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.0596842;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 3.9009791,1.5363194 -0.245,0.503 0.036,0.008 0.036,0.007 0.037,0.006 0.038,0.004 0.038,0.003 0.037,0.002 0.037,0 0.038,-0.002 0.037,-0.002 0.038,-0.004 0.036,-0.005 0.038,-0.007 0.035,-0.008 0.036,-0.009 0.034,-0.011 0.034,-0.012 0.033,-0.013 0.032,-0.014 0.031,-0.016 0.03,-0.016 0.028,-0.018 0.027,-0.019 0.027,-0.02 0.025,-0.02 0.022,-0.022 0.022,-0.021 0.02,-0.024 0.018,-0.024 0.016,-0.024 0.015,-0.025 0.014,-0.026 0.01,-0.025 0.01,-0.027 0.008,-0.027 0.006,-0.026 0.003,-0.028 0.002,-0.027 0,-0.027 -0.002,-0.027 -0.004,-0.027 -0.006,-0.026 -0.008,-0.028 -0.009,-0.025 -0.71,0.149"
|
||||
id="path42"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 3.6589791,2.0403194 0.036,0.008 0.036,0.007 0.037,0.006 0.037,0.004 0.037,0.002 0.038,0.002 0.038,10e-4 0.037,-0.003 0.038,-0.002 0.037,-0.004 0.037,-0.005 0.036,-0.007 0.036,-0.009 0.036,-0.009 0.034,-0.011 0.033,-0.011 0.034,-0.014 0.032,-0.014 0.031,-0.015 0.029,-0.018 0.029,-0.017 0.027,-0.019 0.026,-0.019 0.025,-0.021 0.023,-0.022 0.021,-0.022 0.019,-0.024 0.019,-0.023 0.016,-0.024 0.015,-0.025 0.014,-0.026 0.011,-0.026 0.008,-0.026 0.008,-0.027 0.006,-0.027 0.003,-0.027 0.002,-0.027 0,-0.027 -0.002,-0.027 -0.005,-0.027 -0.005,-0.028 -0.008,-0.026 -0.01,-0.026"
|
||||
id="path44"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 0.80297907,1.2493194 -0.037,-0.34200002 -0.028,0.002 -0.026,0.002 -0.027,0.004 -0.026,0.004 -0.026,0.005 -0.026,0.006 -0.024,0.007 -0.025,0.008 -0.024,0.008 -0.023,0.009 -0.022,0.01 -0.021,0.01 -0.021,0.012 -0.02,0.012 -0.019,0.013 -0.017,0.013 -0.017,0.014 -0.015,0.014 -0.015,0.015 -0.013,0.015 -0.011,0.016 -0.011,0.016 -0.01,0.016 -0.008,0.017 -0.006,0.017 -0.006,0.016 -0.004,0.018 -0.003,0.018 -0.001,0.017 0,0.017 0.001,0.018 0.003,0.017 0.004,0.017 0.006,0.017 0.007,0.017 0.008,0.017 0.009,0.016 0.011,0.016 0.012,0.016 0.013,0.015 0.016,0.015 0.015,0.014 0.017,0.014 0.018,0.013 0.018,0.013 0.02,0.011 0.021,0.011 0.021,0.012 0.022,0.009 0.024,0.009 0.023,0.009 0.243,-0.305"
|
||||
id="path46"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 0.76697907,0.90731938 -0.027,0.002 -0.027,0.002 -0.026,0.003 -0.026,0.005 -0.025,0.004 -0.026,0.006 -0.025,0.007 -0.023,0.007 -0.023,0.009 -0.023,0.009 -0.023,0.009 -0.021,0.01 -0.02,0.011 -0.02,0.012 -0.018,0.012 -0.018,0.013 -0.017,0.013 -0.016,0.015 -0.015,0.014 -0.012,0.014 -0.012,0.016 -0.012,0.015 -0.009,0.016 -0.009,0.016 -0.007,0.017 -0.006,0.017 -0.005,0.017 -0.003,0.017 -0.002,0.017 0,0.017 0,0.017 0.003,0.017 0.003,0.018 0.004,0.016 0.007,0.017 0.006,0.016 0.009,0.017 0.009,0.016 0.012,0.015 0.012,0.016 0.014,0.014 0.014,0.014 0.016,0.015 0.016,0.013 0.018,0.013 0.019,0.012 0.019,0.011 0.021,0.012 0.021,0.01 0.022,0.009 0.023,0.009 0.024,0.009"
|
||||
id="path48"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 2.7759791,1.7874896 -1.109,0.040159 0.008,0.020594 0.009,0.019565 0.013,0.020594 0.015,0.020595 0.018,0.019565 0.021,0.018535 0.023,0.018535 0.025,0.018535 0.029,0.018535 0.031,0.017505 0.032,0.015446 0.036,0.016475 0.037,0.015446 0.039,0.015446 0.042,0.013386 0.043,0.013386 0.045,0.011327 0.047,0.012357 0.048,0.010297 0.049,0.00927 0.051,0.00927 0.052,0.00824 0.053,0.00618 0.053,0.00618 0.055,0.00515 0.055,0.00412 0.056,0.00206 0.055,0.00206 0.057,0.00103 0.055,0 0.057,-0.00103 0.055,-0.00309 0.055,-0.00309 0.055,-0.00515 0.054,-0.00515 0.053,-0.00618 0.052,-0.00721 0.052,-0.00824 0.05,-0.010297 0.049,-0.00927 0.047,-0.011327 0.046,-0.011327 0.044,-0.013386 0.042,-0.014416 0.04,-0.013386 0.039,-0.015446 0.036,-0.015446 0.034,-0.016476 0.031,-0.016476 0.03,-0.017505 0.027,-0.019565 0.025,-0.017505 0.022,-0.019565 0.018,-0.018535 -1.056,-0.1307748"
|
||||
id="path50"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
<path
|
||||
d="m 1.6669791,1.8393194 0.008,0.019 0.01,0.02 0.012,0.02 0.016,0.019 0.017,0.019 0.021,0.018 0.023,0.018 0.025,0.019 0.03,0.017 0.03,0.017 0.032,0.015 0.036,0.016 0.037,0.015 0.039,0.015 0.042,0.013 0.044,0.013 0.043,0.011 0.048,0.012 0.047,0.01 0.049,0.009 0.051,0.009 0.052,0.008 0.053,0.006 0.053,0.005 0.055,0.006 0.054,0.003 0.056,0.003 0.056,0.002 0.056,10e-4 0.056,0 0.056,-10e-4 0.055,-0.003 0.055,-0.003 0.055,-0.005 0.054,-0.005 0.054,-0.006 0.051,-0.007 0.052,-0.008 0.05,-0.009 0.048,-0.01 0.048,-0.011 0.046,-0.011 0.043,-0.013 0.043,-0.012 0.04,-0.015 0.039,-0.014 0.036,-0.016 0.034,-0.015 0.032,-0.017 0.029,-0.016 0.027,-0.018 0.024,-0.018 0.022,-0.019 0.02,-0.018"
|
||||
id="path52"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.06067566;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<rect
|
||||
width="2.7800133"
|
||||
height="0.61515152"
|
||||
rx="0"
|
||||
ry="0.28983101"
|
||||
x="1.2692652"
|
||||
y="0.80605406"
|
||||
transform="matrix(0.999604,0.02812984,-0.02812984,0.999604,0,0)"
|
||||
id="rect1892"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
d="m 2.5029776,1.9073766 0.023,-0.00895 0.020913,-0.00976 0.022119,-0.011947 0.021191,-0.0142 0.021284,-0.015682 0.02031,-0.017195 0.020402,-0.018676 0.020541,-0.020897 0.018455,-0.021702 0.018546,-0.023184 0.018685,-0.025405 0.016552,-0.02547 0.016691,-0.027691 0.014651,-0.029236 0.015717,-0.029204 0.013676,-0.03075 0.012702,-0.032263 0.012748,-0.033004 0.010665,-0.033809 0.010665,-0.033809 0.00863,-0.035354 0.00756,-0.035386 0.00653,-0.036158 0.00658,-0.0369 0.00445,-0.036963 0.00333,-0.036256 0.00236,-0.037768 0.00226,-0.036288 -9.319e-4,-0.036384 2.273e-4,-0.037833 -0.00205,-0.035676 -0.00413,-0.03648 L 2.883076,0.9720976 2.877836,0.9363258 2.871426,0.902003 2.863906,0.8683889 2.855226,0.8362236 2.845476,0.8040261 2.834621,0.7725371 2.82256,0.7432375 2.810453,0.7146786 2.797187,0.6875686 2.782854,0.6604265 2.768383,0.635506 2.751686,0.6120024 2.733784,0.590685 2.716948,0.569403 2.69886,0.5510511 2.679613,0.5341483 2.660319,0.517986 2.640887,0.5040454 2.620296,0.4915538 2.598453,0.4819918 2.577631,0.4732028"
|
||||
id="path24-7"
|
||||
style="fill:none;stroke:#6c8f93;stroke-width:0.107496;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path2057-3"
|
||||
d="M 1.5298421,1.2403194 H 2.3548856 V 1.303797 L 2.577141,1.1602384 2.3548856,1.0313279 v 0.064457 H 1.5298421 v 0.1445348"
|
||||
style="fill:#6c8f93;fill-opacity:1;stroke:none;stroke-width:5.35746e-05;stroke-opacity:0.994961" />
|
||||
<path
|
||||
id="path2057-3-9"
|
||||
d="M 3.1225773,1.2403194 H 3.9476208 V 1.303797 L 4.1698762,1.1602384 3.9476208,1.0313279 v 0.064457 H 3.1225773 v 0.1445348"
|
||||
style="fill:#6c8f93;fill-opacity:1;stroke:none;stroke-width:5.35746e-05;stroke-opacity:0.994961" />
|
||||
<path
|
||||
id="path2057-3-5"
|
||||
d="m 1.5278616,0.86827348 h 0.8319275 v 0.063478 L 2.5838989,0.78819244 2.3597891,0.65928186 v 0.064457 H 1.5278616 v 0.14453482"
|
||||
style="fill:#6c8f93;fill-opacity:1;stroke:none;stroke-width:5.37977e-05;stroke-opacity:0.994961" />
|
||||
<path
|
||||
id="path2057-3-6"
|
||||
d="m 1.527029,1.6225499 h 0.8217599 v 0.063478 L 2.5701597,1.5424689 2.3487889,1.4135585 v 0.064457 H 1.5270291 v 0.1445347"
|
||||
style="fill:#6c8f93;fill-opacity:1;stroke:none;stroke-width:5.34679e-05;stroke-opacity:0.994961" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 30 KiB |
14
setup.py
14
setup.py
@@ -19,9 +19,9 @@ import sys
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
# we only support Python 3 version >= 3.4
|
||||
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 4):
|
||||
raise SystemExit("Python 3.4 or higher is required")
|
||||
# we only support Python 3 version >= 3.8
|
||||
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 8):
|
||||
raise SystemExit("Python 3.8 or higher is required")
|
||||
|
||||
|
||||
class PyTest(TestCommand):
|
||||
@@ -79,7 +79,7 @@ setup(
|
||||
include_package_data=True,
|
||||
package_data={"gns3": ["configs/*.txt", "schemas/*.json"]},
|
||||
platforms="any",
|
||||
python_requires=">=3.4",
|
||||
python_requires='>=3.8',
|
||||
setup_requires=["setuptools>=17.1"],
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
@@ -92,11 +92,7 @@ setup(
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
{
|
||||
"filename": "empty100G.qcow2",
|
||||
"version": "100G",
|
||||
"checksum": "d08fdec95fffbda3f04e9a00db49295df73ae4a507396e442ba9e4ad5c14ce5a",
|
||||
"checksum_type": "sha256",
|
||||
"checksum": "1e6409a4523ada212dea2ebc50e50a65",
|
||||
"checksum_type": "md5",
|
||||
"filesize": 198656,
|
||||
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
|
||||
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-rrequirements.txt
|
||||
|
||||
PyQt5==5.15.10 # pyup: ignore
|
||||
PyQt5==5.15.11 # pyup: ignore
|
||||
pywin32==306 # pyup: ignore
|
||||
|
||||
Reference in New Issue
Block a user