Compare commits

..

89 Commits

Author SHA1 Message Date
grossmj
74763287fb Release v2.2.12 2020-08-07 19:27:32 +09:30
grossmj
737ff42d64 Merge branch 'master' into 2.2 2020-08-07 19:04:08 +09:30
Jeremy Grossmann
5656bd2d48 Downgrade psutil to version 5.6.7 2020-07-29 17:36:14 +09:30
Jeremy Grossmann
058c069394 Fix log shows the GUI command line without spaces between its arguments. Fixes #3026 2020-07-27 18:27:23 +09:30
grossmj
926ec48d00 Upgrade to psutil version 5.7.2 2020-07-21 15:49:58 +09:30
grossmj
410e5353b2 Use server host is console host is equal to "0:0:0:0:0:0:0:0" 2020-07-17 21:13:27 +09:30
grossmj
bfb90406ed Remove VMware promotion. 2020-07-17 21:12:59 +09:30
grossmj
439cdce287 Development on 2.2.12dev1 2020-07-09 21:37:03 +09:30
grossmj
4e50c2a4b1 Release v2.2.11 2020-07-09 20:37:10 +09:30
grossmj
94c636ae61 Merge branch 'master' into 2.2 2020-07-09 20:23:31 +09:30
grossmj
f53b9a266e Try to fix "Recent project" selection not working. Ref #3007 2020-07-09 15:37:47 +09:30
grossmj
2476448032 Fix debug entries shown twice in console window and double error messages with remote GNS3VM. Fixes #3010 #3011
Note that the debug level is broken (has been for a long time apparently).
2020-07-07 21:06:56 +09:30
grossmj
a34cd742e3 Merge branch '2.2' 2020-07-06 22:20:05 +09:30
grossmj
39698196ac Fix deprecation warning. Ref #3009 2020-07-06 22:08:10 +09:30
grossmj
61432ced4f Fix tests on macOS. Ref #3009 2020-07-06 22:03:29 +09:30
grossmj
2ddd13c445 Add Snyk badges. 2020-06-27 18:27:04 +09:30
grossmj
af6c4c5b3e Merge branch 'master' into 2.2 2020-06-26 21:30:37 +09:30
grossmj
d4012294bf Run tests inside container 2020-06-26 20:50:48 +09:30
grossmj
4b04b0e855 Use xvfb to run tests 2020-06-26 20:41:08 +09:30
grossmj
1bec5019bf Install PyQt5 using pip 2020-06-26 19:42:42 +09:30
grossmj
ec6b876baa Explicitly install sip 2020-06-26 19:38:10 +09:30
grossmj
7cee0d01ab Install PyQt5 for tests and add GitHub Actions badge 2020-06-26 19:34:02 +09:30
Jeremy Grossmann
dd3314d06b Set up GitHub Actions for running tests 2020-06-26 19:27:22 +09:30
grossmj
9c58b26265 Remove tox, Travis CI and pep8.sh script
Update dependencies
2020-06-26 19:21:51 +09:30
Jeremy Grossmann
83c26f47da Merge pull request #3005 from GNS3/whitesource/configure
Configure WhiteSource for GitHub.com
2020-06-26 09:04:39 +08:00
whitesource-for-github-com[bot]
8ed2f55600 Add .whitesource configuration file 2020-06-26 01:01:54 +00:00
Jeremy Grossmann
b435317904 Merge pull request #3003 from GNS3/snyk-fix-8bf3e4840df4587cc42afb85b857d470
[Snyk] Security upgrade psutil from 5.6.6 to 5.6.7
2020-06-25 11:41:01 +08:00
snyk-bot
acb8aa8ca2 fix: requirements.txt to reduce vulnerabilities
The following vulnerabilities are fixed by pinning transitive dependencies:
- https://snyk.io/vuln/SNYK-PYTHON-PSUTIL-483082
2020-06-24 13:10:33 +00:00
grossmj
c55d6b8a6f Fix sentry SDK is configured twice. 2020-06-24 12:40:06 +09:30
grossmj
a4039a254e Development on 2.2.11dev1 2020-06-18 19:06:00 +09:30
grossmj
85ed4b3026 Release v2.2.10 2020-06-18 12:29:33 +09:30
grossmj
5207a99692 New fix for multi-device selection/deselection not working as expected with right click. Fixes #2986 2020-06-09 13:50:31 +09:30
grossmj
d69527995d Revert "Fix Multi-device selection/deselection not working as expected with right click. Fixes #2986"
This reverts commit ddeb95cb0a.
2020-06-09 13:19:20 +09:30
grossmj
4b000ba2f7 Optimize snap-to-grid code for drawing items. Fixes #2997 2020-06-09 11:47:05 +09:30
grossmj
1b302b77a0 Move jsonschema 2.6.0 requirement in build repository.
https://github.com/GNS3/gns3-server/issues/1751
https://github.com/GNS3/gns3-gui/issues/2849

This is to avoid the following error:

```
ERROR: Double requirement given: jsonschema==2.6.0 (from -r gns3-gui\win-requirements.txt (line 4)) (already in jsonschema==3.2.0 (from -r gns3-gui\requirements.txt (line 1)), name='jsonschema')
```
2020-06-07 13:07:16 +09:30
grossmj
a5b5c404ec Only use jsonschema 2.6.0 on Windows and macOS.
https://github.com/GNS3/gns3-server/issues/1751
https://github.com/GNS3/gns3-gui/issues/2849
2020-06-07 12:55:22 +09:30
grossmj
6b97b0c6cd Disable default integrations for sentry sdk. 2020-06-06 15:37:17 +09:30
grossmj
115dd43eee Development on 2.2.10dev1 2020-06-04 21:06:30 +09:30
grossmj
2530bf97a8 Release v2.2.9 2020-06-04 18:39:27 +09:30
grossmj
9892fd0654 Fix issue editing README.txt on Windows. 2020-06-04 18:12:50 +09:30
grossmj
c71ee73da8 Merge branch 'master' into 2.2 2020-06-04 12:22:11 +09:30
Jeremy Grossmann
0643fd516d Merge pull request #2993 from GNS3/replicate-network-connection-state
Support to activate/deactive network connection state replication in Qemu
2020-06-04 10:49:41 +08:00
grossmj
a25680f2ce Fix GUI doesn't detect another GUI on macOS. Fixes #2994 2020-06-03 20:38:55 +09:30
grossmj
58bd5be920 Support to activate/deactive network connection state replication in Qemu. 2020-06-02 18:45:22 +09:30
Jeremy Grossmann
d95633ba2c Merge pull request #2989 from GNS3/reset-mac-addresses
Option to reset all MAC addresses when exporting or duplicating a project.
2020-05-27 10:53:22 +08:00
grossmj
dfea6d1723 Option to reset or not all MAC addresses when exporting or duplicating a project. 2020-05-27 12:14:47 +09:30
grossmj
ddeb95cb0a Fix Multi-device selection/deselection not working as expected with right click. Fixes #2986 2020-05-26 16:11:53 +09:30
grossmj
5f7ff0d70d Generate MainWindow Ui file. 2020-05-26 13:01:04 +09:30
Jeremy Grossmann
a00e039cec Merge pull request #2875 from fatoms/master
Proposed fix for "Edit readme" is missing in GNS3 GUI. #2854
2020-05-26 11:30:19 +08:00
Dominic
a24e9adef1 Merge branch 'Edit_Readme' 2020-05-21 20:03:03 +02:00
Dominic Harford
ee5f8e8edd Resolve conflict with GNS3 repo 2020-05-21 19:08:29 +02:00
grossmj
f5470130f5 Fix issues with crash reporting & bump version to 2.2.9dev2. Ref https://github.com/GNS3/gns3-server/issues/1758 2020-05-21 18:19:19 +09:30
grossmj
1ff405885e Merge branch 'master' into 2.2 2020-05-20 17:25:37 +09:30
Dominic
9fb42ead9f Revert "Updated GUI pyqt files from Tab Order 'fixes' in "Tab Order in Preferences and Project Dialog #2872""
This reverts commit 0d2f91709c.
2020-05-19 18:31:02 +02:00
grossmj
2ea1946c0f Replace Raven by Sentry SDK. Fixes https://github.com/GNS3/gns3-server/issues/1758 2020-05-19 15:48:53 +09:30
grossmj
963e054918 Fix online help menu URL. Fixes #2984 2020-05-08 12:42:06 +09:30
grossmj
0f5f6ab645 Require setuptools>=17.1 in setup.py. Ref https://github.com/GNS3/gns3-server/issues/1751
This is to support environmental markers.
https://github.com/pypa/setuptools/blob/master/CHANGES.rst#171
2020-05-08 12:34:58 +09:30
grossmj
8a905b5c39 Development on 2.2.9dev1 2020-05-07 23:10:20 +09:30
grossmj
e917193f06 Merge branch '2.2' 2020-05-07 23:09:04 +09:30
grossmj
16846ce49c Release v2.2.8 2020-05-07 18:10:57 +09:30
grossmj
624a670ae7 Make sure "port" is defined. 2020-05-07 17:51:32 +09:30
grossmj
406326ccd8 Merge remote-tracking branch 'origin/master' 2020-05-06 11:57:25 +09:30
grossmj
24bc15fb73 Default port set to 80 for server running in the GNS3 VM. Fixes #1737 2020-05-05 12:40:50 +09:30
grossmj
348d8b9438 Make the Web UI the default page. Ref https://github.com/GNS3/gns3-server/issues/1737 2020-04-30 17:27:06 +09:30
grossmj
6787982408 Fix "export portable project forgets contents of README". Fixes #1724 2020-04-30 16:43:00 +09:30
Jeremy Grossmann
c2384917fa Update README. Ref https://github.com/GNS3/gns3-server/issues/1719 2020-04-29 15:01:45 +09:30
grossmj
b80178d0cf Activate unified title and toolbar on MacOS. Fixes #2968 2020-04-29 13:08:51 +09:30
grossmj
e6084ed834 Confirmation dialog for "console connect to all nodes". Fixes #2971 2020-04-28 15:04:39 +09:30
grossmj
ba924cd0d9 Add "Resume all suspended links". Fixes #2858 2020-04-28 14:00:26 +09:30
grossmj
0c3d43346f Revert "Change default path for SecureCRT. Fixes #2896"
This reverts commit 0c4367d77e.
2020-04-28 13:19:38 +09:30
grossmj
fcf6ef3027 Remove @property from ConfigurationDialog(). Fixes #2819 #2965 2020-04-28 11:57:54 +09:30
grossmj
e0f87e573d Use Environmental Markers to force jsonschema version. Fixes https://github.com/GNS3/gns3-gui/issues/2849
Version 3.2.0 with Python >= 3.8
Version 2.6.0 with Python < 3.8
2020-04-27 12:54:17 +09:30
grossmj
3ec068f0cb Use Environmental Markers to force jsonschema version 2.6.0 on Windows/macOS. Ref https://github.com/GNS3/gns3-gui/issues/2849 2020-04-27 12:43:07 +09:30
grossmj
37f1fcf6f7 Remove preferences dialog geometry restoration. Fixes #2807 2020-04-27 11:55:01 +09:30
grossmj
c51dd1605d Merge branch '2.3'
# Conflicts:
#	gns3/version.py
2020-04-13 11:57:04 +09:30
grossmj
4ebf3b4e1c Development on 2.2.8dev1 2020-04-08 01:26:42 +09:30
grossmj
b1ec9d535c Release v2.2.7 2020-04-08 00:03:13 +09:30
grossmj
7fc9087cf0 Fix unable to configure custom adapters for Qemu VMs. Fixes #2961 2020-04-07 15:47:53 +09:30
grossmj
4972d460d2 Fix tests. 2020-04-06 21:09:47 +09:30
grossmj
c388836be7 Fix VNC console template doesn't extract %i (Project UUID). Fixes #2960 2020-04-06 18:34:37 +09:30
grossmj
18ae4a6ce9 Fix contextual menu issues. Ref #2955 2020-03-30 21:37:52 -07:00
grossmj
3020e1fc9f Downgrade to PyQt 5.12.3 Ref #2955 #2952 2020-03-29 18:18:53 +10:30
grossmj
fe2f8424db Downgrade to PyQt 5.13.2 Ref #2955 #2952 2020-03-29 14:46:34 +10:30
grossmj
a744f65199 Merge branch 'master' into 2.3
# Conflicts:
#	gns3/version.py
2020-03-28 13:44:08 +10:30
grossmj
8955b9ee29 Upgrade to PyQt 5.14.1. Ref #2778 2020-01-22 17:53:04 +08:00
grossmj
e727abf27a Change version to 2.3.0dev1 on 2.3 branch 2020-01-16 18:06:51 +08:00
Dominic
c8a8663ff0 Restore editReadme attribute which was removed in Change 'New export project wizard' ( ID c2472bcb22 ) 2019-10-18 17:11:28 +02:00
Dominic
d27e5c1795 Revert "Remove unused edit readme action. Fixes #2816"
This reverts commit 7cd0187f33.
2019-10-18 16:46:48 +02:00
Dominic
0d2f91709c Updated GUI pyqt files from Tab Order 'fixes' in "Tab Order in Preferences and Project Dialog #2872" 2019-10-18 16:45:39 +02:00
64 changed files with 719 additions and 563 deletions

19
.github/workflows/testing.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: testing
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and run Docker image
run: |
docker build -t gns3-gui-test .
docker run gns3-gui-test

View File

@@ -1,2 +0,0 @@
branch:
2.2

View File

@@ -1,21 +0,0 @@
sudo: required
services:
- docker
notifications:
email: false
script:
- docker build -t gns3-gui-test .
- docker run gns3-gui-test
before_deploy:
- sudo pip install twine
- sudo pip install urllib3[secure]
deploy:
provider: pypi
edge:
branch: v1.8.45
user: noplay
password:
secure: FofcqlJjgqf2jaDaXpLHeigVoexbrOz3WwnDuiJpwJxeFUlPY8s2cQs/Bm+dzxzZaOaGiVE0A83v/Xa10yD5tflThHt4sqYJK3iQCinA7wgeAlDimB4xrWUNplfNJZ/Eod5Ssa++E02W+3i29PxpXY//mjCY7qDxaoxul1gnFJY=
on:
tags: true
repo: GNS3/gns3-gui

13
.whitesource Normal file
View File

@@ -0,0 +1,13 @@
{
"scanSettings": {
"configMode": "AUTO",
"configExternalURL": "",
"projectToken" : ""
},
"checkRunSettings": {
"vulnerableCheckRunConclusionLevel": "failure"
},
"issueSettings": {
"minSeverityLevel": "LOW"
}
}

View File

@@ -1,5 +1,61 @@
# Change Log
## 2.2.12 07/08/2020
* Downgrade psutil to version 5.6.7
* Fix log shows the GUI command line without spaces between its arguments. Fixes #3026
* Use server host is console host is equal to "0:0:0:0:0:0:0:0"
* Remove VMware promotion.
## 2.2.11 09/07/2020
* Try to fix "Recent project" selection not working. Ref #3007
* Fix debug entries shown twice in console window and double error messages with remote GNS3VM. Fixes #3010
* Fix deprecation warning. Ref #3009
* Fix tests on macOS. Ref #3009
* Fix sentry SDK is configured twice.
## 2.2.10 18/06/2020
* New fix for multi-device selection/deselection not working as expected with right click. Fixes #2986
* Optimize snap-to-grid code for drawing items. Fixes #2997
* Move jsonschema 2.6.0 requirement in build repository.
* Only use jsonschema 2.6.0 on Windows and macOS.
* Disable default integrations for sentry sdk.
## 2.2.9 04/06/2020
* Fix GUI doesn't detect another GUI on macOS. Fixes #2994
* Support to activate/deactive network connection state replication in Qemu.
* Option to reset or not all MAC addresses when exporting or duplicating a project.
* Fix Multi-device selection/deselection not working as expected with right click. Fixes #2986
* Replace Raven by Sentry SDK. Fixes https://github.com/GNS3/gns3-server/issues/1758
* Fix online help menu URL. Fixes #2984
* Require setuptools>=17.1 in setup.py. Ref https://github.com/GNS3/gns3-server/issues/1751 This is to support environmental markers. https://github.com/pypa/setuptools/blob/master/CHANGES.rst#171
* Update README. Ref https://github.com/GNS3/gns3-server/issues/1719
* Restore editReadme attribute which was removed in Change 'New export project wizard'
* Updated GUI pyqt files from Tab Order 'fixes' in "Tab Order in Preferences and Project Dialog #2872"
## 2.2.8 07/05/2020
* Default port set to 80 for server running in the GNS3 VM. Fixes #1737
* Make the Web UI the default page. Ref https://github.com/GNS3/gns3-server/issues/1737
* Fix "export portable project forgets contents of README". Fixes #1724
* Activate unified title and toolbar on MacOS. Fixes #2968
* Confirmation dialog for "console connect to all nodes". Fixes #2971
* Add "Resume all suspended links". Fixes #2858
* Revert "Change default path for SecureCRT. Fixes #2896"
* Remove @property from ConfigurationDialog(). Fixes #2819 #2965
* Use Environmental Markers to force jsonschema version. Fixes https://github.com/GNS3/gns3-gui/issues/2849 Version 3.2.0 with Python >= 3.8 Version 2.6.0 with Python < 3.8
* Use Environmental Markers to force jsonschema version 2.6.0 on Windows/macOS. Ref https://github.com/GNS3/gns3-gui/issues/2849
* Remove preferences dialog geometry restoration. Fixes #2807
* Fix unable to configure custom adapters for Qemu VMs. Fixes #2961
## 2.2.7 07/04/2020
* Fix VNC console template doesn't extract %i (Project UUID). Fixes #2960
* Fix contextual menu issues. Ref #2955
## 2.2.6 26/03/2020
* Prevent locked drawings to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2948

View File

@@ -1,22 +1,16 @@
# Run tests inside a container
FROM ubuntu:18.04
MAINTAINER GNS3 Team
#ENV DEBIAN_FRONTEND noninteractive
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 clean
ADD dev-requirements.txt /dev-requirements.txt
ADD requirements.txt /requirements.txt
RUN pip3 install -r /dev-requirements.txt
ADD . /src
WORKDIR /src
CMD xvfb-run python3.6 -m pytest -vv

View File

@@ -3,7 +3,6 @@ include AUTHORS
include LICENSE
include MANIFEST.in
include requirements.txt
include tox.ini
recursive-include tests *
recursive-include gns3 *
recursive-include resources *

View File

@@ -1,12 +1,15 @@
GNS3-gui
========
.. image:: https://travis-ci.org/GNS3/gns3-gui.svg?branch=master
:target: https://travis-ci.org/GNS3/gns3-gui
.. image:: https://github.com/GNS3/gns3-gui/workflows/testing/badge.svg
:target: https://github.com/GNS3/gns3-gui/actions?query=workflow%3Atesting
.. image:: https://img.shields.io/pypi/v/gns3-gui.svg
:target: https://pypi.python.org/pypi/gns3-gui
.. image:: https://snyk.io/test/github/GNS3/gns3-gui/badge.svg
:target: https://snyk.io/test/github/GNS3/gns3-gui
GNS3 GUI repository.
@@ -15,6 +18,15 @@ Installation
Please see https://docs.gns3.com/
Software dependencies
---------------------
PyQt5 which is either part of the Linux distribution or installable from PyPi. The other Python dependencies are automatically installed during the GNS3 GUI installation and are listed `here <https://github.com/GNS3/gns3-gui/blob/master/requirements.txt>`_
For connecting to nodes using Telnet, a Telnet client is required. On Linux that's a terminal emulator like xterm, gnome-terminal, konsole plus the telnet program. For connecting to nodes with a GUI, a VNC client is required, optionally a SPICE client can be used for Qemu nodes.
For using packet captures within GNS3, Wireshark should be installed. It's recommended, but if you don't need that functionality you can go without it.
Development
-------------

View File

@@ -1,6 +1,5 @@
-rrequirements.txt
pep8==1.7.0
pytest==4.4.1
pytest-pythonpath==0.7.3 # useful for running tests outside tox
pytest-timeout==1.3.3
pytest==5.4.3
flake8==3.8.3
pytest-timeout==1.4.1

View File

@@ -223,17 +223,10 @@ class ConsoleCmd(cmd.Cmd):
level = int(args[0])
if level == 0:
print("Deactivating debugging")
for handler in root.handlers:
if isinstance(handler, logging.StreamHandler):
root.removeHandler(handler)
root.setLevel(logging.INFO)
else:
root.addHandler(logging.StreamHandler(sys.stdout))
if level == 1:
print("Activating debugging")
else:
print("Activating full debugging")
root.setLevel(logging.DEBUG)
print("Activating debugging")
root.setLevel(logging.DEBUG)
from .main_window import MainWindow
MainWindow.instance().setSettings({"debug_level": level})
else:

View File

@@ -16,19 +16,18 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import psutil
import os
import platform
import struct
import distro
try:
import raven
from raven.transport.http import HTTPTransport
RAVEN_AVAILABLE = True
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
SENTRY_SDK_AVAILABLE = True
except ImportError:
# raven is not installed with deb package in order to simplify packaging
RAVEN_AVAILABLE = False
# Sentry SDK is not installed with deb package in order to simplify packaging
SENTRY_SDK_AVAILABLE = False
from .utils.get_resource import get_resource
from .version import __version__, __version_info__
@@ -52,66 +51,67 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://0bd7e1f3f0d74e758c2e545c38779caf:db1869fba0b04962a3a8d22ab161e524@sentry.io/38506"
if hasattr(sys, "frozen"):
cacert = get_resource("cacert.pem")
if cacert is not None and os.path.isfile(cacert):
DSN += "?ca_certs={}".format(cacert)
else:
log.warning("The SSL certificate bundle file '{}' could not be found".format(cacert))
DSN = "https://19d5ca7c4cfe447b92ea140f78b01c35:fd234a69afcc490bb7ca37bbb3eefefd@o19455.ingest.sentry.io/38506"
_instance = None
def __init__(self):
# We don't want sentry making noise if an error is catched when you don't have internet
# We don't want sentry making noise if an error is caught when we don't have internet
sentry_errors = logging.getLogger('sentry.errors')
sentry_errors.disabled = True
sentry_uncaught = logging.getLogger('sentry.errors.uncaught')
sentry_uncaught.disabled = True
self._sentry_initialized = False
def captureException(self, exception, value, tb):
from .local_server import LocalServer
from .local_config import LocalConfig
from .controller import Controller
from .compute_manager import ComputeManager
if SENTRY_SDK_AVAILABLE:
cacert = None
if hasattr(sys, "frozen"):
cacert_resource = get_resource("cacert.pem")
if cacert_resource is not None and os.path.isfile(cacert_resource):
cacert = cacert_resource
else:
log.error("The SSL certificate bundle file '{}' could not be found".format(cacert_resource))
local_server = LocalServer.instance().localServerSettings()
if local_server["report_errors"]:
if not RAVEN_AVAILABLE:
return
# Don't send log records as events.
sentry_logging = LoggingIntegration(level=logging.INFO, event_level=None)
if os.path.exists(LocalConfig.instance().runAsRootPath()):
log.warning("User has run application as root. Crash reports are disabled.")
sys.exit(1)
return
sentry_sdk.init(dsn=CrashReport.DSN,
release=__version__,
ca_certs=cacert,
default_integrations=False,
integrations=[sentry_logging])
if os.path.exists(".git"):
log.warning("A .git directory exist crash report is turn off for developers. Instant exit")
sys.exit(1)
return
if hasattr(exception, "fingerprint"):
client = raven.Client(CrashReport.DSN, release=__version__, fingerprint=['{{ default }}', exception.fingerprint], transport=HTTPTransport)
else:
client = raven.Client(CrashReport.DSN, release=__version__, transport=HTTPTransport)
context = {
tags = {
"os:name": platform.system(),
"os:release": platform.release(),
"os:win_32": " ".join(platform.win32_ver()),
"os:mac": "{} {}".format(platform.mac_ver()[0], platform.mac_ver()[2]),
"os:linux": " ".join(distro.linux_distribution()),
}
self._add_qt_information(tags)
with sentry_sdk.configure_scope() as scope:
for key, value in tags.items():
scope.set_tag(key, value)
extra_context = {
"python:version": "{}.{}.{}".format(sys.version_info[0],
sys.version_info[1],
sys.version_info[2]),
"python:bit": struct.calcsize("P") * 8,
"python:encoding": sys.getdefaultencoding(),
"python:frozen": "{}".format(hasattr(sys, "frozen")),
"python:frozen": "{}".format(hasattr(sys, "frozen"))
}
# extra controller and compute information
extra_context = {"controller:version": Controller.instance().version(),
"controller:host": Controller.instance().host(),
"controller:connected": Controller.instance().connected()}
from .controller import Controller
from .compute_manager import ComputeManager
extra_context["controller:version"] = Controller.instance().version()
extra_context["controller:host"] = Controller.instance().host()
extra_context["controller:connected"] = Controller.instance().connected()
for index, compute in enumerate(ComputeManager.instance().computes()):
extra_context["compute{}:id".format(index)] = compute.id()
extra_context["compute{}:name".format(index)] = compute.name(),
@@ -120,27 +120,48 @@ class CrashReport:
extra_context["compute{}:platform".format(index)] = compute.capabilities().get("platform")
extra_context["compute{}:version".format(index)] = compute.capabilities().get("version")
context = self._add_qt_information(context)
client.tags_context(context)
client.extra_context(extra_context)
try:
report = client.captureException((exception, value, tb))
except Exception as e:
log.error("Can't send crash report to Sentry: {}".format(e))
return
log.debug("Crash report sent with event ID: {}".format(client.get_ident(report)))
with sentry_sdk.configure_scope() as scope:
for key, value in extra_context.items():
scope.set_extra(key, value)
def captureException(self, exception, value, tb):
from .local_server import LocalServer
from .local_config import LocalConfig
local_server = LocalServer.instance().localServerSettings()
if local_server["report_errors"]:
if not SENTRY_SDK_AVAILABLE:
log.warning("Cannot capture exception: Sentry SDK is not available")
return
if os.path.exists(LocalConfig.instance().runAsRootPath()):
log.warning("User is running application as root. Crash reports disabled.")
return
if not hasattr(sys, "frozen") and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".git")):
log.warning(".git directory detected, crash reporting is turned off for developers.")
return
try:
error = (exception, value, tb)
sentry_sdk.capture_exception(error=error)
log.info("Crash report sent with event ID: {}".format(sentry_sdk.last_event_id()))
except Exception as e:
log.warning("Can't send crash report to Sentry: {}".format(e))
def _add_qt_information(self, tags):
def _add_qt_information(self, context):
try:
from .qt import QtCore
from .qt import sip
except ImportError:
return context
context["psutil:version"] = psutil.__version__
context["pyqt:version"] = QtCore.PYQT_VERSION_STR
context["qt:version"] = QtCore.QT_VERSION_STR
context["sip:version"] = sip.SIP_VERSION_STR
return context
return tags
tags["pyqt:version"] = QtCore.PYQT_VERSION_STR
tags["qt:version"] = QtCore.QT_VERSION_STR
tags["sip:version"] = sip.SIP_VERSION_STR
return tags
@classmethod
def instance(cls):

View File

@@ -49,7 +49,6 @@ class ConfigurationDialog(QtWidgets.QDialog, Ui_configurationDialog):
self._settings = settings
self._configuration_page = configuration_page
@property
def settings(self):
return self._settings

View File

@@ -135,17 +135,20 @@ class ProjectDialog(QtWidgets.QDialog, Ui_ProjectDialog):
new_project_name)
name = name.strip()
if reply and len(name) > 0:
reset_mac_addresses = self.uiResetMacAddressesCheckBox.isChecked()
if Controller.instance().isRemote():
Controller.instance().post("/projects/{project_id}/duplicate".format(project_id=project_id),
self._duplicateCallback,
body={"name": name},
body={"name": name, "reset_mac_addresses": reset_mac_addresses},
progressText="Duplicating project '{}'...".format(name),
timeout=None)
else:
project_location = os.path.join(Topology.instance().projectsDirPath(), name)
Controller.instance().post("/projects/{project_id}/duplicate".format(project_id=project_id),
self._duplicateCallback,
body={"name": name, "path": project_location},
body={"name": name, "path": project_location, "reset_mac_addresses": reset_mac_addresses},
progressText="Duplicating project '{}'...".format(name),
timeout=None)
@@ -234,13 +237,13 @@ class ProjectDialog(QtWidgets.QDialog, Ui_ProjectDialog):
"""
menu = QtWidgets.QMenu()
menu.triggered.connect(self._menuTriggeredSlot)
if Controller.instance().isRemote():
for action in self._main_window.recent_project_actions:
menu.addAction(action)
else:
for action in self._main_window.recent_file_actions:
menu.addAction(action)
menu.triggered.connect(self._menuTriggeredSlot)
menu.exec_(QtGui.QCursor.pos())
def _overwriteProjectCallback(self, result, error=False, **kwargs):

View File

@@ -55,21 +55,19 @@ class ExportProjectWizard(QtWidgets.QWizard, Ui_ExportProjectWizard):
self.uiCompressionComboBox.setCurrentIndex(1)
self.helpRequested.connect(self._showHelpSlot)
self.uiPathBrowserToolButton.clicked.connect(self._pathBrowserSlot)
self._loadReadme()
# read an existing README.txt file if existing
readme_text = None
if project.filesDir():
readme_path = os.path.join(project.filesDir(), "README.txt")
if os.path.exists(readme_path):
try:
with open(readme_path, "rb") as file:
readme_text = file.read().decode("utf-8", errors="replace")
except OSError as e:
log.warning("could not read {}: {}".format(readme_path, e))
def _loadReadme(self):
if readme_text is None:
self._project.get("/files/README.txt", self._loadedReadme)
def _loadedReadme(self, result, error=False, raw_body=None, context={}, **kwargs):
if not error:
self.uiReadmeTextEdit.setPlainText(raw_body.decode("utf-8", errors="replace"))
else:
readme_text = "Project: '{}' created on {}\nAuthor: John Doe <john.doe@example.com>\n\nNo project description was given".format(self._project.name(), datetime.date.today())
self.uiReadmeTextEdit.setPlainText(readme_text)
self.uiReadmeTextEdit.setPlainText(readme_text)
def _pathBrowserSlot(self):
@@ -136,8 +134,12 @@ class ExportProjectWizard(QtWidgets.QWizard, Ui_ExportProjectWizard):
include_snapshots = "yes"
else:
include_snapshots = "no"
if self.uiResetMacAddressesCheckBox.isChecked():
reset_mac_addresses = "yes"
else:
reset_mac_addresses = "no"
compression = self.uiCompressionComboBox.currentData()
export_worker = ExportProjectWorker(self._project, self._path, include_images, include_snapshots, compression)
export_worker = ExportProjectWorker(self._project, self._path, include_images, include_snapshots, reset_mac_addresses, compression)
progress_dialog = ProgressDialog(export_worker, "Exporting project", "Exporting portable project files...", "Cancel", parent=self, create_thread=False)
progress_dialog.show()
progress_dialog.exec_()

View File

@@ -52,7 +52,8 @@ class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
"engine": "vmware",
"vcpus": 1,
"ram": 2048,
"vmname": "GNS3 VM"
"vmname": "GNS3 VM",
"port": 80
}
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
@@ -66,7 +67,6 @@ class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
self.uiRefreshPushButton.clicked.connect(self._refreshVMListSlot)
self.uiVmwareRadioButton.clicked.connect(self._listVMwareVMsSlot)
self.uiVirtualBoxRadioButton.clicked.connect(self._listVirtualBoxVMsSlot)
self.uiVMwareBannerButton.clicked.connect(self._VMwareBannerButtonClickedSlot)
settings = parent.settings()
self.uiShowCheckBox.setChecked(settings["hide_setup_wizard"])
@@ -93,11 +93,6 @@ class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
self.uiLocalServerHostComboBox.addItem("::", "::") # all IPv6 addresses
self.uiLocalServerHostComboBox.addItem("0.0.0.0", "0.0.0.0") # all IPv4 addresses
if sys.platform.startswith("darwin"):
self.uiVMwareBannerButton.setIcon(QtGui.QIcon(":/images/vmware_fusion_banner.png"))
else:
self.uiVMwareBannerButton.setIcon(QtGui.QIcon(":/images/vmware_workstation_banner.png"))
if sys.platform.startswith("linux"):
self.uiLocalRadioButton.setChecked(True)
self.uiLocalLabel.setText("Dependencies like Dynamips and Qemu must be manually installed")
@@ -120,13 +115,6 @@ class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
self.uiLocalServerPathLineEdit.setText(path)
def _VMwareBannerButtonClickedSlot(self):
if sys.platform.startswith("darwin"):
url = "http://send.onenetworkdirect.net/z/621395/CD225091/"
else:
url = "http://send.onenetworkdirect.net/z/616207/CD225091/"
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url))
def _listVMwareVMsSlot(self):
"""
Slot to refresh the VMware VMs list.

View File

@@ -460,25 +460,15 @@ class GraphicsView(QtWidgets.QGraphicsView):
else:
item.setSelected(True)
elif is_not_link and is_not_logo and event.button() == QtCore.Qt.RightButton and not self._adding_link:
if item and not sip.isdeleted(item):
# Prevent right clicking on a selected item from de-selecting all other items
if not item.isSelected():
if not event.modifiers() & QtCore.Qt.ControlModifier:
for it in self.scene().items():
it.setSelected(False)
item.setSelected(True)
self._showDeviceContextualMenu(QtGui.QCursor.pos())
else:
self._showDeviceContextualMenu(QtGui.QCursor.pos())
# when more than one item is selected display the contextual menu even if mouse is not above an item
elif len(self.scene().selectedItems()) > 1:
self._showDeviceContextualMenu(QtGui.QCursor.pos())
pass #TODO: remove this without creating a bug...
elif is_not_link and self._adding_link and event.button() == QtCore.Qt.RightButton:
# send a escape key to the main window to cancel the link addition
key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier)
QtWidgets.QApplication.sendEvent(self._main_window, key)
elif item and isinstance(item, NodeItem) and self._adding_link and event.button() == QtCore.Qt.LeftButton:
self._userNodeLinking(event, item)
#context_event = QtGui.QContextMenuEvent(QtGui.QContextMenuEvent.Mouse, event.pos())
#QtWidgets.QApplication.sendEvent(self, context_event)
elif event.button() == QtCore.Qt.LeftButton and self._adding_note:
pos = self.mapToScene(event.pos())
note = self.createDrawingItem("text", pos.x(), pos.y(), 2)
@@ -512,6 +502,46 @@ class GraphicsView(QtWidgets.QGraphicsView):
self.toggleUiDeviceMenu()
def contextMenuEvent(self, event):
"""
Handles all context menu events.
:param event: QContextMenuEvent instance
"""
is_not_link = True
is_not_logo = True
item = self.itemAt(event.pos())
if item and sip.isdeleted(item):
return
if item and (isinstance(item, LinkItem) or isinstance(item.parentItem(), LinkItem)):
is_not_link = False
if item and (isinstance(item, LogoItem) or isinstance(item.parentItem(), LogoItem)):
is_not_logo = False
else:
for it in self.scene().items():
if isinstance(it, LinkItem):
it.setHovered(False)
if is_not_link and is_not_logo and not self._adding_link:
if item and not sip.isdeleted(item):
# Prevent right clicking on a selected item from de-selecting all other items
if not item.isSelected():
if not event.modifiers() & QtCore.Qt.ControlModifier:
for it in self.scene().items():
it.setSelected(False)
item.setSelected(True)
self._showDeviceContextualMenu(event.globalPos())
# when more than one item is selected display the contextual menu even if mouse is not above an item
elif len(self.scene().selectedItems()) > 1:
self._showDeviceContextualMenu(event.globalPos())
#elif item and isinstance(item, NodeItem) and self._adding_link:
# self._userNodeLinking(event, item)
else:
super().contextMenuEvent(event)
def mouseReleaseEvent(self, event):
"""
Handles all mouse release events.
@@ -724,6 +754,11 @@ class GraphicsView(QtWidgets.QGraphicsView):
self.populateDeviceContextualMenu(menu)
menu.exec_(pos)
menu.clear()
# Make sure to deselect all items.
# This is to prevent a bug on Windows
# see https://github.com/GNS3/gns3-gui/issues/2986
for it in self.scene().items():
it.setSelected(False)
def populateDeviceContextualMenu(self, menu):
"""
@@ -1103,6 +1138,16 @@ class GraphicsView(QtWidgets.QGraphicsView):
items = [item for item in self.scene().items()
if isinstance(item, NodeItem) and item.node().consoleType() != "none"]
nb_items = len(items)
if nb_items > 10:
proceed = QtWidgets.QMessageBox.question(self,
"Console to all nodes",
"You are about to open console windows to {} nodes. Are you sure?".format(nb_items),
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if proceed == QtWidgets.QMessageBox.No:
return
self.consoleFromItems(items)
def consoleActionSlot(self):

View File

@@ -212,14 +212,13 @@ class DrawingItem:
self._project.delete("/drawings/" + self._id, None, body=self.__json__())
def itemChange(self, change, value):
if change == QtWidgets.QGraphicsItem.ItemPositionHasChanged and self.isActive() and self._main_window.uiSnapToGridAction.isChecked():
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self.isActive() and self._main_window.uiSnapToGridAction.isChecked():
grid_size = self._graphics_view.drawingGridSize()
mid_x = self.boundingRect().width() / 2
tmp_x = (grid_size * round((self.x() + mid_x) / grid_size)) - mid_x
value.setX((grid_size * round((value.x() + mid_x) / grid_size)) - mid_x)
mid_y = self.boundingRect().height() / 2
tmp_y = (grid_size * round((self.y() + mid_y) / grid_size)) - mid_y
if tmp_x != self.x() and tmp_y != self.y():
self.setPos(tmp_x, tmp_y)
value.setY((grid_size * round((value.y()+mid_y)/grid_size)) - mid_y)
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
if not value:

View File

@@ -280,23 +280,31 @@ class LinkItem(QtWidgets.QGraphicsPathItem):
:param: QGraphicsSceneMouseEvent instance
"""
if event.button() == QtCore.Qt.RightButton:
if self._adding_flag:
# send a escape key to the main window to cancel the link addition
from ..main_window import MainWindow
key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier)
QtWidgets.QApplication.sendEvent(MainWindow.instance(), key)
return
if event.button() == QtCore.Qt.RightButton and self._adding_flag:
# send a escape key to the main window to cancel the link addition
from ..main_window import MainWindow
key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier)
QtWidgets.QApplication.sendEvent(MainWindow.instance(), key)
return
else:
super().mousePressEvent(event)
if not sip_is_deleted(self):
# create the contextual menu
self.setAcceptHoverEvents(False)
menu = QtWidgets.QMenu()
self.populateLinkContextualMenu(menu)
menu.exec_(QtGui.QCursor.pos())
self.setAcceptHoverEvents(True)
self._hovered = False
self.adjust()
def contextMenuEvent(self, event):
"""
Handles all context menu events.
:param event: QContextMenuEvent instance
"""
if not sip_is_deleted(self):
# create the contextual menu
self.setAcceptHoverEvents(False)
menu = QtWidgets.QMenu()
self.populateLinkContextualMenu(menu)
menu.exec_(QtGui.QCursor.pos())
self.setAcceptHoverEvents(True)
self._hovered = False
self.adjust()
def keyPressEvent(self, event):
"""

View File

@@ -488,7 +488,7 @@ class LocalConfig(QtCore.QObject):
if pid != my_pid:
try:
process = psutil.Process(pid=pid)
ps_name = process.name()
ps_name = process.name().lower()
except (OSError, psutil.NoSuchProcess, psutil.AccessDenied):
pass
else:

View File

@@ -255,8 +255,7 @@ def main():
current_year = datetime.date.today().year
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.info("Application started with {}".format(" ".join(sys.argv)))
# 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)

View File

@@ -84,6 +84,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self._settings = {}
self.setupUi(self)
self.setUnifiedTitleAndToolBarOnMac(True)
self._notif_dialog = NotifDialog(self)
# Setup logger
@@ -240,7 +241,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.uiLockAllAction.triggered.connect(self._lockActionSlot)
# tool menu connections
self.uiWebInterfaceAction.triggered.connect(self._openLightWebInterfaceActionSlot)
self.uiWebUIAction.triggered.connect(self._openWebInterfaceActionSlot)
# control menu connections
@@ -260,6 +260,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.uiDrawRectangleAction.triggered.connect(self._drawRectangleActionSlot)
self.uiDrawEllipseAction.triggered.connect(self._drawEllipseActionSlot)
self.uiDrawLineAction.triggered.connect(self._drawLineActionSlot)
self.uiEditReadmeAction.triggered.connect(self._editReadmeActionSlot)
# help menu connections
self.uiOnlineHelpAction.triggered.connect(self._onlineHelpActionSlot)
@@ -322,10 +323,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
LocalConfig.instance().saveSectionSettings(self.__class__.__name__, self._settings)
self.settings_updated_signal.emit()
def _openLightWebInterfaceActionSlot(self):
if Controller.instance().connected():
QtGui.QDesktopServices.openUrl(QtCore.QUrl(Controller.instance().httpClient().fullUrl()))
def _openWebInterfaceActionSlot(self):
if Controller.instance().connected():
base_url = Controller.instance().httpClient().fullUrl()
@@ -914,7 +911,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
Slot to launch a browser pointing to the documentation page.
"""
QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://gns3.com/support/docs"))
QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://docs.gns3.com/"))
def _checkForUpdateActionSlot(self, silent=False):
"""
@@ -1058,11 +1055,17 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
with Progress.instance().context(min_duration=0):
dialog = PreferencesDialog(self)
dialog.restoreGeometry(QtCore.QByteArray().fromBase64(self._settings["preferences_dialog_geometry"].encode()))
#dialog.restoreGeometry(QtCore.QByteArray().fromBase64(self._settings["preferences_dialog_geometry"].encode()))
dialog.show()
dialog.exec_()
self._settings["preferences_dialog_geometry"] = bytes(dialog.saveGeometry().toBase64()).decode()
self.setSettings(self._settings)
#self._settings["preferences_dialog_geometry"] = bytes(dialog.saveGeometry().toBase64()).decode()
#self.setSettings(self._settings)
def _editReadmeActionSlot(self):
"""
Slot to edit the README file
"""
Topology.instance().editReadme()
def resizeEvent(self, event):
self._notif_dialog.resize()
@@ -1182,8 +1185,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
# restore debug level
if self._settings["debug_level"]:
print("Activating debugging (use command 'debug 0' to deactivate)")
root = logging.getLogger()
root.addHandler(logging.StreamHandler(sys.stdout))
root.setLevel(logging.DEBUG)
# restore the style
self._setStyle(self._settings.get("style"))

View File

@@ -210,7 +210,7 @@ class IOUDevicePreferencesPage(QtWidgets.QWidget, Ui_IOUDevicePreferencesPageWid
del self._iou_devices[key]
item.setText(0, iou_device["name"])
item.setData(0, QtCore.Qt.UserRole, new_key)
self._refreshInfo(dialog.settings)
self._refreshInfo(dialog.settings())
def _iouDeviceDeleteSlot(self):
"""

View File

@@ -401,7 +401,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
QtWidgets.QMessageBox.critical(self, "Invalid format", "Invalid port name format")
return
if self._settings["legacy_networking"]:
if self.uiLegacyNetworkingCheckBox.isChecked():
network_devices = {}
for nic, desc in self._qemu_network_devices.items():
if nic in self._legacy_devices:
@@ -525,6 +525,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
self._custom_adapters = settings["custom_adapters"].copy()
self.uiLegacyNetworkingCheckBox.setChecked(settings["legacy_networking"])
self.uiReplicateNetworkConnectionStateCheckBox.setChecked(settings["replicate_network_connection_state"])
# load the MAC address setting
self.uiMacAddrLineEdit.setInputMask("HH:HH:HH:HH:HH:HH;_")
@@ -657,6 +658,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
settings["adapters"] = adapters
settings["legacy_networking"] = self.uiLegacyNetworkingCheckBox.isChecked()
settings["replicate_network_connection_state"] = self.uiReplicateNetworkConnectionStateCheckBox.isChecked()
settings["custom_adapters"] = self._custom_adapters.copy()
settings["on_close"] = self.uiOnCloseComboBox.itemData(self.uiOnCloseComboBox.currentIndex())
settings["cpus"] = self.uiCPUSpinBox.value()

View File

@@ -71,6 +71,7 @@ class QemuVM(Node):
"adapter_type": QEMU_VM_SETTINGS["adapter_type"],
"mac_address": QEMU_VM_SETTINGS["mac_address"],
"legacy_networking": QEMU_VM_SETTINGS["legacy_networking"],
"replicate_network_connection_state": QEMU_VM_SETTINGS["replicate_network_connection_state"],
"platform": QEMU_VM_SETTINGS["platform"],
"on_close": QEMU_VM_SETTINGS["on_close"],
"cpu_throttling": QEMU_VM_SETTINGS["cpu_throttling"],

View File

@@ -56,6 +56,7 @@ QEMU_VM_SETTINGS = {
"adapter_type": "e1000",
"mac_address": "",
"legacy_networking": False,
"replicate_network_connection_state": True,
"on_close": "power_off",
"platform": "",
"cpu_throttling": 0,

View File

@@ -526,6 +526,23 @@
<string>Network</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="0">
<widget class="QLabel" name="uiPortSegmentSizeLabel">
<property name="text">
<string>Segment size:</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="uiPortSegmentSizeSpinBox">
<property name="maximum">
<number>128</number>
</property>
<property name="singleStep">
<number>4</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="uiAdaptersLabel">
<property name="text">
@@ -560,13 +577,6 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="uiPortSegmentSizeLabel">
<property name="text">
<string>Segment size:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="uiMacAddrLabel">
<property name="text">
@@ -598,14 +608,14 @@
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<item row="8" column="0" colspan="3">
<widget class="QCheckBox" name="uiLegacyNetworkingCheckBox">
<property name="text">
<string>Use the legacy networking mode</string>
</property>
</widget>
</item>
<item row="8" column="2">
<item row="9" column="2">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -628,16 +638,6 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="uiPortSegmentSizeSpinBox">
<property name="maximum">
<number>128</number>
</property>
<property name="singleStep">
<number>4</number>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QSpinBox" name="uiAdaptersSpinBox">
<property name="sizePolicy">
@@ -654,6 +654,13 @@
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QCheckBox" name="uiReplicateNetworkConnectionStateCheckBox">
<property name="text">
<string>Replicate network connection states in Qemu</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="uiAdvancedSettingsTab">

View File

@@ -2,12 +2,14 @@
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/qemu/ui/qemu_vm_configuration_page.ui'
#
# Created by: PyQt5 UI code generator 5.9
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_QemuVMConfigPageWidget(object):
def setupUi(self, QemuVMConfigPageWidget):
QemuVMConfigPageWidget.setObjectName("QemuVMConfigPageWidget")
@@ -268,6 +270,14 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiNetworkTab.setObjectName("uiNetworkTab")
self.gridLayout_5 = QtWidgets.QGridLayout(self.uiNetworkTab)
self.gridLayout_5.setObjectName("gridLayout_5")
self.uiPortSegmentSizeLabel = QtWidgets.QLabel(self.uiNetworkTab)
self.uiPortSegmentSizeLabel.setObjectName("uiPortSegmentSizeLabel")
self.gridLayout_5.addWidget(self.uiPortSegmentSizeLabel, 3, 0, 1, 1)
self.uiPortSegmentSizeSpinBox = QtWidgets.QSpinBox(self.uiNetworkTab)
self.uiPortSegmentSizeSpinBox.setMaximum(128)
self.uiPortSegmentSizeSpinBox.setSingleStep(4)
self.uiPortSegmentSizeSpinBox.setObjectName("uiPortSegmentSizeSpinBox")
self.gridLayout_5.addWidget(self.uiPortSegmentSizeSpinBox, 3, 1, 1, 2)
self.uiAdaptersLabel = QtWidgets.QLabel(self.uiNetworkTab)
self.uiAdaptersLabel.setObjectName("uiAdaptersLabel")
self.gridLayout_5.addWidget(self.uiAdaptersLabel, 0, 0, 1, 1)
@@ -284,9 +294,6 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiPortNameFormatLineEdit.setText("")
self.uiPortNameFormatLineEdit.setObjectName("uiPortNameFormatLineEdit")
self.gridLayout_5.addWidget(self.uiPortNameFormatLineEdit, 2, 1, 1, 2)
self.uiPortSegmentSizeLabel = QtWidgets.QLabel(self.uiNetworkTab)
self.uiPortSegmentSizeLabel.setObjectName("uiPortSegmentSizeLabel")
self.gridLayout_5.addWidget(self.uiPortSegmentSizeLabel, 3, 0, 1, 1)
self.uiMacAddrLabel = QtWidgets.QLabel(self.uiNetworkTab)
self.uiMacAddrLabel.setObjectName("uiMacAddrLabel")
self.gridLayout_5.addWidget(self.uiMacAddrLabel, 4, 0, 1, 1)
@@ -304,9 +311,9 @@ class Ui_QemuVMConfigPageWidget(object):
self.gridLayout_5.addWidget(self.uiCustomAdaptersConfigurationPushButton, 6, 1, 1, 2)
self.uiLegacyNetworkingCheckBox = QtWidgets.QCheckBox(self.uiNetworkTab)
self.uiLegacyNetworkingCheckBox.setObjectName("uiLegacyNetworkingCheckBox")
self.gridLayout_5.addWidget(self.uiLegacyNetworkingCheckBox, 7, 0, 1, 3)
self.gridLayout_5.addWidget(self.uiLegacyNetworkingCheckBox, 8, 0, 1, 3)
spacerItem3 = QtWidgets.QSpacerItem(20, 261, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_5.addItem(spacerItem3, 8, 2, 1, 1)
self.gridLayout_5.addItem(spacerItem3, 9, 2, 1, 1)
self.uiAdapterTypesComboBox = QtWidgets.QComboBox(self.uiNetworkTab)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -315,11 +322,6 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiAdapterTypesComboBox.setSizePolicy(sizePolicy)
self.uiAdapterTypesComboBox.setObjectName("uiAdapterTypesComboBox")
self.gridLayout_5.addWidget(self.uiAdapterTypesComboBox, 5, 1, 1, 2)
self.uiPortSegmentSizeSpinBox = QtWidgets.QSpinBox(self.uiNetworkTab)
self.uiPortSegmentSizeSpinBox.setMaximum(128)
self.uiPortSegmentSizeSpinBox.setSingleStep(4)
self.uiPortSegmentSizeSpinBox.setObjectName("uiPortSegmentSizeSpinBox")
self.gridLayout_5.addWidget(self.uiPortSegmentSizeSpinBox, 3, 1, 1, 2)
self.uiAdaptersSpinBox = QtWidgets.QSpinBox(self.uiNetworkTab)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -330,6 +332,9 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiAdaptersSpinBox.setMaximum(275)
self.uiAdaptersSpinBox.setObjectName("uiAdaptersSpinBox")
self.gridLayout_5.addWidget(self.uiAdaptersSpinBox, 0, 1, 1, 2)
self.uiReplicateNetworkConnectionStateCheckBox = QtWidgets.QCheckBox(self.uiNetworkTab)
self.uiReplicateNetworkConnectionStateCheckBox.setObjectName("uiReplicateNetworkConnectionStateCheckBox")
self.gridLayout_5.addWidget(self.uiReplicateNetworkConnectionStateCheckBox, 7, 0, 1, 3)
self.uiQemutabWidget.addTab(self.uiNetworkTab, "")
self.uiAdvancedSettingsTab = QtWidgets.QWidget()
self.uiAdvancedSettingsTab.setObjectName("uiAdvancedSettingsTab")
@@ -502,16 +507,17 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiCdromImageLabel.setText(_translate("QemuVMConfigPageWidget", "Image:"))
self.uiCdromImageToolButton.setText(_translate("QemuVMConfigPageWidget", "&Browse..."))
self.uiQemutabWidget.setTabText(self.uiQemutabWidget.indexOf(self.uiCdromTab), _translate("QemuVMConfigPageWidget", "CD/DVD"))
self.uiPortSegmentSizeLabel.setText(_translate("QemuVMConfigPageWidget", "Segment size:"))
self.uiAdaptersLabel.setText(_translate("QemuVMConfigPageWidget", "Adapters:"))
self.uiFirstPortNameLabel.setText(_translate("QemuVMConfigPageWidget", "First port name:"))
self.uiPortNameFormatLabel.setToolTip(_translate("QemuVMConfigPageWidget", "<html><head/><body><p>{0} - the port number, from 0 to the number of adapters-1.</p><p>{1} - the segment number, from 0 to the number of segments-1.</p><p>{port0} - named alias for {0}.</p><p>{port1} - the port number, from 1 to the number of adapters.</p><p>{segment0} - named alias for {1}.</p><p>{segment1} - the segment number, from 1 to the number of segments.</p></body></html>"))
self.uiPortNameFormatLabel.setText(_translate("QemuVMConfigPageWidget", "Name format:"))
self.uiPortSegmentSizeLabel.setText(_translate("QemuVMConfigPageWidget", "Segment size:"))
self.uiMacAddrLabel.setText(_translate("QemuVMConfigPageWidget", "Base MAC:"))
self.uiAdapterTypesLabel.setText(_translate("QemuVMConfigPageWidget", "Type:"))
self.uiCustomAdaptersLabel.setText(_translate("QemuVMConfigPageWidget", "Custom adapters:"))
self.uiCustomAdaptersConfigurationPushButton.setText(_translate("QemuVMConfigPageWidget", "&Configure custom adapters"))
self.uiLegacyNetworkingCheckBox.setText(_translate("QemuVMConfigPageWidget", "Use the legacy networking mode"))
self.uiReplicateNetworkConnectionStateCheckBox.setText(_translate("QemuVMConfigPageWidget", "Replicate network connection states in Qemu"))
self.uiQemutabWidget.setTabText(self.uiQemutabWidget.indexOf(self.uiNetworkTab), _translate("QemuVMConfigPageWidget", "Network"))
self.uiLinuxBootGroupBox.setTitle(_translate("QemuVMConfigPageWidget", "Linux boot specific settings"))
self.uiKernelCommandLineLabel.setText(_translate("QemuVMConfigPageWidget", "Kernel command line:"))
@@ -548,4 +554,3 @@ class Ui_QemuVMConfigPageWidget(object):
self.uiBaseVMCheckBox.setText(_translate("QemuVMConfigPageWidget", "Use as a linked base VM"))
self.uiQemutabWidget.setTabText(self.uiQemutabWidget.indexOf(self.uiAdvancedSettingsTab), _translate("QemuVMConfigPageWidget", "Advanced"))
self.uiQemutabWidget.setTabText(self.uiQemutabWidget.indexOf(self.uiUsageTab), _translate("QemuVMConfigPageWidget", "Usage"))

View File

@@ -654,7 +654,7 @@ class Node(BaseNode):
"""
host = self.settings()["console_host"]
if host is None or host == "::" or host == "0.0.0.0":
if host is None or host == "::" or host == "0.0.0.0" or host == "0:0:0:0:0:0:0:0":
host = Controller.instance().host()
return host
@@ -704,10 +704,10 @@ class Node(BaseNode):
nodeTelnetConsole(self, console_port, command)
elif console_type == "vnc":
from .vnc_console import vncConsole
vncConsole(self.consoleHost(), console_port, command)
vncConsole(self, console_port, command)
elif console_type.startswith("spice"):
from .spice_console import spiceConsole
spiceConsole(self.consoleHost(), console_port, command)
spiceConsole(self, console_port, command)
elif console_type == "http" or console_type == "https":
QtGui.QDesktopServices.openUrl(QtCore.QUrl("{console_type}://{host}:{port}{path}".format(console_type=console_type, host=self.consoleHost(), port=console_port, path=self.consoleHttpPath())))

View File

@@ -142,19 +142,14 @@ class NodesView(QtWidgets.QTreeWidget):
# when we're in docked mode, outside main window
return self.window().parent()
def mousePressEvent(self, event):
def contextMenuEvent(self, event):
"""
Handles all mouse press events.
Handles all context menu events.
:param: QMouseEvent instance
:param event: QContextMenuEvent instance
"""
# Check that an item has been selected and right click
if event.button() == QtCore.Qt.RightButton:
self._showContextualMenu()
event.accept()
return
super().mousePressEvent(event)
self._showContextualMenu(event.globalPos())
def mouseMoveEvent(self, event):
"""
@@ -181,7 +176,7 @@ class NodesView(QtWidgets.QTreeWidget):
drag.exec_(QtCore.Qt.CopyAction)
event.accept()
def _showContextualMenu(self):
def _showContextualMenu(self, pos):
menu = QtWidgets.QMenu()
refresh_action = QtWidgets.QAction("Refresh templates", menu)
@@ -207,7 +202,7 @@ class NodesView(QtWidgets.QTreeWidget):
delete_action.triggered.connect(qpartial(self._deleteSlot, template))
menu.addAction(delete_action)
menu.exec_(QtGui.QCursor.pos())
menu.exec_(pos)
def _configurationSlot(self, template, configuration_page, source):

View File

@@ -66,6 +66,12 @@ class GNS3VMPreferencesPage(QtWidgets.QWidget, Ui_GNS3VMPreferencesPageWidget):
self.uiRamLabel.setVisible(engine["support_ram"])
self.uiRamSpinBox.setVisible(engine["support_ram"])
self.uiCpuSpinBox.setVisible(engine["support_ram"])
if engine_id == "remote":
self.uiPortLabel.setVisible(False)
self.uiPortSpinBox.setVisible(False)
else:
self.uiPortLabel.setVisible(True)
self.uiPortSpinBox.setVisible(True)
self._refreshVMSlot(ignore_error=True)
def loadPreferences(self):
@@ -91,6 +97,7 @@ class GNS3VMPreferencesPage(QtWidgets.QWidget, Ui_GNS3VMPreferencesPageWidget):
self._settings = result
self.uiRamSpinBox.setValue(self._settings["ram"])
self.uiCpuSpinBox.setValue(self._settings["vcpus"])
self.uiPortSpinBox.setValue(self._settings.get("port", 3080))
self.uiEnableVMCheckBox.setChecked(self._settings["enable"])
if self._settings["when_exit"] == "keep":
self.uiWhenExitKeepRadioButton.setChecked(True)
@@ -168,7 +175,8 @@ class GNS3VMPreferencesPage(QtWidgets.QWidget, Ui_GNS3VMPreferencesPageWidget):
"when_exit": when_exit,
"engine": self.uiGNS3VMEngineComboBox.currentData(),
"ram": self.uiRamSpinBox.value(),
"vcpus": self.uiCpuSpinBox.value()
"vcpus": self.uiCpuSpinBox.value(),
"port": self.uiPortSpinBox.value()
}
if self._old_settings != settings:
Controller.instance().put("/gns3vm", self._saveSettingsCallback, settings, timeout=60 * 5)

View File

@@ -115,10 +115,13 @@ class LogQMessageBox(QtWidgets.QMessageBox):
show a stack trace when a critical message box is shown in debug mode
"""
@staticmethod
def critical(parent, title, message, *args):
def critical(parent, title, message, *args, show_stack_info=False):
if message.startswith("QXcbConnection"): # Qt noise not relevant
return
LogQMessageBox._get_logger().critical(re.sub(r"<[^<]+?>", "", message), stack_info=LogQMessageBox.stack_info())
stack_info = None
if show_stack_info:
stack_info = LogQMessageBox.stack_info()
LogQMessageBox._get_logger().critical(re.sub(r"<[^<]+?>", "", message), stack_info=stack_info)
if parent is False:
# special case to display a QMessageBox before the main window is created.
parent = None

View File

@@ -19,7 +19,7 @@
import json
import copy
import os
import collections
import collections.abc
import jsonschema
@@ -30,7 +30,7 @@ class ApplianceError(Exception):
pass
class Appliance(collections.Mapping):
class Appliance(collections.abc.Mapping):
def __init__(self, registry, path):
"""

View File

@@ -61,8 +61,8 @@ if sys.platform.startswith("win"):
'Royal TS V3': r'{}\code4ward.net\Royal TS V3\RTS3App.exe /connectadhoc:%h /adhoctype:terminal /p:IsTelnetConnection="true" /p:ConnectionType="telnet;Telnet Connection" /p:Port="%p" /p:Name="%d"'.format(program_files),
'Royal TS V5': r'"{}\Royal TS V5\RoyalTS.exe" /protocol:terminal /using:adhoc /uri:"%h" /property:Port="%p" /property:IsTelnetConnection="true" /property:Name="%d"'.format(program_files_x86),
'SuperPutty': r'SuperPutty.exe -telnet "%h -P %p -wt \"%d\""',
'SecureCRT': r'"{}\VanDyke Software\Clients\SecureCRT.exe" /N "%d" /T /TELNET %h %p'.format(program_files),
'SecureCRT (personal profile)': r'"{}\AppData\Local\VanDyke Software\Clients\SecureCRT.exe" /T /N "%d" /TELNET %h %p'.format(userprofile),
'SecureCRT': r'"{}\VanDyke Software\SecureCRT\SecureCRT.exe" /N "%d" /T /TELNET %h %p'.format(program_files),
'SecureCRT (personal profile)': r'"{}\AppData\Local\VanDyke Software\SecureCRT\SecureCRT.exe" /T /N "%d" /TELNET %h %p'.format(userprofile),
'TeraTerm Pro': r'"{}\teraterm\ttermpro.exe" /W="%d" /M="ttstart.macro" /T=1 %h %p'.format(program_files_x86),
'Telnet': 'telnet %h %p',
'Xshell 4': r'"{}\NetSarang\Xshell 4\xshell.exe" -url telnet://%h:%p'.format(program_files_x86),
@@ -295,7 +295,7 @@ GENERAL_SETTINGS = {
"recent_projects": [],
"geometry": "",
"state": "",
"preferences_dialog_geometry": "",
#"preferences_dialog_geometry": "",
"debug_level": 0,
"multi_profiles": False,
"hdpi": not sys.platform.startswith("linux"),

View File

@@ -24,15 +24,17 @@ import os
import shlex
import subprocess
from .controller import Controller
import logging
log = logging.getLogger(__name__)
def spiceConsole(host, port, command):
def spiceConsole(node, port, command):
"""
Start a SPICE console program.
:param host: host or IP address
:param node: Node instance
:param port: port number
:param command: command to be executed
"""
@@ -41,6 +43,9 @@ def spiceConsole(host, port, command):
log.error("SPICE client is not configured")
return
name = node.name()
host = node.consoleHost()
# ipv6 support
if ":" in host:
host = "[{}]".format(host)
@@ -48,6 +53,9 @@ def spiceConsole(host, port, command):
# replace the place-holders by the actual values
command = command.replace("%h", host)
command = command.replace("%p", str(port))
command = command.replace("%d", name.replace('"', '\\"'))
command = command.replace("%i", node.project().id())
command = command.replace("%n", str(node.id()))
try:
log.debug('starting SPICE program "{}"'.format(command))

View File

@@ -76,6 +76,7 @@ class Style:
self._mw.uiDrawRectangleAction.setIcon(self._getStyleIcon(":/icons/rectangle.svg", ":/icons/rectangle-hover.svg"))
self._mw.uiDrawEllipseAction.setIcon(self._getStyleIcon(":/icons/ellipse.svg", ":/icons/ellipse-hover.svg"))
self._mw.uiDrawLineAction.setIcon(QtGui.QIcon(":/icons/vertically.svg"))
self._mw.uiEditReadmeAction.setIcon(QtGui.QIcon(":/icons/edit.svg"))
self._mw.uiOnlineHelpAction.setIcon(QtGui.QIcon(":/icons/help.svg"))
self._mw.uiBrowseRoutersAction.setIcon(self._getStyleIcon(":/icons/router.png", ":/icons/router-hover.png"))
self._mw.uiBrowseSwitchesAction.setIcon(self._getStyleIcon(":/icons/switch.png", ":/icons/switch-hover.png"))
@@ -127,6 +128,7 @@ class Style:
self._mw.uiDrawRectangleAction.setIcon(self._getStyleIcon(":/classic_icons/rectangle.svg", ":/classic_icons/rectangle-hover.svg"))
self._mw.uiDrawEllipseAction.setIcon(self._getStyleIcon(":/classic_icons/ellipse.svg", ":/classic_icons/ellipse-hover.svg"))
self._mw.uiDrawLineAction.setIcon(self._getStyleIcon(":/classic_icons/line.svg", ":/classic_icons/line-hover.svg"))
self._mw.uiEditReadmeAction.setIcon(self._getStyleIcon(":/classic_icons/edit.svg", ":/classic_icons/edit-hover.svg"))
self._mw.uiOnlineHelpAction.setIcon(self._getStyleIcon(":/classic_icons/help.svg", ":/classic_icons/help-hover.svg"))
self._mw.uiBrowseRoutersAction.setIcon(self._getStyleIcon(":/classic_icons/router.svg", ":/classic_icons/router-hover.svg"))
self._mw.uiBrowseSwitchesAction.setIcon(self._getStyleIcon(":/classic_icons/switch.svg", ":/classic_icons/switch-hover.svg"))
@@ -188,6 +190,7 @@ class Style:
self._mw.uiDrawRectangleAction.setIcon(self._getStyleIcon(":/charcoal_icons/rectangle.svg", ":/charcoal_icons/rectangle-hover.svg"))
self._mw.uiDrawEllipseAction.setIcon(self._getStyleIcon(":/charcoal_icons/ellipse.svg", ":/charcoal_icons/ellipse-hover.svg"))
self._mw.uiDrawLineAction.setIcon(self._getStyleIcon(":/charcoal_icons/line.svg", ":/charcoal_icons/line-hover.svg"))
self._mw.uiEditReadmeAction.setIcon(self._getStyleIcon(":/charcoal_icons/edit.svg", ":/charcoal_icons/edit-hover.svg"))
self._mw.uiOnlineHelpAction.setIcon(self._getStyleIcon(":/charcoal_icons/help.svg", ":/charcoal_icons/help-hover.svg"))
self._mw.uiBrowseRoutersAction.setIcon(self._getStyleIcon(":/charcoal_icons/router.svg", ":/charcoal_icons/router-hover.svg"))
self._mw.uiBrowseSwitchesAction.setIcon(self._getStyleIcon(":/charcoal_icons/switch.svg", ":/charcoal_icons/switch-hover.svg"))

View File

@@ -29,6 +29,7 @@ from .qt import QtCore, QtWidgets
from .utils.progress_dialog import ProgressDialog
from .utils.import_project_worker import ImportProjectWorker
from .dialogs.project_export_wizard import ExportProjectWizard
from .dialogs.file_editor_dialog import FileEditorDialog
from .dialogs.project_welcome_dialog import ProjectWelcomeDialog
from .modules import MODULES
@@ -243,6 +244,13 @@ class Topology(QtCore.QObject):
self._main_window.uiStatusBar.showMessage("Project loaded {}".format(path), 2000)
return True
def editReadme(self):
if self.project() is None:
return
dialog = FileEditorDialog(self.project(), "README.txt", parent=self._main_window, default="Project title\n\nAuthor: Grace Hopper <grace@example.org>\n\nThis project is about...")
dialog.show()
dialog.exec_()
def _projectCreationErrorSlot(self, message):
if self._project:
self._project.project_creation_error_signal.disconnect(self._projectCreationErrorSlot)

View File

@@ -267,19 +267,16 @@ class TopologySummaryView(QtWidgets.QTreeWidget):
if item.link() == link:
view.centerOn(item)
def mousePressEvent(self, event):
def contextMenuEvent(self, event):
"""
Handles all mouse press events.
Handles all context menu events.
:param event: QMouseEvent instance
:param event: QContextMenuEvent instance
"""
if event.button() == QtCore.Qt.RightButton:
self._showContextualMenu()
else:
super().mousePressEvent(event)
self._showContextualMenu(event.globalPos())
def _showContextualMenu(self):
def _showContextualMenu(self, pos):
"""
Contextual menu to expand and collapse the tree.
"""
@@ -322,6 +319,11 @@ class TopologySummaryView(QtWidgets.QTreeWidget):
reset_all_filters.triggered.connect(self._resetAllFiltersSlot)
menu.addAction(reset_all_filters)
resume_suspended_links = QtWidgets.QAction("Resume all suspended links", menu)
resume_suspended_links.setIcon(get_icon("start.svg"))
resume_suspended_links.triggered.connect(self._resumeAllLinksSlot)
menu.addAction(resume_suspended_links)
current_item = self.currentItem()
from .main_window import MainWindow
view = MainWindow.instance().uiGraphicsView
@@ -336,7 +338,7 @@ class TopologySummaryView(QtWidgets.QTreeWidget):
item.populateLinkContextualMenu(menu)
break
menu.exec_(QtGui.QCursor.pos())
menu.exec_(pos)
@qslot
def _expandAllSlot(self, *args):
@@ -403,3 +405,13 @@ class TopologySummaryView(QtWidgets.QTreeWidget):
filters = {}
link.setFilters(filters)
link.update()
@qslot
def _resumeAllLinksSlot(self, *args):
"""
Resume all suspended links.
"""
for link in self._topology.links():
if link.suspended():
link.toggleSuspend()

View File

@@ -64,21 +64,21 @@
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="uiCompressionComboBox"/>
</item>
<item row="2" column="0" colspan="3">
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="uiIncludeImagesCheckBox">
<property name="text">
<string>Include base images</string>
<string>&amp;Include base images</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="uiIncludeSnapshotsCheckBox">
<property name="text">
<string>Include snapshots</string>
<string>&amp;Include snapshots</string>
</property>
</widget>
</item>
<item row="4" column="2">
<item row="6" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -91,6 +91,13 @@
</property>
</spacer>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="uiResetMacAddressesCheckBox">
<property name="text">
<string>&amp;Reset MAC addresses</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="uiProjectReadmeWizardPage">

View File

@@ -2,12 +2,14 @@
# 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.9
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ExportProjectWizard(object):
def setupUi(self, ExportProjectWizard):
ExportProjectWizard.setObjectName("ExportProjectWizard")
@@ -43,12 +45,15 @@ class Ui_ExportProjectWizard(object):
self.gridLayout.addWidget(self.uiCompressionComboBox, 1, 1, 1, 2)
self.uiIncludeImagesCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
self.uiIncludeImagesCheckBox.setObjectName("uiIncludeImagesCheckBox")
self.gridLayout.addWidget(self.uiIncludeImagesCheckBox, 2, 0, 1, 3)
self.gridLayout.addWidget(self.uiIncludeImagesCheckBox, 3, 0, 1, 3)
self.uiIncludeSnapshotsCheckBox = QtWidgets.QCheckBox(self.uiExportOptionsWizardPage)
self.uiIncludeSnapshotsCheckBox.setObjectName("uiIncludeSnapshotsCheckBox")
self.gridLayout.addWidget(self.uiIncludeSnapshotsCheckBox, 3, 0, 1, 2)
self.gridLayout.addWidget(self.uiIncludeSnapshotsCheckBox, 4, 0, 1, 2)
spacerItem = QtWidgets.QSpacerItem(20, 247, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 4, 2, 1, 1)
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)
ExportProjectWizard.addPage(self.uiExportOptionsWizardPage)
self.uiProjectReadmeWizardPage = QtWidgets.QWizardPage()
self.uiProjectReadmeWizardPage.setObjectName("uiProjectReadmeWizardPage")
@@ -70,8 +75,9 @@ class Ui_ExportProjectWizard(object):
self.uiPathLabel.setText(_translate("ExportProjectWizard", "Path:"))
self.uiPathBrowserToolButton.setText(_translate("ExportProjectWizard", "Browse..."))
self.uiCompressionLabel.setText(_translate("ExportProjectWizard", "Compression:"))
self.uiIncludeImagesCheckBox.setText(_translate("ExportProjectWizard", "Include base images"))
self.uiIncludeSnapshotsCheckBox.setText(_translate("ExportProjectWizard", "Include snapshots"))
self.uiIncludeImagesCheckBox.setText(_translate("ExportProjectWizard", "&Include base images"))
self.uiIncludeSnapshotsCheckBox.setText(_translate("ExportProjectWizard", "&Include snapshots"))
self.uiResetMacAddressesCheckBox.setText(_translate("ExportProjectWizard", "&Reset MAC addresses"))
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"
@@ -79,4 +85,3 @@ class Ui_ExportProjectWizard(object):
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Ubuntu\'; font-size:11pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'.SF NS Text\'; font-size:13pt;\"><br /></p></body></html>"))

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>931</width>
<height>878</height>
<width>941</width>
<height>910</height>
</rect>
</property>
<property name="windowTitle">
@@ -223,16 +223,7 @@
<string>Binary images</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>10</number>
</property>
<item>
@@ -382,16 +373,7 @@
<string>Console applications</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>10</number>
</property>
<item>
@@ -418,17 +400,7 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;%h = console IP or hostname&lt;/li&gt;
&lt;li&gt;%p = console port&lt;/li&gt;
&lt;li&gt;%P = VNC display&lt;/li&gt;
&lt;li&gt;%s = path of the serial connection&lt;/li&gt;
&lt;li&gt;%d = title of the console&lt;/li&gt;
&lt;li&gt;%i = project UUID&lt;/li&gt;
&lt;li&gt;%c = server URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%h = console IP or hostname&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%p = console port&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%d = title of the console&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%i = project UUID&lt;/li&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%n = node UUID&lt;/li&gt;&lt;/ul&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%c = server URL&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="readOnly">
<bool>true</bool>
@@ -502,16 +474,7 @@
<string>VNC</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>10</number>
</property>
<item>
@@ -538,17 +501,7 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;%h = console IP or hostname&lt;/li&gt;
&lt;li&gt;%p = console port&lt;/li&gt;
&lt;li&gt;%P = VNC display&lt;/li&gt;
&lt;li&gt;%s = path of the serial connection&lt;/li&gt;
&lt;li&gt;%d = title of the console&lt;/li&gt;
&lt;li&gt;%i = project UUID&lt;/li&gt;
&lt;li&gt;%c = server URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%h = console IP or hostname&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%p = console port&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%P = VNC display&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%d = title of the console&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%i = project UUID&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%n = node UUID&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="readOnly">
<bool>true</bool>
@@ -617,17 +570,7 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;%h = console IP or hostname&lt;/li&gt;
&lt;li&gt;%p = console port&lt;/li&gt;
&lt;li&gt;%P = VNC display&lt;/li&gt;
&lt;li&gt;%s = path of the serial connection&lt;/li&gt;
&lt;li&gt;%d = title of the console&lt;/li&gt;
&lt;li&gt;%i = project UUID&lt;/li&gt;
&lt;li&gt;%c = server URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Command line replacements:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%h = console IP or hostname&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%p = console port&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%d = title of the console&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%i = project UUID&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;%n = node UUID&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="readOnly">
<bool>true</bool>
@@ -1000,16 +943,7 @@
<string>Miscellaneous</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>10</number>
</property>
<item>

View File

@@ -2,16 +2,18 @@
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/general_preferences_page.ui'
#
# Created by: PyQt5 UI code generator 5.9
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GeneralPreferencesPageWidget(object):
def setupUi(self, GeneralPreferencesPageWidget):
GeneralPreferencesPageWidget.setObjectName("GeneralPreferencesPageWidget")
GeneralPreferencesPageWidget.resize(931, 878)
GeneralPreferencesPageWidget.resize(941, 910)
self.verticalLayout = QtWidgets.QVBoxLayout(GeneralPreferencesPageWidget)
self.verticalLayout.setObjectName("verticalLayout")
self.uiMiscTabWidget = QtWidgets.QTabWidget(GeneralPreferencesPageWidget)
@@ -140,6 +142,7 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiImageDirectoriesLabel.setObjectName("uiImageDirectoriesLabel")
self.verticalLayout_10.addWidget(self.uiImageDirectoriesLabel)
self.uiImageDirectoriesListWidget = QtWidgets.QListWidget(self.uiLocalBinaryImagePathsGroupBox)
self.uiImageDirectoriesListWidget.setFocusPolicy(QtCore.Qt.ClickFocus)
self.uiImageDirectoriesListWidget.setLineWidth(0)
self.uiImageDirectoriesListWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.uiImageDirectoriesListWidget.setAlternatingRowColors(False)
@@ -312,6 +315,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setHeightForWidth(self.uiDefaultNoteStylePlainTextEdit.sizePolicy().hasHeightForWidth())
self.uiDefaultNoteStylePlainTextEdit.setSizePolicy(sizePolicy)
self.uiDefaultNoteStylePlainTextEdit.setMaximumSize(QtCore.QSize(16777215, 50))
self.uiDefaultNoteStylePlainTextEdit.setFocusPolicy(QtCore.Qt.NoFocus)
self.uiDefaultNoteStylePlainTextEdit.setReadOnly(True)
self.uiDefaultNoteStylePlainTextEdit.setObjectName("uiDefaultNoteStylePlainTextEdit")
self.gridLayout_3.addWidget(self.uiDefaultNoteStylePlainTextEdit, 14, 0, 1, 3)
@@ -329,10 +333,6 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiLimitSizeNodeSymbolCheckBox = QtWidgets.QCheckBox(self.uiSceneTab)
self.uiLimitSizeNodeSymbolCheckBox.setObjectName("uiLimitSizeNodeSymbolCheckBox")
self.gridLayout_3.addWidget(self.uiLimitSizeNodeSymbolCheckBox, 9, 0, 1, 2)
self.uiDrawLinkStatusPointsCheckBox = QtWidgets.QCheckBox(self.uiSceneTab)
self.uiDrawLinkStatusPointsCheckBox.setChecked(True)
self.uiDrawLinkStatusPointsCheckBox.setObjectName("uiDrawLinkStatusPointsCheckBox")
self.gridLayout_3.addWidget(self.uiDrawLinkStatusPointsCheckBox, 5, 0, 1, 1)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.uiDefaultLabelFontPushButton = QtWidgets.QPushButton(self.uiSceneTab)
@@ -351,6 +351,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setHeightForWidth(self.uiDefaultLabelStylePlainTextEdit.sizePolicy().hasHeightForWidth())
self.uiDefaultLabelStylePlainTextEdit.setSizePolicy(sizePolicy)
self.uiDefaultLabelStylePlainTextEdit.setMaximumSize(QtCore.QSize(16777215, 50))
self.uiDefaultLabelStylePlainTextEdit.setFocusPolicy(QtCore.Qt.NoFocus)
self.uiDefaultLabelStylePlainTextEdit.setReadOnly(True)
self.uiDefaultLabelStylePlainTextEdit.setObjectName("uiDefaultLabelStylePlainTextEdit")
self.gridLayout_3.addWidget(self.uiDefaultLabelStylePlainTextEdit, 11, 0, 1, 3)
@@ -360,6 +361,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiSceneHeightSpinBox.sizePolicy().hasHeightForWidth())
self.uiSceneHeightSpinBox.setSizePolicy(sizePolicy)
self.uiSceneHeightSpinBox.setFocusPolicy(QtCore.Qt.StrongFocus)
self.uiSceneHeightSpinBox.setMinimum(500)
self.uiSceneHeightSpinBox.setMaximum(1000000)
self.uiSceneHeightSpinBox.setSingleStep(100)
@@ -372,6 +374,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiSceneWidthSpinBox.sizePolicy().hasHeightForWidth())
self.uiSceneWidthSpinBox.setSizePolicy(sizePolicy)
self.uiSceneWidthSpinBox.setFocusPolicy(QtCore.Qt.StrongFocus)
self.uiSceneWidthSpinBox.setMinimum(500)
self.uiSceneWidthSpinBox.setMaximum(1000000)
self.uiSceneWidthSpinBox.setSingleStep(100)
@@ -396,6 +399,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiDrawingGridSizeSpinBox.sizePolicy().hasHeightForWidth())
self.uiDrawingGridSizeSpinBox.setSizePolicy(sizePolicy)
self.uiDrawingGridSizeSpinBox.setFocusPolicy(QtCore.Qt.StrongFocus)
self.uiDrawingGridSizeSpinBox.setMinimum(5)
self.uiDrawingGridSizeSpinBox.setMaximum(100)
self.uiDrawingGridSizeSpinBox.setSingleStep(5)
@@ -408,6 +412,7 @@ class Ui_GeneralPreferencesPageWidget(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiNodeGridSizeSpinBox.sizePolicy().hasHeightForWidth())
self.uiNodeGridSizeSpinBox.setSizePolicy(sizePolicy)
self.uiNodeGridSizeSpinBox.setFocusPolicy(QtCore.Qt.StrongFocus)
self.uiNodeGridSizeSpinBox.setMinimum(5)
self.uiNodeGridSizeSpinBox.setMaximum(150)
self.uiNodeGridSizeSpinBox.setSingleStep(5)
@@ -423,6 +428,10 @@ class Ui_GeneralPreferencesPageWidget(object):
self.gridLayout_3.addWidget(self.uiRectangleSelectedItemCheckBox, 4, 0, 1, 3)
spacerItem9 = QtWidgets.QSpacerItem(20, 5, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_3.addItem(spacerItem9, 16, 0, 1, 1)
self.uiDrawLinkStatusPointsCheckBox = QtWidgets.QCheckBox(self.uiSceneTab)
self.uiDrawLinkStatusPointsCheckBox.setChecked(True)
self.uiDrawLinkStatusPointsCheckBox.setObjectName("uiDrawLinkStatusPointsCheckBox")
self.gridLayout_3.addWidget(self.uiDrawLinkStatusPointsCheckBox, 5, 0, 1, 2)
self.uiMiscTabWidget.addTab(self.uiSceneTab, "")
self.uiMiscTab = QtWidgets.QWidget()
self.uiMiscTab.setObjectName("uiMiscTab")
@@ -472,6 +481,53 @@ class Ui_GeneralPreferencesPageWidget(object):
self.retranslateUi(GeneralPreferencesPageWidget)
self.uiMiscTabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(GeneralPreferencesPageWidget)
GeneralPreferencesPageWidget.setTabOrder(self.uiProjectsPathLineEdit, self.uiProjectsPathToolButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiProjectsPathToolButton, self.uiSymbolsPathLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiSymbolsPathLineEdit, self.uiSymbolsPathToolButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiSymbolsPathToolButton, self.uiConfigsPathLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiConfigsPathLineEdit, self.uiConfigsPathToolButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiConfigsPathToolButton, self.uiAppliancesPathLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiAppliancesPathLineEdit, self.uiAppliancesPathToolButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiAppliancesPathToolButton, self.uiStyleComboBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiStyleComboBox, self.uiSymbolThemeComboBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiSymbolThemeComboBox, self.uiImportConfigurationFilePushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiImportConfigurationFilePushButton, self.uiExportConfigurationFilePushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiExportConfigurationFilePushButton, self.uiBrowseConfigurationPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiBrowseConfigurationPushButton, self.uiImagesPathLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiImagesPathLineEdit, self.uiImagesPathToolButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiImagesPathToolButton, self.uiImageDirectoriesAddPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiImageDirectoriesAddPushButton, self.uiImageDirectoriesDeletePushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiImageDirectoriesDeletePushButton, self.uiTelnetConsoleCommandLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiTelnetConsoleCommandLineEdit, self.uiTelnetConsolePreconfiguredCommandPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiTelnetConsolePreconfiguredCommandPushButton, self.uiDelayConsoleAllSpinBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiDelayConsoleAllSpinBox, self.uiVNCConsoleCommandLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiVNCConsoleCommandLineEdit, self.uiVNCConsolePreconfiguredCommandPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiVNCConsolePreconfiguredCommandPushButton, self.uiSPICEConsoleCommandLineEdit)
GeneralPreferencesPageWidget.setTabOrder(self.uiSPICEConsoleCommandLineEdit, self.uiSPICEConsolePreconfiguredCommandPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiSPICEConsolePreconfiguredCommandPushButton, self.uiSceneWidthSpinBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiSceneWidthSpinBox, self.uiSceneHeightSpinBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiSceneHeightSpinBox, self.uiNodeGridSizeSpinBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiNodeGridSizeSpinBox, self.uiDrawingGridSizeSpinBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiDrawingGridSizeSpinBox, self.uiRectangleSelectedItemCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiRectangleSelectedItemCheckBox, self.uiDrawLinkStatusPointsCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiDrawLinkStatusPointsCheckBox, self.uiShowInterfaceLabelsOnNewProject)
GeneralPreferencesPageWidget.setTabOrder(self.uiShowInterfaceLabelsOnNewProject, self.uiShowGridOnNewProject)
GeneralPreferencesPageWidget.setTabOrder(self.uiShowGridOnNewProject, self.uiSnapToGridOnNewProject)
GeneralPreferencesPageWidget.setTabOrder(self.uiSnapToGridOnNewProject, self.uiLimitSizeNodeSymbolCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiLimitSizeNodeSymbolCheckBox, self.uiDefaultLabelFontPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiDefaultLabelFontPushButton, self.uiDefaultLabelColorPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiDefaultLabelColorPushButton, self.uiDefaultNoteFontPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiDefaultNoteFontPushButton, self.uiDefaultNoteColorPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiDefaultNoteColorPushButton, self.uiCheckForUpdateCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiCheckForUpdateCheckBox, self.uiCrashReportCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiCrashReportCheckBox, self.uiStatsCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiStatsCheckBox, self.uiOverlayNotificationsCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiOverlayNotificationsCheckBox, self.uiExperimentalFeaturesCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiExperimentalFeaturesCheckBox, self.uiHdpiCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiHdpiCheckBox, self.uiMultiProfilesCheckBox)
GeneralPreferencesPageWidget.setTabOrder(self.uiMultiProfilesCheckBox, self.uiDirectFileUpload)
GeneralPreferencesPageWidget.setTabOrder(self.uiDirectFileUpload, self.uiRestoreDefaultsPushButton)
GeneralPreferencesPageWidget.setTabOrder(self.uiRestoreDefaultsPushButton, self.uiMiscTabWidget)
def retranslateUi(self, GeneralPreferencesPageWidget):
_translate = QtCore.QCoreApplication.translate
@@ -506,17 +562,7 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiImagesTab), _translate("GeneralPreferencesPageWidget", "Binary images"))
self.uiTelnetConsoleSettingsGroupBox.setTitle(_translate("GeneralPreferencesPageWidget", "Console settings"))
self.uiTelnetConsoleCommandLabel.setText(_translate("GeneralPreferencesPageWidget", "Console application command for Telnet:"))
self.uiTelnetConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p>\n"
"<ul>\n"
"<li>%h = console IP or hostname</li>\n"
"<li>%p = console port</li>\n"
"<li>%P = VNC display</li>\n"
"<li>%s = path of the serial connection</li>\n"
"<li>%d = title of the console</li>\n"
"<li>%i = project UUID</li>\n"
"<li>%c = server URL</li>\n"
"</ul>\n"
"</body></html>"))
self.uiTelnetConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p><ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li style=\" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%h = console IP or hostname</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%p = console port</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%d = title of the console</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%i = project UUID</li><ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%n = node UUID</li></ul><li style=\" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%c = server URL</li></ul></body></html>"))
self.uiTelnetConsolePreconfiguredCommandPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Edit"))
self.uiConsoleMiscGroupBox.setTitle(_translate("GeneralPreferencesPageWidget", "Miscellaneous"))
self.uiDelayConsoleAllSpinBox.setSuffix(_translate("GeneralPreferencesPageWidget", " ms"))
@@ -524,32 +570,12 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiConsoleTab), _translate("GeneralPreferencesPageWidget", "Console applications"))
self.uiVNCConsoleSettingsGroupBox.setTitle(_translate("GeneralPreferencesPageWidget", "Settings for VNC connections"))
self.uiVNCConsoleCommandLabel.setText(_translate("GeneralPreferencesPageWidget", "Console application command for VNC:"))
self.uiVNCConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p>\n"
"<ul>\n"
"<li>%h = console IP or hostname</li>\n"
"<li>%p = console port</li>\n"
"<li>%P = VNC display</li>\n"
"<li>%s = path of the serial connection</li>\n"
"<li>%d = title of the console</li>\n"
"<li>%i = project UUID</li>\n"
"<li>%c = server URL</li>\n"
"</ul>\n"
"</body></html>"))
self.uiVNCConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p><ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li style=\" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%h = console IP or hostname</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%p = console port</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%P = VNC display</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%d = title of the console</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%i = project UUID</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%n = node UUID</li></ul></body></html>"))
self.uiVNCConsolePreconfiguredCommandPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Edit"))
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiVNCTab), _translate("GeneralPreferencesPageWidget", "VNC"))
self.uiSPICEConsoleSettingsGroupBox.setTitle(_translate("GeneralPreferencesPageWidget", "Settings for SPICE connections"))
self.uiSPICEConsoleCommandLabel.setText(_translate("GeneralPreferencesPageWidget", "Console application command for SPICE:"))
self.uiSPICEConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p>\n"
"<ul>\n"
"<li>%h = console IP or hostname</li>\n"
"<li>%p = console port</li>\n"
"<li>%P = VNC display</li>\n"
"<li>%s = path of the serial connection</li>\n"
"<li>%d = title of the console</li>\n"
"<li>%i = project UUID</li>\n"
"<li>%c = server URL</li>\n"
"</ul>\n"
"</body></html>"))
self.uiSPICEConsoleCommandLineEdit.setToolTip(_translate("GeneralPreferencesPageWidget", "<html><head/><body><p>Command line replacements:</p><ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li style=\" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%h = console IP or hostname</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%p = console port</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%d = title of the console</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%i = project UUID</li><li style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%n = node UUID</li></ul><p><br/></p></body></html>"))
self.uiSPICEConsolePreconfiguredCommandPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Edit"))
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiSPICETab), _translate("GeneralPreferencesPageWidget", "SPICE"))
self.uiSceneWidthLabel.setText(_translate("GeneralPreferencesPageWidget", "Default width:"))
@@ -560,7 +586,6 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiDefaultNoteFontPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Select default font"))
self.uiDefaultNoteColorPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Select default color"))
self.uiLimitSizeNodeSymbolCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Limit the size of node symbols"))
self.uiDrawLinkStatusPointsCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Draw link status points"))
self.uiDefaultLabelFontPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Select default font"))
self.uiDefaultLabelColorPushButton.setText(_translate("GeneralPreferencesPageWidget", "&Select default color"))
self.uiDefaultLabelStylePlainTextEdit.setPlainText(_translate("GeneralPreferencesPageWidget", "AaBbYyZz"))
@@ -572,6 +597,7 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiNodeGridSizeLabel.setText(_translate("GeneralPreferencesPageWidget", "Default node grid size:"))
self.uiShowGridOnNewProject.setText(_translate("GeneralPreferencesPageWidget", "Show grid on new project"))
self.uiRectangleSelectedItemCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Draw a rectangle when an item is selected"))
self.uiDrawLinkStatusPointsCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Draw link status points"))
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiSceneTab), _translate("GeneralPreferencesPageWidget", "Topology view"))
self.uiCheckForUpdateCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Automatically check for update"))
self.uiCrashReportCheckBox.setText(_translate("GeneralPreferencesPageWidget", "Send anonymous crash reports"))
@@ -584,4 +610,3 @@ class Ui_GeneralPreferencesPageWidget(object):
self.uiDirectFileUpload.setText(_translate("GeneralPreferencesPageWidget", "Upload files directly to computes (experimental)"))
self.uiMiscTabWidget.setTabText(self.uiMiscTabWidget.indexOf(self.uiMiscTab), _translate("GeneralPreferencesPageWidget", "Miscellaneous"))
self.uiRestoreDefaultsPushButton.setText(_translate("GeneralPreferencesPageWidget", "Restore defaults"))

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>494</width>
<height>585</height>
<width>467</width>
<height>657</height>
</rect>
</property>
<property name="sizePolicy">
@@ -191,6 +191,26 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uiPortLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="uiPortSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65635</number>
</property>
<property name="value">
<number>80</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -2,16 +2,18 @@
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/gns3_vm_preferences_page.ui'
#
# Created by: PyQt5 UI code generator 5.9
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GNS3VMPreferencesPageWidget(object):
def setupUi(self, GNS3VMPreferencesPageWidget):
GNS3VMPreferencesPageWidget.setObjectName("GNS3VMPreferencesPageWidget")
GNS3VMPreferencesPageWidget.resize(494, 585)
GNS3VMPreferencesPageWidget.resize(467, 657)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -102,12 +104,30 @@ class Ui_GNS3VMPreferencesPageWidget(object):
self.uiCpuLabel = QtWidgets.QLabel(self.uiGNS3VMSettingsGroupBox)
self.uiCpuLabel.setObjectName("uiCpuLabel")
self.gridLayout.addWidget(self.uiCpuLabel, 5, 0, 1, 1)
self.uiPortLabel = QtWidgets.QLabel(self.uiGNS3VMSettingsGroupBox)
self.uiPortLabel.setObjectName("uiPortLabel")
self.gridLayout.addWidget(self.uiPortLabel, 2, 0, 1, 1)
self.uiPortSpinBox = QtWidgets.QSpinBox(self.uiGNS3VMSettingsGroupBox)
self.uiPortSpinBox.setMinimum(1)
self.uiPortSpinBox.setMaximum(65635)
self.uiPortSpinBox.setProperty("value", 80)
self.uiPortSpinBox.setObjectName("uiPortSpinBox")
self.gridLayout.addWidget(self.uiPortSpinBox, 2, 1, 1, 1)
self.verticalLayout.addWidget(self.uiGNS3VMSettingsGroupBox)
spacerItem = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.retranslateUi(GNS3VMPreferencesPageWidget)
QtCore.QMetaObject.connectSlotsByName(GNS3VMPreferencesPageWidget)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiEnableVMCheckBox, self.uiGNS3VMEngineComboBox)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiGNS3VMEngineComboBox, self.uiVMListComboBox)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiVMListComboBox, self.uiRefreshPushButton)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiRefreshPushButton, self.uiHeadlessCheckBox)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiHeadlessCheckBox, self.uiRamSpinBox)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiRamSpinBox, self.uiCpuSpinBox)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiCpuSpinBox, self.uiWhenExitKeepRadioButton)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiWhenExitKeepRadioButton, self.uiWhenExitSuspendRadioButton)
GNS3VMPreferencesPageWidget.setTabOrder(self.uiWhenExitSuspendRadioButton, self.uiWhenExitStopRadioButton)
def retranslateUi(self, GNS3VMPreferencesPageWidget):
_translate = QtCore.QCoreApplication.translate
@@ -126,4 +146,4 @@ class Ui_GNS3VMPreferencesPageWidget(object):
self.uiRamLabel.setText(_translate("GNS3VMPreferencesPageWidget", "RAM:"))
self.uiRamSpinBox.setSuffix(_translate("GNS3VMPreferencesPageWidget", " MB"))
self.uiCpuLabel.setText(_translate("GNS3VMPreferencesPageWidget", "vCPUs:"))
self.uiPortLabel.setText(_translate("GNS3VMPreferencesPageWidget", "Port:"))

View File

@@ -62,7 +62,7 @@ background-none;
<x>0</x>
<y>0</y>
<width>986</width>
<height>40</height>
<height>42</height>
</rect>
</property>
<widget class="QMenu" name="uiEditMenu">
@@ -151,6 +151,7 @@ background-none;
<addaction name="uiDrawRectangleAction"/>
<addaction name="uiDrawEllipseAction"/>
<addaction name="uiDrawLineAction"/>
<addaction name="uiEditReadmeAction"/>
</widget>
<widget class="QMenu" name="uiDeviceMenu">
<property name="title">
@@ -163,7 +164,6 @@ background-none;
</property>
<addaction name="uiScreenshotAction"/>
<addaction name="uiImportExportConfigsAction"/>
<addaction name="uiWebInterfaceAction"/>
<addaction name="uiWebUIAction"/>
</widget>
<addaction name="uiFileMenu"/>
@@ -1156,6 +1156,15 @@ background-none;
<string>Import portable project</string>
</property>
</action>
<action name="uiEditReadmeAction">
<property name="icon">
<iconset resource="../../resources/resources.qrc">
<normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
</property>
<property name="text">
<string>Edit readme</string>
</property>
</action>
<action name="uiAcademyAction">
<property name="text">
<string>GNS3 &amp;Academy</string>
@@ -1187,11 +1196,6 @@ background-none;
<string>Edit project</string>
</property>
</action>
<action name="uiWebInterfaceAction">
<property name="text">
<string>Light Web interface</string>
</property>
</action>
<action name="uiDrawLineAction">
<property name="checkable">
<bool>true</bool>
@@ -1227,7 +1231,7 @@ background-none;
</action>
<action name="uiWebUIAction">
<property name="text">
<string>WebUI - topology preview</string>
<string>Web UI - beta</string>
</property>
</action>
<action name="uiNewTemplateAction">

View File

@@ -2,12 +2,14 @@
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/main_window.ui'
#
# Created by: PyQt5 UI code generator 5.9
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
@@ -46,7 +48,7 @@ class Ui_MainWindow(object):
self.gridlayout.addWidget(self.uiGraphicsView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.uiCentralWidget)
self.uiMenuBar = QtWidgets.QMenuBar(MainWindow)
self.uiMenuBar.setGeometry(QtCore.QRect(0, 0, 986, 40))
self.uiMenuBar.setGeometry(QtCore.QRect(0, 0, 986, 42))
self.uiMenuBar.setObjectName("uiMenuBar")
self.uiEditMenu = QtWidgets.QMenu(self.uiMenuBar)
self.uiEditMenu.setObjectName("uiEditMenu")
@@ -214,22 +216,22 @@ class Ui_MainWindow(object):
self.uiOnlineHelpAction.setObjectName("uiOnlineHelpAction")
self.uiScreenshotAction = QtWidgets.QAction(MainWindow)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/icons/camera-photo-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon4.addPixmap(QtGui.QPixmap(":/icons/camera-photo.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon4.addPixmap(QtGui.QPixmap(":/icons/camera-photo-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiScreenshotAction.setIcon(icon4)
self.uiScreenshotAction.setObjectName("uiScreenshotAction")
self.uiStartAllAction = QtWidgets.QAction(MainWindow)
self.uiStartAllAction.setEnabled(True)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/icons/start-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon5.addPixmap(QtGui.QPixmap(":/icons/start.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon5.addPixmap(QtGui.QPixmap(":/icons/start-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiStartAllAction.setIcon(icon5)
self.uiStartAllAction.setObjectName("uiStartAllAction")
self.uiStopAllAction = QtWidgets.QAction(MainWindow)
self.uiStopAllAction.setEnabled(True)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/icons/stop-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon6.addPixmap(QtGui.QPixmap(":/icons/stop.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon6.addPixmap(QtGui.QPixmap(":/icons/stop-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiStopAllAction.setIcon(icon6)
self.uiStopAllAction.setObjectName("uiStopAllAction")
self.uiConsoleAllAction = QtWidgets.QAction(MainWindow)
@@ -243,14 +245,14 @@ class Ui_MainWindow(object):
self.uiAboutQtAction.setObjectName("uiAboutQtAction")
self.uiZoomInAction = QtWidgets.QAction(MainWindow)
icon8 = QtGui.QIcon()
icon8.addPixmap(QtGui.QPixmap(":/icons/zoom-in-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon8.addPixmap(QtGui.QPixmap(":/icons/zoom-in.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon8.addPixmap(QtGui.QPixmap(":/icons/zoom-in-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiZoomInAction.setIcon(icon8)
self.uiZoomInAction.setObjectName("uiZoomInAction")
self.uiZoomOutAction = QtWidgets.QAction(MainWindow)
icon9 = QtGui.QIcon()
icon9.addPixmap(QtGui.QPixmap(":/icons/zoom-out-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon9.addPixmap(QtGui.QPixmap(":/icons/zoom-out.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon9.addPixmap(QtGui.QPixmap(":/icons/zoom-out-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiZoomOutAction.setIcon(icon9)
self.uiZoomOutAction.setObjectName("uiZoomOutAction")
self.uiZoomResetAction = QtWidgets.QAction(MainWindow)
@@ -267,8 +269,8 @@ class Ui_MainWindow(object):
self.uiPreferencesAction.setObjectName("uiPreferencesAction")
self.uiSuspendAllAction = QtWidgets.QAction(MainWindow)
icon11 = QtGui.QIcon()
icon11.addPixmap(QtGui.QPixmap(":/icons/pause-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon11.addPixmap(QtGui.QPixmap(":/icons/pause.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon11.addPixmap(QtGui.QPixmap(":/icons/pause-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiSuspendAllAction.setIcon(icon11)
self.uiSuspendAllAction.setObjectName("uiSuspendAllAction")
self.uiAddNoteAction = QtWidgets.QAction(MainWindow)
@@ -296,15 +298,15 @@ class Ui_MainWindow(object):
self.uiDrawRectangleAction = QtWidgets.QAction(MainWindow)
self.uiDrawRectangleAction.setCheckable(True)
icon16 = QtGui.QIcon()
icon16.addPixmap(QtGui.QPixmap(":/icons/rectangle-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon16.addPixmap(QtGui.QPixmap(":/icons/rectangle.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon16.addPixmap(QtGui.QPixmap(":/icons/rectangle-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiDrawRectangleAction.setIcon(icon16)
self.uiDrawRectangleAction.setObjectName("uiDrawRectangleAction")
self.uiDrawEllipseAction = QtWidgets.QAction(MainWindow)
self.uiDrawEllipseAction.setCheckable(True)
icon17 = QtGui.QIcon()
icon17.addPixmap(QtGui.QPixmap(":/icons/ellipse-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon17.addPixmap(QtGui.QPixmap(":/icons/ellipse.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon17.addPixmap(QtGui.QPixmap(":/icons/ellipse-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiDrawEllipseAction.setIcon(icon17)
self.uiDrawEllipseAction.setObjectName("uiDrawEllipseAction")
self.uiShowPortNamesAction = QtWidgets.QAction(MainWindow)
@@ -346,40 +348,40 @@ class Ui_MainWindow(object):
self.uiCheckForUpdateAction.setObjectName("uiCheckForUpdateAction")
self.uiBrowseRoutersAction = QtWidgets.QAction(MainWindow)
icon23 = QtGui.QIcon()
icon23.addPixmap(QtGui.QPixmap(":/icons/router-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon23.addPixmap(QtGui.QPixmap(":/icons/router.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon23.addPixmap(QtGui.QPixmap(":/icons/router-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiBrowseRoutersAction.setIcon(icon23)
self.uiBrowseRoutersAction.setObjectName("uiBrowseRoutersAction")
self.uiBrowseSwitchesAction = QtWidgets.QAction(MainWindow)
icon24 = QtGui.QIcon()
icon24.addPixmap(QtGui.QPixmap(":/icons/switch-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon24.addPixmap(QtGui.QPixmap(":/icons/switch.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon24.addPixmap(QtGui.QPixmap(":/icons/switch-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiBrowseSwitchesAction.setIcon(icon24)
self.uiBrowseSwitchesAction.setObjectName("uiBrowseSwitchesAction")
self.uiBrowseEndDevicesAction = QtWidgets.QAction(MainWindow)
icon25 = QtGui.QIcon()
icon25.addPixmap(QtGui.QPixmap(":/icons/PC-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon25.addPixmap(QtGui.QPixmap(":/icons/PC.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon25.addPixmap(QtGui.QPixmap(":/icons/PC-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiBrowseEndDevicesAction.setIcon(icon25)
self.uiBrowseEndDevicesAction.setObjectName("uiBrowseEndDevicesAction")
self.uiBrowseSecurityDevicesAction = QtWidgets.QAction(MainWindow)
icon26 = QtGui.QIcon()
icon26.addPixmap(QtGui.QPixmap(":/icons/firewall-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon26.addPixmap(QtGui.QPixmap(":/icons/firewall.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon26.addPixmap(QtGui.QPixmap(":/icons/firewall-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiBrowseSecurityDevicesAction.setIcon(icon26)
self.uiBrowseSecurityDevicesAction.setObjectName("uiBrowseSecurityDevicesAction")
self.uiBrowseAllDevicesAction = QtWidgets.QAction(MainWindow)
icon27 = QtGui.QIcon()
icon27.addPixmap(QtGui.QPixmap(":/icons/browse-all-icons-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon27.addPixmap(QtGui.QPixmap(":/icons/browse-all-icons.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon27.addPixmap(QtGui.QPixmap(":/icons/browse-all-icons-hover.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
self.uiBrowseAllDevicesAction.setIcon(icon27)
self.uiBrowseAllDevicesAction.setObjectName("uiBrowseAllDevicesAction")
self.uiAddLinkAction = QtWidgets.QAction(MainWindow)
self.uiAddLinkAction.setCheckable(True)
icon28 = QtGui.QIcon()
icon28.addPixmap(QtGui.QPixmap(":/icons/connection-new-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon28.addPixmap(QtGui.QPixmap(":/icons/connection-new.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon28.addPixmap(QtGui.QPixmap(":/icons/cancel-connection.svg"), QtGui.QIcon.Normal, QtGui.QIcon.On)
icon28.addPixmap(QtGui.QPixmap(":/icons/connection-new-hover.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon28.addPixmap(QtGui.QPixmap(":/icons/cancel-connection.svg"), QtGui.QIcon.Active, QtGui.QIcon.On)
self.uiAddLinkAction.setIcon(icon28)
self.uiAddLinkAction.setObjectName("uiAddLinkAction")
@@ -407,23 +409,24 @@ class Ui_MainWindow(object):
icon30.addPixmap(QtGui.QPixmap(":/icons/import.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiImportProjectAction.setIcon(icon30)
self.uiImportProjectAction.setObjectName("uiImportProjectAction")
self.uiEditReadmeAction = QtWidgets.QAction(MainWindow)
icon31 = QtGui.QIcon()
icon31.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiEditReadmeAction.setIcon(icon31)
self.uiEditReadmeAction.setObjectName("uiEditReadmeAction")
self.uiAcademyAction = QtWidgets.QAction(MainWindow)
self.uiAcademyAction.setObjectName("uiAcademyAction")
self.uiDeleteProjectAction = QtWidgets.QAction(MainWindow)
icon31 = QtGui.QIcon()
icon31.addPixmap(QtGui.QPixmap(":/icons/delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiDeleteProjectAction.setIcon(icon31)
icon32 = QtGui.QIcon()
icon32.addPixmap(QtGui.QPixmap(":/icons/delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiDeleteProjectAction.setIcon(icon32)
self.uiDeleteProjectAction.setObjectName("uiDeleteProjectAction")
self.uiShowGridAction = QtWidgets.QAction(MainWindow)
self.uiShowGridAction.setCheckable(True)
self.uiShowGridAction.setObjectName("uiShowGridAction")
self.uiEditProjectAction = QtWidgets.QAction(MainWindow)
icon32 = QtGui.QIcon()
icon32.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiEditProjectAction.setIcon(icon32)
self.uiEditProjectAction.setIcon(icon31)
self.uiEditProjectAction.setObjectName("uiEditProjectAction")
self.uiWebInterfaceAction = QtWidgets.QAction(MainWindow)
self.uiWebInterfaceAction.setObjectName("uiWebInterfaceAction")
self.uiDrawLineAction = QtWidgets.QAction(MainWindow)
self.uiDrawLineAction.setCheckable(True)
icon33 = QtGui.QIcon()
@@ -434,9 +437,9 @@ class Ui_MainWindow(object):
self.uiLockAllAction.setCheckable(True)
self.uiLockAllAction.setChecked(False)
icon34 = QtGui.QIcon()
icon34.addPixmap(QtGui.QPixmap(":/icons/unlock.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon34.addPixmap(QtGui.QPixmap(":/icons/unlock.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon34.addPixmap(QtGui.QPixmap(":/icons/lock.svg"), QtGui.QIcon.Normal, QtGui.QIcon.On)
icon34.addPixmap(QtGui.QPixmap(":/icons/unlock.svg"), QtGui.QIcon.Active, QtGui.QIcon.Off)
icon34.addPixmap(QtGui.QPixmap(":/icons/lock.svg"), QtGui.QIcon.Active, QtGui.QIcon.On)
self.uiLockAllAction.setIcon(icon34)
self.uiLockAllAction.setObjectName("uiLockAllAction")
@@ -497,9 +500,9 @@ class Ui_MainWindow(object):
self.uiAnnotateMenu.addAction(self.uiDrawRectangleAction)
self.uiAnnotateMenu.addAction(self.uiDrawEllipseAction)
self.uiAnnotateMenu.addAction(self.uiDrawLineAction)
self.uiAnnotateMenu.addAction(self.uiEditReadmeAction)
self.uiToolsMenu.addAction(self.uiScreenshotAction)
self.uiToolsMenu.addAction(self.uiImportExportConfigsAction)
self.uiToolsMenu.addAction(self.uiWebInterfaceAction)
self.uiToolsMenu.addAction(self.uiWebUIAction)
self.uiMenuBar.addAction(self.uiFileMenu.menuAction())
self.uiMenuBar.addAction(self.uiEditMenu.menuAction())
@@ -698,17 +701,16 @@ class Ui_MainWindow(object):
self.uiDoctorAction.setText(_translate("MainWindow", "GNS3 &Doctor"))
self.uiExportProjectAction.setText(_translate("MainWindow", "Export portable project"))
self.uiImportProjectAction.setText(_translate("MainWindow", "Import portable project"))
self.uiEditReadmeAction.setText(_translate("MainWindow", "Edit readme"))
self.uiAcademyAction.setText(_translate("MainWindow", "GNS3 &Academy"))
self.uiDeleteProjectAction.setText(_translate("MainWindow", "Delete project"))
self.uiShowGridAction.setText(_translate("MainWindow", "Show the grid"))
self.uiEditProjectAction.setText(_translate("MainWindow", "Edit project"))
self.uiWebInterfaceAction.setText(_translate("MainWindow", "Light Web interface"))
self.uiDrawLineAction.setText(_translate("MainWindow", "Drawn line"))
self.uiLockAllAction.setText(_translate("MainWindow", "Lock or unlock all items"))
self.uiLockAllAction.setToolTip(_translate("MainWindow", "Lock or unlock all items"))
self.uiWebUIAction.setText(_translate("MainWindow", "WebUI - topology preview"))
self.uiWebUIAction.setText(_translate("MainWindow", "Web UI - beta"))
self.uiNewTemplateAction.setText(_translate("MainWindow", "New template"))
from ..compute_summary_view import ComputeSummaryView
from ..console_view import ConsoleView
from ..graphics_view import GraphicsView

View File

@@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>678</width>
<width>823</width>
<height>367</height>
</rect>
</property>
@@ -204,6 +204,16 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="uiResetMacAddressesCheckBox">
<property name="text">
<string>&amp;Reset MAC addresses</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

View File

@@ -1,20 +1,20 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/ui/project_dialog.ui'
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/project_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.6
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ProjectDialog(object):
def setupUi(self, ProjectDialog):
ProjectDialog.setObjectName("ProjectDialog")
ProjectDialog.setWindowModality(QtCore.Qt.ApplicationModal)
ProjectDialog.resize(520, 301)
ProjectDialog.resize(823, 367)
ProjectDialog.setModal(True)
self.verticalLayout = QtWidgets.QVBoxLayout(ProjectDialog)
self.verticalLayout.setObjectName("verticalLayout")
@@ -99,6 +99,10 @@ class Ui_ProjectDialog(object):
self.uiDuplicateProjectPushButton = QtWidgets.QPushButton(self.uiProjectsLibraryTab)
self.uiDuplicateProjectPushButton.setObjectName("uiDuplicateProjectPushButton")
self.horizontalLayout_4.addWidget(self.uiDuplicateProjectPushButton)
self.uiResetMacAddressesCheckBox = QtWidgets.QCheckBox(self.uiProjectsLibraryTab)
self.uiResetMacAddressesCheckBox.setChecked(True)
self.uiResetMacAddressesCheckBox.setObjectName("uiResetMacAddressesCheckBox")
self.horizontalLayout_4.addWidget(self.uiResetMacAddressesCheckBox)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_4.addItem(spacerItem2)
self.uiRefreshProjectsPushButton = QtWidgets.QPushButton(self.uiProjectsLibraryTab)
@@ -116,7 +120,7 @@ class Ui_ProjectDialog(object):
self.horizontalLayout.addItem(spacerItem3)
self.uiButtonBox = QtWidgets.QDialogButtonBox(ProjectDialog)
self.uiButtonBox.setOrientation(QtCore.Qt.Horizontal)
self.uiButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
self.uiButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.uiButtonBox.setObjectName("uiButtonBox")
self.horizontalLayout.addWidget(self.uiButtonBox)
self.verticalLayout.addLayout(self.horizontalLayout)
@@ -128,6 +132,16 @@ class Ui_ProjectDialog(object):
self.uiNameLineEdit.returnPressed.connect(ProjectDialog.accept)
self.uiLocationLineEdit.returnPressed.connect(ProjectDialog.accept)
QtCore.QMetaObject.connectSlotsByName(ProjectDialog)
ProjectDialog.setTabOrder(self.uiProjectTabWidget, self.uiNameLineEdit)
ProjectDialog.setTabOrder(self.uiNameLineEdit, self.uiLocationLineEdit)
ProjectDialog.setTabOrder(self.uiLocationLineEdit, self.uiLocationBrowserToolButton)
ProjectDialog.setTabOrder(self.uiLocationBrowserToolButton, self.uiOpenProjectPushButton)
ProjectDialog.setTabOrder(self.uiOpenProjectPushButton, self.uiRecentProjectsPushButton)
ProjectDialog.setTabOrder(self.uiRecentProjectsPushButton, self.uiSettingsPushButton)
ProjectDialog.setTabOrder(self.uiSettingsPushButton, self.uiProjectsTreeWidget)
ProjectDialog.setTabOrder(self.uiProjectsTreeWidget, self.uiDeleteProjectButton)
ProjectDialog.setTabOrder(self.uiDeleteProjectButton, self.uiDuplicateProjectPushButton)
ProjectDialog.setTabOrder(self.uiDuplicateProjectPushButton, self.uiRefreshProjectsPushButton)
def retranslateUi(self, ProjectDialog):
_translate = QtCore.QCoreApplication.translate
@@ -146,6 +160,7 @@ class Ui_ProjectDialog(object):
self.uiProjectsTreeWidget.headerItem().setText(2, _translate("ProjectDialog", "Path"))
self.uiDeleteProjectButton.setText(_translate("ProjectDialog", "Delete"))
self.uiDuplicateProjectPushButton.setText(_translate("ProjectDialog", "Duplicate"))
self.uiResetMacAddressesCheckBox.setText(_translate("ProjectDialog", "&Reset MAC addresses"))
self.uiRefreshProjectsPushButton.setText(_translate("ProjectDialog", "Refresh list"))
self.uiProjectTabWidget.setTabText(self.uiProjectTabWidget.indexOf(self.uiProjectsLibraryTab), _translate("ProjectDialog", "Projects library"))
self.uiSettingsPushButton.setText(_translate("ProjectDialog", "Settings"))

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1081</width>
<height>534</height>
<width>1104</width>
<height>665</height>
</rect>
</property>
<property name="windowTitle">
@@ -234,33 +234,6 @@
<string>In order to run the GNS3 VM you must first have VMware or VirtualBox installed and the GNS3 VM.ova imported with one of these software.</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="uiVirtualizationSoftwarLabel">
<property name="text">
<string>Virtualization software:</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="4">
<widget class="QPushButton" name="uiVMwareBannerButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../resources/resources.qrc">
<normaloff>:/images/vmware_fusion_banner.png</normaloff>:/images/vmware_fusion_banner.png</iconset>
</property>
<property name="iconSize">
<size>
<width>300</width>
<height>150</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="uiVmwareRadioButton">
<property name="toolTip">
@@ -274,18 +247,12 @@
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="0" column="0">
<widget class="QLabel" name="uiVirtualizationSoftwarLabel">
<property name="text">
<string>Virtualization software:</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>317</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="uiVirtualBoxRadioButton">
@@ -328,7 +295,7 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<item row="6" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="uiVMListComboBox">
@@ -349,7 +316,7 @@
</item>
</layout>
</item>
<item row="8" column="0" colspan="3">
<item row="8" column="0" colspan="2">
<widget class="QSpinBox" name="uiCPUSpinBox">
<property name="minimum">
<number>1</number>
@@ -362,7 +329,7 @@
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<item row="10" column="0" colspan="2">
<widget class="QSpinBox" name="uiRAMSpinBox">
<property name="enabled">
<bool>true</bool>

View File

@@ -2,9 +2,10 @@
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/setup_wizard.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
# Created by: PyQt5 UI code generator 5.15.0
#
# 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
@@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_SetupWizard(object):
def setupUi(self, SetupWizard):
SetupWizard.setObjectName("SetupWizard")
SetupWizard.resize(1081, 534)
SetupWizard.resize(1104, 665)
SetupWizard.setModal(True)
SetupWizard.setWizardStyle(QtWidgets.QWizard.ModernStyle)
SetupWizard.setOptions(QtWidgets.QWizard.NoBackButtonOnStartPage)
@@ -114,24 +115,13 @@ class Ui_SetupWizard(object):
self.uiVMWizardPage.setObjectName("uiVMWizardPage")
self.gridLayout_3 = QtWidgets.QGridLayout(self.uiVMWizardPage)
self.gridLayout_3.setObjectName("gridLayout_3")
self.uiVirtualizationSoftwarLabel = QtWidgets.QLabel(self.uiVMWizardPage)
self.uiVirtualizationSoftwarLabel.setObjectName("uiVirtualizationSoftwarLabel")
self.gridLayout_3.addWidget(self.uiVirtualizationSoftwarLabel, 0, 0, 1, 1)
self.uiVMwareBannerButton = QtWidgets.QPushButton(self.uiVMWizardPage)
self.uiVMwareBannerButton.setText("")
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/images/vmware_fusion_banner.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.uiVMwareBannerButton.setIcon(icon)
self.uiVMwareBannerButton.setIconSize(QtCore.QSize(300, 150))
self.uiVMwareBannerButton.setFlat(True)
self.uiVMwareBannerButton.setObjectName("uiVMwareBannerButton")
self.gridLayout_3.addWidget(self.uiVMwareBannerButton, 0, 2, 4, 1)
self.uiVmwareRadioButton = QtWidgets.QRadioButton(self.uiVMWizardPage)
self.uiVmwareRadioButton.setChecked(True)
self.uiVmwareRadioButton.setObjectName("uiVmwareRadioButton")
self.gridLayout_3.addWidget(self.uiVmwareRadioButton, 1, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(317, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem1, 1, 1, 1, 1)
self.uiVirtualizationSoftwarLabel = QtWidgets.QLabel(self.uiVMWizardPage)
self.uiVirtualizationSoftwarLabel.setObjectName("uiVirtualizationSoftwarLabel")
self.gridLayout_3.addWidget(self.uiVirtualizationSoftwarLabel, 0, 0, 1, 1)
self.uiVirtualBoxRadioButton = QtWidgets.QRadioButton(self.uiVMWizardPage)
self.uiVirtualBoxRadioButton.setObjectName("uiVirtualBoxRadioButton")
self.gridLayout_3.addWidget(self.uiVirtualBoxRadioButton, 2, 0, 1, 1)
@@ -161,13 +151,13 @@ class Ui_SetupWizard(object):
self.uiRefreshPushButton = QtWidgets.QPushButton(self.uiVMWizardPage)
self.uiRefreshPushButton.setObjectName("uiRefreshPushButton")
self.horizontalLayout.addWidget(self.uiRefreshPushButton)
self.gridLayout_3.addLayout(self.horizontalLayout, 6, 0, 1, 3)
self.gridLayout_3.addLayout(self.horizontalLayout, 6, 0, 1, 2)
self.uiCPUSpinBox = QtWidgets.QSpinBox(self.uiVMWizardPage)
self.uiCPUSpinBox.setMinimum(1)
self.uiCPUSpinBox.setMaximum(128)
self.uiCPUSpinBox.setProperty("value", 1)
self.uiCPUSpinBox.setObjectName("uiCPUSpinBox")
self.gridLayout_3.addWidget(self.uiCPUSpinBox, 8, 0, 1, 3)
self.gridLayout_3.addWidget(self.uiCPUSpinBox, 8, 0, 1, 2)
self.uiRAMSpinBox = QtWidgets.QSpinBox(self.uiVMWizardPage)
self.uiRAMSpinBox.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
@@ -180,7 +170,7 @@ class Ui_SetupWizard(object):
self.uiRAMSpinBox.setSingleStep(512)
self.uiRAMSpinBox.setProperty("value", 2048)
self.uiRAMSpinBox.setObjectName("uiRAMSpinBox")
self.gridLayout_3.addWidget(self.uiRAMSpinBox, 10, 0, 1, 3)
self.gridLayout_3.addWidget(self.uiRAMSpinBox, 10, 0, 1, 2)
SetupWizard.addPage(self.uiVMWizardPage)
self.uiRemoteControllerWizardPage = QtWidgets.QWizardPage()
self.uiRemoteControllerWizardPage.setObjectName("uiRemoteControllerWizardPage")
@@ -260,9 +250,9 @@ class Ui_SetupWizard(object):
self.uiLocalServerStatusWizardPage.setSubTitle(_translate("SetupWizard", "Validation of the configuration for the local server"))
self.uiVMWizardPage.setTitle(_translate("SetupWizard", "GNS3 VM"))
self.uiVMWizardPage.setSubTitle(_translate("SetupWizard", "In order to run the GNS3 VM you must first have VMware or VirtualBox installed and the GNS3 VM.ova imported with one of these software."))
self.uiVirtualizationSoftwarLabel.setText(_translate("SetupWizard", "Virtualization software:"))
self.uiVmwareRadioButton.setToolTip(_translate("SetupWizard", "VMware is recommended to run Qemu based appliances (required for KVM)."))
self.uiVmwareRadioButton.setText(_translate("SetupWizard", "VMware (recommended)"))
self.uiVirtualizationSoftwarLabel.setText(_translate("SetupWizard", "Virtualization software:"))
self.uiVirtualBoxRadioButton.setToolTip(_translate("SetupWizard", "Use VirtualBox if you intend to only use Dynamips, IOU or VPCS."))
self.uiVirtualBoxRadioButton.setText(_translate("SetupWizard", "VirtualBox"))
self.uiVMNameLabel.setText(_translate("SetupWizard", "VM name:"))

View File

@@ -28,17 +28,18 @@ class ExportProjectWorker(QtCore.QObject):
finished = QtCore.pyqtSignal()
updated = QtCore.pyqtSignal(int)
def __init__(self, project, path, include_images, include_snapshots, compression):
def __init__(self, project, path, include_images, include_snapshots, reset_mac_addresses, compression):
super().__init__()
self._project = project
self._include_images = include_images
self._include_snapshots = include_snapshots
self._reset_mac_addresses = reset_mac_addresses
self._path = path
self._compression = compression
def run(self):
if self._project:
self._project.get("/export?include_images={}&include_snapshots={}&compression={}".format(self._include_images, self._include_snapshots, self._compression),
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)

View File

@@ -23,9 +23,8 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.6"
__version_info__ = (2, 2, 6, 0)
__version__ = "2.2.12"
__version_info__ = (2, 2, 12, 0)
# If it's a git checkout try to add the commit
if "dev" in __version__:
try:

View File

@@ -24,15 +24,17 @@ import os
import shlex
import subprocess
from .controller import Controller
import logging
log = logging.getLogger(__name__)
def vncConsole(host, port, command):
def vncConsole(node, port, command):
"""
Start a VNC console program.
:param host: host or IP address
:param node: Node instance
:param port: port number
"""
@@ -40,10 +42,16 @@ def vncConsole(host, port, command):
log.error("VNC client is not configured")
return
name = node.name()
host = node.consoleHost()
# replace the place-holders by the actual values
command = command.replace("%h", host)
command = command.replace("%p", str(port))
command = command.replace("%P", str(port - 5900))
command = command.replace("%d", name.replace('"', '\\"'))
command = command.replace("%i", node.project().id())
command = command.replace("%n", str(node.id()))
try:
log.debug('starting VNC program "{}"'.format(command))

View File

@@ -1,3 +1,2 @@
-rrequirements.txt
#PyQt5==5.7

View File

@@ -1,4 +1,4 @@
jsonschema==2.6.0 # pyup: ignore
raven>=5.23.0
psutil==5.6.6
distro>=1.3.0
jsonschema==3.2.0
sentry-sdk>=0.14.4
psutil==5.6.7
distro>=1.3.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -326,8 +326,6 @@
<file>charcoal_icons/filter-hover.svg</file>
<file>charcoal_icons/filter-reset.svg</file>
<file>charcoal_icons/filter-reset-hover.svg</file>
<file>images/vmware_fusion_banner.png</file>
<file>images/vmware_workstation_banner.png</file>
<file>styles/charcoal.css</file>
</qresource>
</RCC>

View File

@@ -1,19 +0,0 @@
#!/bin/bash
echo '
_______ ________ _______ ______
| \ | \| \ / \
| $$$$$$$\| $$$$$$$$| $$$$$$$\| $$$$$$\
| $$__/ $$| $$__ | $$__/ $$| $$__/ $$
| $$ $$| $$ \ | $$ $$ >$$ $$
| $$$$$$$ | $$$$$ | $$$$$$$ | $$$$$$
| $$ | $$_____ | $$ | $$__/ $$
| $$ | $$ \| $$ \$$ $$
\$$ \$$$$$$$$ \$$ \$$$$$$
'
find . -name '*.py' -exec autopep8 --in-place -v --aggressive --aggressive \{\} \;
echo "It's clean"

View File

@@ -24,7 +24,7 @@ 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")
class Tox(TestCommand):
class PyTest(TestCommand):
def finalize_options(self):
TestCommand.finalize_options(self)
@@ -33,10 +33,10 @@ class Tox(TestCommand):
def run_tests(self):
# import here, cause outside the eggs aren't loaded
import tox
errcode = tox.cmdline(self.test_args)
sys.exit(errcode)
import pytest
errcode = pytest.main(self.test_args)
sys.exit(errcode)
if sys.platform.startswith('linux'):
data_files = [
@@ -61,8 +61,8 @@ setup(
version=__import__("gns3").__version__,
url="http://github.com/GNS3/gns3-gui",
license="GNU General Public License v3 (GPLv3)",
tests_require=["tox"],
cmdclass={"test": Tox},
tests_require=["pytest"],
cmdclass={"test": PyTest},
author="Jeremy Grossmann",
author_email="package-maintainer@gns3.net",
description="GNS3 graphical interface for the GNS3 server.",
@@ -78,6 +78,7 @@ setup(
include_package_data=True,
package_data={"gns3": ["configs/*.txt", "schemas/*.json"]},
platforms="any",
setup_requires=["setuptools>=17.1"],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: X11 Applications :: Qt",

View File

@@ -22,6 +22,7 @@ import json
from unittest.mock import patch, MagicMock
from gns3.local_config import LocalConfig
from gns3.version import __version_info__
@pytest.fixture
@@ -119,16 +120,17 @@ def test_migrateOldConfigOSX(tmpdir):
local_config = LocalConfig()
assert os.path.exists(str(tmpdir / '.config' / 'GNS3'))
assert os.path.exists(str(tmpdir / '.config' / 'GNS3' / 'hello'))
version = "{}.{}".format(__version_info__[0], __version_info__[1])
assert os.path.exists(str(tmpdir / '.config' / 'GNS3' / version))
assert os.path.exists(str(tmpdir / '.config' / 'GNS3' / version / 'hello'))
assert os.path.exists(str(tmpdir / '.config' / 'gns3.net'))
# It should migrate only one time
open(str(tmpdir / '.config' / 'gns3.net' / 'world'), 'w+').close()
local_config._migrateOldConfigPath()
assert os.path.exists(str(tmpdir / '.config' / 'GNS3' / 'hello'))
assert not os.path.exists(str(tmpdir / '.config' / 'GNS3' / 'world'))
assert os.path.exists(str(tmpdir / '.config' / 'GNS3' / version / 'hello'))
assert not os.path.exists(str(tmpdir / '.config' / 'GNS3' / version / 'world'))
def test_migrate13Config(tmpdir):

View File

@@ -23,19 +23,20 @@ from unittest.mock import patch
from gns3.spice_console import spiceConsole
def test_spice_console_on_linux_and_mac():
def test_spice_console_on_linux_and_mac(vpcs_device):
with patch('subprocess.Popen') as popen, \
patch('sys.platform', new="linux"):
spiceConsole('localhost', '2525', 'command %h %p')
vpcs_device.settings()["console_host"] = "localhost"
spiceConsole(vpcs_device, '2525', 'command %h %p')
popen.assert_called_once_with(shlex.split('command localhost 2525'), env=os.environ)
def test_spice_console_on_windows():
def test_spice_console_on_windows(vpcs_device):
with patch('subprocess.Popen') as popen, \
patch('sys.platform', new="win"):
spiceConsole('localhost', '2525', 'command %h %p')
vpcs_device.settings()["console_host"] = "localhost"
spiceConsole(vpcs_device, '2525', 'command %h %p')
popen.assert_called_once_with('command localhost 2525')
@@ -47,9 +48,10 @@ def test_spice_console_on_windows():
# spiceConsole('localhost', '2525', 'command %h %p')
def test_spice_console_with_ipv6_support():
def test_spice_console_with_ipv6_support(vpcs_device):
with patch('subprocess.Popen') as popen, \
patch('sys.platform', new="linux"):
spiceConsole('::1', '2525', 'command %h %p')
vpcs_device.settings()["console_host"] = "::1"
spiceConsole(vpcs_device, '2525', 'command %h %p')
popen.assert_called_once_with(shlex.split('command [::1] 2525'), env=os.environ)

View File

@@ -23,18 +23,20 @@ from unittest.mock import patch
from gns3.vnc_console import vncConsole
def test_vnc_console_on_linux_and_mac():
def test_vnc_console_on_linux_and_mac(vpcs_device):
with patch('subprocess.Popen') as popen, \
patch('sys.platform', new="linux"):
vncConsole('localhost', 6000, 'command %h %p %P')
popen.assert_called_once_with(shlex.split('command localhost 6000 100'), env=os.environ)
vpcs_device.settings()["console_host"] = "localhost"
vncConsole(vpcs_device, 6000, 'command %h %p %P')
popen.assert_called_once_with(shlex.split('command localhost 6000 100'), env=os.environ)
def test_vnc_console_on_windows():
def test_vnc_console_on_windows(vpcs_device):
with patch('subprocess.Popen') as popen, \
patch('sys.platform', new="win"):
vncConsole('localhost', 6000, 'command %h %p %P')
popen.assert_called_once_with('command localhost 6000 100')
vpcs_device.settings()["console_host"] = "localhost"
vncConsole(vpcs_device, 6000, 'command %h %p %P')
popen.assert_called_once_with('command localhost 6000 100')
# def test_vnc_console_on_linux_with_popen_issues():

19
tox.ini
View File

@@ -1,19 +0,0 @@
[tox]
envlist = py34
[testenv]
sitepackages=True
setenv = PYTHONPATH={toxinidir}
commands = py.test
[pep8]
ignore = E501,E402
[flake8]
ignore = E265,E501
exclude = tests/*,gns3/ui/*,./gns3/modules/*/ui
[pytest]
python_paths = {toxinidir}
norecursedirs = .tox
timeout = 10

View File

@@ -1,4 +1,4 @@
-rrequirements.txt
PyQt5==5.14.1 # pyup: ignore
PyQt5==5.12.3 # pyup: ignore
pywin32>=223 # pyup: ignore