mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-06-07 11:06:28 +03:00
Compare commits
436 Commits
v1.3.5
...
v1.4.0alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e05ee6bba0 | ||
|
|
111ed742ec | ||
|
|
8fd5743d75 | ||
|
|
63b79ccf3b | ||
|
|
45f4265c03 | ||
|
|
b7b13ea2cb | ||
|
|
1f660b180e | ||
|
|
3b2ccf75ec | ||
|
|
734fc65c29 | ||
|
|
5252ed16ca | ||
|
|
cec6fcf81a | ||
|
|
a812796bdc | ||
|
|
9abb4fe692 | ||
|
|
42b86c6b18 | ||
|
|
8aec2275fd | ||
|
|
61f03d734b | ||
|
|
907e20d0ec | ||
|
|
f84c759e8d | ||
|
|
f6fb4695c1 | ||
|
|
3a1ccb5ba0 | ||
|
|
7b8ab4ac2c | ||
|
|
53504f1c3d | ||
|
|
d5408165f9 | ||
|
|
9bf8c115c1 | ||
|
|
a06ac4cbb6 | ||
|
|
6406b7412d | ||
|
|
41aca47f92 | ||
|
|
a170e1cfb5 | ||
|
|
b2429a6a1b | ||
|
|
23e1baf92f | ||
|
|
278c94b7df | ||
|
|
256fc5a222 | ||
|
|
a0fa28b3fd | ||
|
|
09d8212225 | ||
|
|
e658786e88 | ||
|
|
4a1e6eba8c | ||
|
|
ce5e209681 | ||
|
|
40178b5277 | ||
|
|
631c487233 | ||
|
|
5e47afe3a4 | ||
|
|
942bf9094d | ||
|
|
985200b6d9 | ||
|
|
35b61bc891 | ||
|
|
b149abbb23 | ||
|
|
536387ad8c | ||
|
|
1628edbb8b | ||
|
|
39adbbdb27 | ||
|
|
be49fa9b54 | ||
|
|
aaed8435d1 | ||
|
|
c5bd406351 | ||
|
|
4004caadc7 | ||
|
|
1ac2a782c4 | ||
|
|
6887928bba | ||
|
|
1401537796 | ||
|
|
e53f5ca175 | ||
|
|
463f49586c | ||
|
|
5a87098f95 | ||
|
|
da44ff05aa | ||
|
|
3839171d42 | ||
|
|
8d9a009f89 | ||
|
|
2c0a4cf7a7 | ||
|
|
4b2269b668 | ||
|
|
3bfff093f8 | ||
|
|
6d835a2068 | ||
|
|
36398c54e0 | ||
|
|
2a2777b22d | ||
|
|
11dc69334d | ||
|
|
c4c17aa115 | ||
|
|
4b41c06dc4 | ||
|
|
a9e27cd63f | ||
|
|
0f6b4f2b32 | ||
|
|
08877155e2 | ||
|
|
7007f3ea44 | ||
|
|
9419cce747 | ||
|
|
033c884059 | ||
|
|
99b0b65e89 | ||
|
|
67042470f3 | ||
|
|
7c5388ee71 | ||
|
|
96634ece3f | ||
|
|
ee9ea92a11 | ||
|
|
246e9f7e3f | ||
|
|
fc43f89d9e | ||
|
|
be75dc95a3 | ||
|
|
6bb0f7b902 | ||
|
|
6178c56606 | ||
|
|
0a2ca923ee | ||
|
|
5adc4cb437 | ||
|
|
28d4371f4d | ||
|
|
d343bbe1ac | ||
|
|
c6a6163aec | ||
|
|
be60a37a29 | ||
|
|
b3d42866b7 | ||
|
|
9633fb659a | ||
|
|
fab637f5ae | ||
|
|
edcd991659 | ||
|
|
84f41b9c2f | ||
|
|
e7a61f07a2 | ||
|
|
57616ffd83 | ||
|
|
ea002e6634 | ||
|
|
24574360a0 | ||
|
|
e4dff4916b | ||
|
|
bd1ff4c954 | ||
|
|
563c762756 | ||
|
|
6c6bd65969 | ||
|
|
e2dbd5216d | ||
|
|
959a05643f | ||
|
|
3e0f33859a | ||
|
|
b70615c19c | ||
|
|
f6956baf89 | ||
|
|
47cd7cf2a2 | ||
|
|
a1d6d17685 | ||
|
|
fe768a650d | ||
|
|
d9ba282024 | ||
|
|
1b48cc99e5 | ||
|
|
8740e20c90 | ||
|
|
93a2cdf4bf | ||
|
|
0faa4e62f0 | ||
|
|
78e97e9731 | ||
|
|
d59be759bd | ||
|
|
2df78eb436 | ||
|
|
3f132a759f | ||
|
|
b87244bf9a | ||
|
|
6d826001cc | ||
|
|
2de4d36c9f | ||
|
|
ef01212ce8 | ||
|
|
9fa8c36b5f | ||
|
|
a4973616b4 | ||
|
|
a8dd2ed2da | ||
|
|
2766667d16 | ||
|
|
a7e7b9a3ca | ||
|
|
7df272fd4a | ||
|
|
cd694366ed | ||
|
|
4a9fb62663 | ||
|
|
8c7144205b | ||
|
|
f4057d4c2c | ||
|
|
ad5de8c84c | ||
|
|
15f414cae3 | ||
|
|
54d01d2ffd | ||
|
|
f8e87c5aa1 | ||
|
|
090a85bdd5 | ||
|
|
403611443f | ||
|
|
82b14a14e0 | ||
|
|
a0789b45e4 | ||
|
|
12975b1ecf | ||
|
|
59de1212cb | ||
|
|
cc8246b474 | ||
|
|
f13a91e83e | ||
|
|
598aae8ef1 | ||
|
|
fe5414bdf4 | ||
|
|
fd40289887 | ||
|
|
225b8aa63a | ||
|
|
e63bbe734c | ||
|
|
8c76fb6f7c | ||
|
|
617ed0a3cd | ||
|
|
e32e7dd828 | ||
|
|
d6ba027ae7 | ||
|
|
1ea4a7c113 | ||
|
|
8d7e161662 | ||
|
|
332b04d640 | ||
|
|
e7af8305c2 | ||
|
|
edffba3496 | ||
|
|
88834250c5 | ||
|
|
0da15c21e6 | ||
|
|
3076f98127 | ||
|
|
5a7f52b41f | ||
|
|
f403ff7776 | ||
|
|
57998195f6 | ||
|
|
e873150542 | ||
|
|
73440be270 | ||
|
|
e8caa8853e | ||
|
|
4d63643fbf | ||
|
|
c632303fd6 | ||
|
|
06596d8626 | ||
|
|
e0a47b050a | ||
|
|
55bd9bbc7e | ||
|
|
a4c47b920c | ||
|
|
25355596bb | ||
|
|
a40d128704 | ||
|
|
2f0ab09250 | ||
|
|
6be425de4d | ||
|
|
aa55b984a2 | ||
|
|
35725b2324 | ||
|
|
bb4a3487a2 | ||
|
|
2f51f985d8 | ||
|
|
bacdca038e | ||
|
|
f80e190e22 | ||
|
|
024aec1891 | ||
|
|
b80f6cc507 | ||
|
|
be11046cfc | ||
|
|
0a0522d92d | ||
|
|
f436a34474 | ||
|
|
7ab3884cb9 | ||
|
|
b616be8c0e | ||
|
|
65431c462f | ||
|
|
bc6ae0e773 | ||
|
|
5698b2eab9 | ||
|
|
4b1ff7deb5 | ||
|
|
327c0d7a2e | ||
|
|
90522914c0 | ||
|
|
cf44a36153 | ||
|
|
ba23cfdaca | ||
|
|
a85888bcbd | ||
|
|
3d8c25159d | ||
|
|
543f73bf7a | ||
|
|
4130082a8d | ||
|
|
692815713b | ||
|
|
14bef07d25 | ||
|
|
e9c69a118c | ||
|
|
275faea616 | ||
|
|
f4268bb447 | ||
|
|
35eeae7c58 | ||
|
|
ed04df26f8 | ||
|
|
79efaad817 | ||
|
|
1075745439 | ||
|
|
2f7255301d | ||
|
|
fc60d50560 | ||
|
|
488d32974f | ||
|
|
bdd12b262e | ||
|
|
ec8e645679 | ||
|
|
a239c923a3 | ||
|
|
e2fa8b3199 | ||
|
|
2128f46165 | ||
|
|
1378cab008 | ||
|
|
65aca8ab76 | ||
|
|
9db42c9783 | ||
|
|
d9e551031d | ||
|
|
554a163d7d | ||
|
|
858a59568e | ||
|
|
e0eabbebd1 | ||
|
|
1b5c675711 | ||
|
|
bf4daff685 | ||
|
|
14bd2c6a3b | ||
|
|
109ee591c1 | ||
|
|
c67cf56dc5 | ||
|
|
727dcc149d | ||
|
|
b450178444 | ||
|
|
23e281689a | ||
|
|
f96eb630d1 | ||
|
|
7cd16c7063 | ||
|
|
87a04193f9 | ||
|
|
5c196d7e47 | ||
|
|
8db1b230d4 | ||
|
|
f92e98d587 | ||
|
|
9b3ed76fb0 | ||
|
|
91780f0b9c | ||
|
|
0f7f7946cd | ||
|
|
c4a0037956 | ||
|
|
586492fc92 | ||
|
|
cfe34628fa | ||
|
|
1e2b7c7e02 | ||
|
|
c12a91ee5f | ||
|
|
c93a2dcb1c | ||
|
|
9baa529200 | ||
|
|
29bf1e5dc4 | ||
|
|
0f1b78e1a5 | ||
|
|
d03820bf91 | ||
|
|
adbf7aeb42 | ||
|
|
b57bf29247 | ||
|
|
4a96468e42 | ||
|
|
272c7850d7 | ||
|
|
7466bda816 | ||
|
|
c202399eb6 | ||
|
|
3c046020ef | ||
|
|
af3ab140bd | ||
|
|
9d9d43a249 | ||
|
|
5045447bc6 | ||
|
|
a9772dd313 | ||
|
|
59999abb61 | ||
|
|
23a42b7c48 | ||
|
|
8bda1fe719 | ||
|
|
207e55e869 | ||
|
|
a09b8f1762 | ||
|
|
28f23ae595 | ||
|
|
da0dc31ed0 | ||
|
|
6a9873dbaa | ||
|
|
c68d311f92 | ||
|
|
c148fa9000 | ||
|
|
26fc48ce14 | ||
|
|
0eb7174183 | ||
|
|
248e8750e1 | ||
|
|
6c240fc5d3 | ||
|
|
def3d617b0 | ||
|
|
c49314e755 | ||
|
|
18a80d4fdd | ||
|
|
195e136798 | ||
|
|
606e702e6f | ||
|
|
aed7a6fbf3 | ||
|
|
bbb79bba0f | ||
|
|
731a838c16 | ||
|
|
1a55c472e0 | ||
|
|
222b476d84 | ||
|
|
0e42f31b88 | ||
|
|
d5b3f605f3 | ||
|
|
17471db248 | ||
|
|
e2cdff3604 | ||
|
|
118b1a039b | ||
|
|
ea8119f3ad | ||
|
|
9b0f548336 | ||
|
|
e8a7c15fee | ||
|
|
6055127118 | ||
|
|
81e4a402f2 | ||
|
|
ca975e4f94 | ||
|
|
2e06972161 | ||
|
|
d6f26f78a5 | ||
|
|
ae53634f48 | ||
|
|
09d8e1ce6b | ||
|
|
535069587e | ||
|
|
5318fbaca1 | ||
|
|
5f251c296e | ||
|
|
291f87e197 | ||
|
|
cca86141fd | ||
|
|
84c4fb825c | ||
|
|
79272be631 | ||
|
|
4b9d03fb59 | ||
|
|
3c95e88f08 | ||
|
|
73ed4fa6f3 | ||
|
|
6451f580cb | ||
|
|
dcf8a4948b | ||
|
|
3458cec41e | ||
|
|
809008561f | ||
|
|
72d60e1227 | ||
|
|
8fc335718a | ||
|
|
e6129ad78b | ||
|
|
10802d6a2c | ||
|
|
7b05d26d7e | ||
|
|
fa8d67ebe1 | ||
|
|
0d320c26cd | ||
|
|
96c0276a0e | ||
|
|
3cc5a8ae5c | ||
|
|
5b0ca03640 | ||
|
|
0af08cf578 | ||
|
|
dfe21c5b8c | ||
|
|
f8c5da52f3 | ||
|
|
20752bf48e | ||
|
|
7778790bae | ||
|
|
fccbc90307 | ||
|
|
c5895a7d21 | ||
|
|
9262c8527b | ||
|
|
32484570bb | ||
|
|
f26f6c33d0 | ||
|
|
ec2db0594e | ||
|
|
a6f3f425c3 | ||
|
|
4566fec58a | ||
|
|
a362206e55 | ||
|
|
a9543e50f2 | ||
|
|
06fc3e726a | ||
|
|
e19a2ac67a | ||
|
|
5e28fb5246 | ||
|
|
2ad9fcf701 | ||
|
|
427b38912f | ||
|
|
5d4619a70a | ||
|
|
5e56f27e45 | ||
|
|
92fca450f1 | ||
|
|
e52f8bbbde | ||
|
|
94c6ccb549 | ||
|
|
a8edd8ffb9 | ||
|
|
298768f0cb | ||
|
|
b566098a56 | ||
|
|
f8f34e46e3 | ||
|
|
9227831922 | ||
|
|
625d4c951e | ||
|
|
5cdc479029 | ||
|
|
d385585291 | ||
|
|
248107bfb8 | ||
|
|
539e336fa1 | ||
|
|
8ab07563e0 | ||
|
|
487332df40 | ||
|
|
68d156c0e8 | ||
|
|
a9a5622525 | ||
|
|
9e02950844 | ||
|
|
a1730c9524 | ||
|
|
ed3257399b | ||
|
|
763f65cbbe | ||
|
|
26675eac64 | ||
|
|
4789be70fc | ||
|
|
2b0168296f | ||
|
|
2a8868e029 | ||
|
|
7410abf895 | ||
|
|
86d0c3bfcb | ||
|
|
fb14747a8b | ||
|
|
d11fbc1069 | ||
|
|
b48d8d4372 | ||
|
|
e257a64772 | ||
|
|
a6b1961d77 | ||
|
|
d363212191 | ||
|
|
266bf202bb | ||
|
|
f280445138 | ||
|
|
fcd93c8db8 | ||
|
|
d02f0bf5b4 | ||
|
|
986734e29b | ||
|
|
147d9dbe83 | ||
|
|
c974853fe8 | ||
|
|
d124f9c8e0 | ||
|
|
cb9222271d | ||
|
|
72505b550d | ||
|
|
7500b602dc | ||
|
|
89410cc55d | ||
|
|
9d3b17d86b | ||
|
|
553e3b02f5 | ||
|
|
756f1dd218 | ||
|
|
accf332668 | ||
|
|
4b0b5cb85c | ||
|
|
23ad776a74 | ||
|
|
02cc9ec935 | ||
|
|
1d0c21eff1 | ||
|
|
422c97f681 | ||
|
|
f0d00420c3 | ||
|
|
64c1eac2d0 | ||
|
|
ae7c98ce78 | ||
|
|
e04fc7d950 | ||
|
|
97f75fb971 | ||
|
|
0e2c411198 | ||
|
|
ca7917b407 | ||
|
|
69013d2765 | ||
|
|
8a022a2365 | ||
|
|
0d07af4862 | ||
|
|
d5279fb50c | ||
|
|
7d887bdbef | ||
|
|
d12770f97c | ||
|
|
a3d9efbda2 | ||
|
|
3f6479e578 | ||
|
|
5d8d8a5ffe | ||
|
|
9d511e0370 | ||
|
|
73d26b45fc | ||
|
|
03d1cc4f78 | ||
|
|
49c89810d8 | ||
|
|
4dc3647370 | ||
|
|
6ab00e46b2 | ||
|
|
ec22d72f3f | ||
|
|
97324ce4d4 | ||
|
|
a11d84e812 | ||
|
|
1d7774bcd6 | ||
|
|
806a8efe94 | ||
|
|
b0894b1e75 | ||
|
|
92faccdd90 | ||
|
|
7025accd88 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -37,6 +37,7 @@ nosetests.xml
|
||||
|
||||
# PyCharm
|
||||
.idea
|
||||
/.eggs
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
@@ -50,3 +51,10 @@ nosetests.xml
|
||||
|
||||
# Qt creator
|
||||
*.autosave
|
||||
|
||||
# Licence keys
|
||||
keys
|
||||
|
||||
# Custom config
|
||||
/gns3_server.ini
|
||||
updates
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -5,7 +5,6 @@ language: python
|
||||
#sudo: false
|
||||
|
||||
python:
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
|
||||
cache:
|
||||
@@ -14,11 +13,16 @@ cache:
|
||||
- build
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev
|
||||
- sudo apt-get install qt5-default qttools5-dev-tools
|
||||
- sh scripts/prepare_travis.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- julien@gns3.net
|
||||
email: false
|
||||
#email:
|
||||
# - julien@gns3.net
|
||||
#irc:
|
||||
# channels:
|
||||
# - "chat.freenode.net#gns3"
|
||||
|
||||
98
CHANGELOG
98
CHANGELOG
@@ -1,5 +1,103 @@
|
||||
# Change Log
|
||||
|
||||
## 1.4.0alpha2 22/07/2015
|
||||
|
||||
* Cloud support with the GNS3 VM.
|
||||
* Display an error message when Qemu binaries cannot be retrieved in the Qemu VM configuration page.
|
||||
* Remove default FLASH when no hda disk for Qemu VMs. Fixes #535.
|
||||
* Use the registry to find vmrun if the default VMware install path doesn't exist. Fixes #546.
|
||||
* Avoid the creation of a NIO when one has been cancelled.
|
||||
* Fix Crash with chinese characters
|
||||
* Display an error if terminal command is invalid
|
||||
* Prevents "Show in File Manager" to be used with generic switches.
|
||||
* Remove unused dependencies
|
||||
* Drop PyQt4 support and show an error for users
|
||||
* Fixes symbol for VM template gone after restart. Fixes #538.
|
||||
* Fix VirtualBox GNS3 VM
|
||||
* Fix issue with remote server not saved/migrated
|
||||
* Remove ram as a mandatory dynamips settings
|
||||
* Force UTF-8 when reading server configuration file
|
||||
|
||||
## 1.4.0alpha1 09/07/2015
|
||||
|
||||
* Remove unused cloud code from the 1.4
|
||||
* Setup Wizard (to be tweaked). Implements #402.
|
||||
* Adds -no-kvm to the ASA template and ignore -no-kvm on platforms other than Linux. Should resolve #472.
|
||||
* Explicitly set the acceleration method to tcg for ASA templates. Should resolve #472.
|
||||
* Show an error if the console port range overlaps the default VNC port range (5900 to 6000) in the server preferences.
|
||||
* Support self update of the application
|
||||
* Option to adjust the local server IP address to be in the same subnet as the GNS3 VM.
|
||||
* Warning about deprecated ASA on Qemu
|
||||
* Moves KVM setting to Qemu preferences.
|
||||
* VNC console support for Qemu VMs. Implements #447.
|
||||
* Change the location of the config file on OSX
|
||||
* Adds first port name option (for management interfaces). Completes #309.
|
||||
* Add a force quit button when closing the app
|
||||
* Basic auth support for remote servers
|
||||
* Adds symbol overview in tooltips for all symbol text fields.
|
||||
* Remove SVG icons used in hover events.
|
||||
* Support for custom symbols
|
||||
* RAM usage based load balancing. #419.
|
||||
* Creates a new "Servers" config section and moves "LocalServer", "RemoteServers" and "GNS3VM" under it.
|
||||
* Support spaces in the local server log path.
|
||||
* Round-Robin load balancing support. #419.
|
||||
* Auto upload image if missing on remote server
|
||||
* ACPI shutdown support for VMware VMs. Fixes #436.
|
||||
* Add timestamps to gns3_gui.log
|
||||
* Store MD5 of images in topology
|
||||
* SSL support
|
||||
* GNS3 VM support
|
||||
* Add a specific icon for VPCS
|
||||
* Ensure no colored log output on Windows
|
||||
* Enable KVM acceleration option.
|
||||
* Apply the result of the auto Idle-PC feature to other routers with the same IOS image.
|
||||
* Improve config change autodetect
|
||||
* Show in file manager (#260: to complete using the VM directory instead).
|
||||
* Open/save dialog is opened in project folder when importing/exporting configs. Fixes #299.
|
||||
* IPv6 support.
|
||||
* Import/Export support for IOU nvrams.
|
||||
* Option to drop nvram & disk files for IOS routers in order to save disk space.
|
||||
* Fix IOU server edit
|
||||
* JSON schema for checking topologies
|
||||
* Support for base MAC address for Qemu VMs.
|
||||
* Drop Python 3.3
|
||||
* ACPI shutdown support for Qemu VMs.
|
||||
* ACPI shutdown support for VirtualBox VMs.
|
||||
* Rename node configurator to node properties.
|
||||
* Merge pull request #381 from GNS3/doubleclick_label
|
||||
* If you doubleclick on a label we open the change hostname dialog
|
||||
* Fix GNS3 server location for OSX
|
||||
* Serial console implementation for VMware VMs.
|
||||
* Ubridge configuration support.
|
||||
* Adds a wizard for creating images with qemu-img and mofified qemu configuration page to use it.
|
||||
* Download remote project with md5 support
|
||||
* SSH support
|
||||
* Avoid moving .gns3_temporary files.
|
||||
* New inline help text for the idle-pc dialog.
|
||||
* Add support for IOS-XRv under qemu wizard.
|
||||
* Upload images from gui
|
||||
* Text can now has an alpha channel, allowing for transparent or semi-transparent text.
|
||||
* The device list in the configuration dialog is hidden by default when only one device is selected.
|
||||
* Adds multi select support in all device template pages.
|
||||
* Adjusted the double click action so that a click on a stopped node opens the configuration dialog with all selected nodes and a double click on a started node consoles to all selected devices.
|
||||
* VMware support for Windows and Linux
|
||||
* Listen for notifications from servers.
|
||||
* Migration to QT5
|
||||
* Wireshark remote packet capture
|
||||
|
||||
## 1.3.7 22/06/2015
|
||||
|
||||
* Makes sure Hub Ethernet port names are string.
|
||||
* Support spaces in the local server log path.
|
||||
* Fixes issue when setting the local server settings.
|
||||
* Fix a crash with Python 3.3
|
||||
* Fixes WICs are not displayed correctly. Fixes #434.
|
||||
* Do not load settings that the GUI doesn't use.
|
||||
|
||||
## 1.3.6 16/06/2015
|
||||
|
||||
* Fix an issue with 1.4dev compatibility
|
||||
|
||||
## 1.3.5 16/06/2015
|
||||
|
||||
* Do not crash in a very rare case on Windows when stoping local server
|
||||
|
||||
31
README.rst
31
README.rst
@@ -20,7 +20,7 @@ Dependencies:
|
||||
|
||||
- Python 3.3 or above
|
||||
- Setuptools
|
||||
- PyQt libraries
|
||||
- PyQt 5 libraries
|
||||
- Apache Libcloud library
|
||||
- Requests library
|
||||
- Paramiko library
|
||||
@@ -30,6 +30,13 @@ The following commands will install some of these dependencies:
|
||||
.. code:: bash
|
||||
|
||||
sudo apt-get install python3-setuptools
|
||||
sudo apt-get install python3-pyqt5
|
||||
sudo apt-get install python3-pyqt5.qtsvg
|
||||
sudo apt-get install python3-pyqt5.qtwebkit
|
||||
|
||||
If you want to test using PyQt4
|
||||
|
||||
.. code:: bash
|
||||
sudo apt-get install python3-pyqt4
|
||||
|
||||
Finally these commands will install the GUI as well as the rest of the dependencies:
|
||||
@@ -49,8 +56,8 @@ If you install via source you need to first install:
|
||||
|
||||
- Python (3.3 or above) - https://www.python.org/downloads/windows/
|
||||
- Pywin32 - https://sourceforge.net/projects/pywin32/
|
||||
- Qt4 - http://www.qt.io/download-open-source/
|
||||
- PyQt4 - http://www.riverbankcomputing.com/software/pyqt/download
|
||||
- Qt5 - http://www.qt.io/download-open-source/
|
||||
- PyQt5 - http://www.riverbankcomputing.com/software/pyqt/download5
|
||||
- PyCrypto (which if you compile from source, requires Visual Studio 2010 with GMP or MPIR libraries)
|
||||
|
||||
And finally, call
|
||||
@@ -75,6 +82,11 @@ Then install the GNS3 dependencies.
|
||||
brew install python3
|
||||
brew install qt
|
||||
brew install sip --without-python --with-python3
|
||||
brew install pyqt5 --without-python --with-python3
|
||||
|
||||
If you want to test using PyQt4
|
||||
|
||||
.. code:: bash
|
||||
brew install pyqt --without-python --with-python3
|
||||
|
||||
Finally, install both the GUI & server from the source.
|
||||
@@ -100,3 +112,16 @@ If you want to update the interface, modify the .ui files using QT tools. And:
|
||||
|
||||
cd scripts
|
||||
python build_pyqt.py
|
||||
|
||||
|
||||
Test with PyQT4
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to simulate a user with PyQT4:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
export GNS3_QT4=1
|
||||
python gns3/main.py
|
||||
|
||||
|
||||
|
||||
38
fake_frozen_gns3.py
Executable file
38
fake_frozen_gns3.py
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This script fake GNS3 run as a frozen app.
|
||||
|
||||
Use it for testing stuff like self update.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import importlib
|
||||
|
||||
# Fake GNS3 run from a binary
|
||||
sys.executable = os.path.realpath(__file__)
|
||||
|
||||
# Add site-package directory before cx_freeze directory
|
||||
sys.path.insert(0, os.path.dirname(sys.executable))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(sys.executable), 'site-packages'))
|
||||
|
||||
sys.frozen = True
|
||||
|
||||
module = importlib.import_module("gns3.main")
|
||||
module.main()
|
||||
@@ -1,337 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Base cloud controller class.
|
||||
|
||||
Base class for interacting with Cloud APIs to create and manage cloud
|
||||
instances.
|
||||
|
||||
"""
|
||||
from collections import namedtuple
|
||||
import hashlib
|
||||
import os
|
||||
import logging
|
||||
from io import StringIO, BytesIO
|
||||
|
||||
from libcloud.compute.base import NodeAuthSSHKey
|
||||
from libcloud.storage.types import ContainerAlreadyExistsError, ContainerDoesNotExistError, ObjectDoesNotExistError
|
||||
|
||||
from .exceptions import ItemNotFound, KeyPairExists, MethodNotAllowed
|
||||
from .exceptions import OverLimit, BadRequest, ServiceUnavailable
|
||||
from .exceptions import Unauthorized, ApiError
|
||||
|
||||
|
||||
KeyPair = namedtuple("KeyPair", ['name'], verbose=False)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def parse_exception(exception):
|
||||
"""
|
||||
Parse the exception to separate the HTTP status code from the text.
|
||||
|
||||
Libcloud raises many exceptions of the form:
|
||||
Exception("<http status code> <http error> <reponse body>")
|
||||
|
||||
in lieu of raising specific incident-based exceptions.
|
||||
|
||||
"""
|
||||
|
||||
e_str = str(exception)
|
||||
|
||||
try:
|
||||
status = int(e_str[0:3])
|
||||
error_text = e_str[3:]
|
||||
|
||||
except ValueError:
|
||||
status = None
|
||||
error_text = e_str
|
||||
|
||||
return status, error_text
|
||||
|
||||
|
||||
class BaseCloudCtrl(object):
|
||||
|
||||
""" Base class for interacting with a cloud provider API. """
|
||||
|
||||
http_status_to_exception = {
|
||||
400: BadRequest,
|
||||
401: Unauthorized,
|
||||
404: ItemNotFound,
|
||||
405: MethodNotAllowed,
|
||||
413: OverLimit,
|
||||
500: ApiError,
|
||||
503: ServiceUnavailable
|
||||
}
|
||||
|
||||
GNS3_CONTAINER_NAME = 'GNS3'
|
||||
|
||||
def __init__(self, username, api_key):
|
||||
self.username = username
|
||||
self.api_key = api_key
|
||||
|
||||
def _handle_exception(self, status, error_text, response_overrides=None):
|
||||
""" Raise an exception based on the HTTP status. """
|
||||
|
||||
if response_overrides:
|
||||
if status in response_overrides:
|
||||
raise response_overrides[status](error_text)
|
||||
|
||||
raise self.http_status_to_exception[status](error_text)
|
||||
|
||||
def authenticate(self):
|
||||
""" Validate cloud account credentials. Return boolean. """
|
||||
raise NotImplementedError
|
||||
|
||||
def list_sizes(self):
|
||||
""" Return a list of NodeSize objects. """
|
||||
|
||||
return self.driver.list_sizes()
|
||||
|
||||
def list_flavors(self):
|
||||
""" Return an iterable of flavors """
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def create_instance(self, name, size_id, image_id, keypair):
|
||||
"""
|
||||
Create a new instance with the supplied attributes.
|
||||
|
||||
Return a Node object.
|
||||
|
||||
"""
|
||||
try:
|
||||
image = self.get_image(image_id)
|
||||
if image is None:
|
||||
raise ItemNotFound("Image not found")
|
||||
|
||||
size = self.driver.ex_get_size(size_id)
|
||||
|
||||
args = {
|
||||
"name": name,
|
||||
"size": size,
|
||||
"image": image,
|
||||
}
|
||||
|
||||
if keypair is not None:
|
||||
auth_key = NodeAuthSSHKey(keypair.public_key)
|
||||
args["auth"] = auth_key
|
||||
args["ex_keyname"] = name
|
||||
|
||||
return self.driver.create_node(**args)
|
||||
|
||||
except Exception as e:
|
||||
status, error_text = parse_exception(e)
|
||||
|
||||
if status:
|
||||
self._handle_exception(status, error_text)
|
||||
else:
|
||||
log.error("create_instance method raised an exception: {}".format(e))
|
||||
log.error('image id {}'.format(image_id))
|
||||
|
||||
def delete_instance(self, instance):
|
||||
""" Delete the specified instance. Returns True or False. """
|
||||
|
||||
try:
|
||||
return self.driver.destroy_node(instance)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
status, error_text = parse_exception(e)
|
||||
|
||||
if status:
|
||||
self._handle_exception(status, error_text)
|
||||
else:
|
||||
raise e
|
||||
|
||||
def get_instance(self, instance):
|
||||
""" Return a Node object representing the requested instance. """
|
||||
|
||||
for i in self.driver.list_nodes():
|
||||
if i.id == instance.id:
|
||||
return i
|
||||
|
||||
raise ItemNotFound("Instance not found")
|
||||
|
||||
def list_instances(self):
|
||||
""" Return a list of instances in the current region. """
|
||||
|
||||
return self.driver.list_nodes()
|
||||
|
||||
def create_key_pair(self, name):
|
||||
""" Create and return a new Key Pair. """
|
||||
|
||||
response_overrides = {
|
||||
409: KeyPairExists
|
||||
}
|
||||
try:
|
||||
return self.driver.create_key_pair(name)
|
||||
|
||||
except Exception as e:
|
||||
status, error_text = parse_exception(e)
|
||||
if status:
|
||||
self._handle_exception(status, error_text, response_overrides)
|
||||
else:
|
||||
raise e
|
||||
|
||||
def delete_key_pair(self, keypair):
|
||||
""" Delete the keypair. Returns True or False. """
|
||||
|
||||
try:
|
||||
return self.driver.delete_key_pair(keypair)
|
||||
|
||||
except Exception as e:
|
||||
status, error_text = parse_exception(e)
|
||||
if status:
|
||||
self._handle_exception(status, error_text)
|
||||
else:
|
||||
raise e
|
||||
|
||||
def delete_key_pair_by_name(self, keypair_name):
|
||||
""" Utility method to incapsulate boilerplate code """
|
||||
|
||||
kp = KeyPair(name=keypair_name)
|
||||
return self.delete_key_pair(kp)
|
||||
|
||||
def list_key_pairs(self):
|
||||
""" Return a list of Key Pairs. """
|
||||
|
||||
return self.driver.list_key_pairs()
|
||||
|
||||
def upload_file(self, file_path, cloud_object_name):
|
||||
"""
|
||||
Uploads file to cloud storage (if it is not identical to a file already in cloud storage).
|
||||
:param file_path: path to file to upload
|
||||
:param cloud_object_name: name of file saved in cloud storage
|
||||
:return: True if file was uploaded, False if it was skipped because it already existed and was identical
|
||||
"""
|
||||
try:
|
||||
gns3_container = self.storage_driver.create_container(self.GNS3_CONTAINER_NAME)
|
||||
except ContainerAlreadyExistsError:
|
||||
gns3_container = self.storage_driver.get_container(self.GNS3_CONTAINER_NAME)
|
||||
|
||||
with open(file_path, 'rb') as file:
|
||||
local_file_hash = hashlib.md5(file.read()).hexdigest()
|
||||
|
||||
cloud_hash_name = cloud_object_name + '.md5'
|
||||
cloud_objects = [obj.name for obj in gns3_container.list_objects()]
|
||||
|
||||
# if the file and its hash are in object storage, and the local and storage file hashes match
|
||||
# do not upload the file, otherwise upload it
|
||||
if cloud_object_name in cloud_objects and cloud_hash_name in cloud_objects:
|
||||
hash_object = gns3_container.get_object(cloud_hash_name)
|
||||
cloud_object_hash = ''
|
||||
for chunk in hash_object.as_stream():
|
||||
cloud_object_hash += chunk.decode('utf8')
|
||||
|
||||
if cloud_object_hash == local_file_hash:
|
||||
return False
|
||||
|
||||
file.seek(0)
|
||||
self.storage_driver.upload_object_via_stream(file, gns3_container, cloud_object_name)
|
||||
self.storage_driver.upload_object_via_stream(StringIO(local_file_hash), gns3_container, cloud_hash_name)
|
||||
return True
|
||||
|
||||
def list_projects(self):
|
||||
"""
|
||||
Lists projects in cloud storage
|
||||
:return: Dictionary where project names are keys and values are names of objects in storage
|
||||
"""
|
||||
|
||||
try:
|
||||
gns3_container = self.storage_driver.get_container(self.GNS3_CONTAINER_NAME)
|
||||
projects = {
|
||||
obj.name.replace('projects/', '').replace('.zip', ''): obj.name
|
||||
for obj in gns3_container.list_objects()
|
||||
if obj.name.startswith('projects/') and obj.name[-4:] == '.zip'
|
||||
}
|
||||
return projects
|
||||
except ContainerDoesNotExistError:
|
||||
return []
|
||||
|
||||
def download_file(self, file_name, destination=None):
|
||||
"""
|
||||
Downloads file from cloud storage. If a file exists at destination, and it is identical to the file in cloud
|
||||
storage, it is not downloaded.
|
||||
:param file_name: name of file in cloud storage to download
|
||||
:param destination: local path to save file to (if None, returns file contents as a file-like object)
|
||||
:return: A file-like object if file contents are returned, or None if file is saved to filesystem
|
||||
"""
|
||||
|
||||
gns3_container = self.storage_driver.get_container(self.GNS3_CONTAINER_NAME)
|
||||
storage_object = gns3_container.get_object(file_name)
|
||||
|
||||
if destination is not None:
|
||||
if os.path.isfile(destination):
|
||||
# if a file exists at destination and its hash matches that of the
|
||||
# file in cloud storage, don't download it
|
||||
with open(destination, 'rb') as f:
|
||||
local_file_hash = hashlib.md5(f.read()).hexdigest()
|
||||
|
||||
hash_object = gns3_container.get_object(file_name + '.md5')
|
||||
cloud_object_hash = ''
|
||||
for chunk in hash_object.as_stream():
|
||||
cloud_object_hash += chunk.decode('utf8')
|
||||
|
||||
if local_file_hash == cloud_object_hash:
|
||||
return
|
||||
|
||||
storage_object.download(destination)
|
||||
else:
|
||||
contents = b''
|
||||
|
||||
for chunk in storage_object.as_stream():
|
||||
contents += chunk
|
||||
|
||||
return BytesIO(contents)
|
||||
|
||||
def find_storage_image_names(self, images_to_find):
|
||||
"""
|
||||
Maps names of image files to their full name in cloud storage
|
||||
:param images_to_find: list of image names to find
|
||||
:return: A dictionary where keys are image names, and values are the corresponding names of
|
||||
the files in cloud storage
|
||||
"""
|
||||
gns3_container = self.storage_driver.get_container(self.GNS3_CONTAINER_NAME)
|
||||
images_in_storage = [obj.name for obj in gns3_container.list_objects() if obj.name.startswith('images/')]
|
||||
|
||||
images = {}
|
||||
for image_name in images_to_find:
|
||||
images_with_same_name =\
|
||||
list(filter(lambda storage_image_name: storage_image_name.endswith(image_name), images_in_storage))
|
||||
|
||||
if len(images_with_same_name) == 1:
|
||||
images[image_name] = images_with_same_name[0]
|
||||
else:
|
||||
raise Exception('Image does not exist in cloud storage or is duplicated')
|
||||
|
||||
return images
|
||||
|
||||
def delete_file(self, file_name):
|
||||
gns3_container = self.storage_driver.get_container(self.GNS3_CONTAINER_NAME)
|
||||
|
||||
try:
|
||||
object_to_delete = gns3_container.get_object(file_name)
|
||||
object_to_delete.delete()
|
||||
except ObjectDoesNotExistError:
|
||||
pass
|
||||
|
||||
try:
|
||||
hash_object = gns3_container.get_object(file_name + '.md5')
|
||||
hash_object.delete()
|
||||
except ObjectDoesNotExistError:
|
||||
pass
|
||||
@@ -1,67 +0,0 @@
|
||||
""" Exception classes for CloudCtrl classes. """
|
||||
|
||||
|
||||
class ApiError(Exception):
|
||||
|
||||
""" Raised when the server returns 500 Compute Error. """
|
||||
pass
|
||||
|
||||
|
||||
class BadRequest(Exception):
|
||||
|
||||
""" Raised when the server returns 400 Bad Request. """
|
||||
pass
|
||||
|
||||
|
||||
class ComputeFault(Exception):
|
||||
|
||||
""" Raised when the server returns 400|500 Compute Fault. """
|
||||
pass
|
||||
|
||||
|
||||
class Forbidden(Exception):
|
||||
|
||||
""" Raised when the server returns 403 Forbidden. """
|
||||
pass
|
||||
|
||||
|
||||
class ItemNotFound(Exception):
|
||||
|
||||
""" Raised when the server returns 404 Not Found. """
|
||||
pass
|
||||
|
||||
|
||||
class KeyPairExists(Exception):
|
||||
|
||||
""" Raised when the server returns 409 Conflict Key pair exists. """
|
||||
pass
|
||||
|
||||
|
||||
class MethodNotAllowed(Exception):
|
||||
|
||||
""" Raised when the server returns 405 Method Not Allowed. """
|
||||
pass
|
||||
|
||||
|
||||
class OverLimit(Exception):
|
||||
|
||||
""" Raised when the server returns 413 Over Limit. """
|
||||
pass
|
||||
|
||||
|
||||
class ServerCapacityUnavailable(Exception):
|
||||
|
||||
""" Raised when the server returns 503 Server Capacity Uavailable. """
|
||||
pass
|
||||
|
||||
|
||||
class ServiceUnavailable(Exception):
|
||||
|
||||
""" Raised when the server returns 503 Service Unavailable. """
|
||||
pass
|
||||
|
||||
|
||||
class Unauthorized(Exception):
|
||||
|
||||
""" Raised when the server returns 401 Unauthorized. """
|
||||
pass
|
||||
@@ -1,259 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" Interacts with Rackspace API to create and manage cloud instances. """
|
||||
|
||||
from .base_cloud_ctrl import BaseCloudCtrl
|
||||
import json
|
||||
import requests
|
||||
from libcloud.compute.drivers.rackspace import ENDPOINT_ARGS_MAP
|
||||
from libcloud.compute.providers import get_driver
|
||||
from libcloud.compute.types import Provider
|
||||
from libcloud.storage.providers import get_driver as get_storage_driver
|
||||
from libcloud.storage.types import Provider as StorageProvider
|
||||
|
||||
from .exceptions import ItemNotFound, ApiError
|
||||
from ..version import __version__
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
RACKSPACE_REGIONS = [{ENDPOINT_ARGS_MAP[k]['region']: k} for k in
|
||||
ENDPOINT_ARGS_MAP]
|
||||
|
||||
|
||||
class RackspaceCtrl(BaseCloudCtrl):
|
||||
|
||||
""" Controller class for interacting with Rackspace API. """
|
||||
|
||||
def __init__(self, username, api_key, *args, **kwargs):
|
||||
super(RackspaceCtrl, self).__init__(username, api_key)
|
||||
|
||||
# set this up so it can be swapped out with a mock for testing
|
||||
self.post_fn = requests.post
|
||||
self.driver_cls = get_driver(Provider.RACKSPACE)
|
||||
self.storage_driver_cls = get_storage_driver(StorageProvider.CLOUDFILES)
|
||||
|
||||
self.driver = None
|
||||
self.storage_driver = None
|
||||
self.region = None
|
||||
self.instances = {}
|
||||
|
||||
self.authenticated = False
|
||||
self.identity_ep = \
|
||||
"https://identity.api.rackspacecloud.com/v2.0/tokens"
|
||||
|
||||
self.regions = []
|
||||
self.token = None
|
||||
self.tenant_id = None
|
||||
self.flavor_ep = "https://dfw.servers.api.rackspacecloud.com/v2/{username}/flavors"
|
||||
self._flavors = OrderedDict([
|
||||
('2', '512MB, 1 VCPU'),
|
||||
('3', '1GB, 1 VCPU'),
|
||||
('4', '2GB, 2 VCPUs'),
|
||||
('5', '4GB, 2 VCPUs'),
|
||||
('6', '8GB, 4 VCPUs'),
|
||||
('7', '15GB, 6 VCPUs'),
|
||||
('8', '30GB, 8 VCPUs'),
|
||||
('performance1-1', '1GB Performance, 1 VCPU'),
|
||||
('performance1-2', '2GB Performance, 2 VCPUs'),
|
||||
('performance1-4', '4GB Performance, 4 VCPUs'),
|
||||
('performance1-8', '8GB Performance, 8 VCPUs'),
|
||||
('performance2-15', '15GB Performance, 4 VCPUs'),
|
||||
('performance2-30', '30GB Performance, 8 VCPUs'),
|
||||
('performance2-60', '60GB Performance, 16 VCPUs'),
|
||||
('performance2-90', '90GB Performance, 24 VCPUs'),
|
||||
('performance2-120', '120GB Performance, 32 VCPUs',)
|
||||
])
|
||||
|
||||
def authenticate(self):
|
||||
"""
|
||||
Submit username and api key to API service.
|
||||
|
||||
If authentication is successful, set self.regions and self.token.
|
||||
Return boolean.
|
||||
|
||||
"""
|
||||
|
||||
self.authenticated = False
|
||||
|
||||
if len(self.username) < 1:
|
||||
return False
|
||||
|
||||
if len(self.api_key) < 1:
|
||||
return False
|
||||
|
||||
data = json.dumps({
|
||||
"auth": {
|
||||
"RAX-KSKEY:apiKeyCredentials": {
|
||||
"username": self.username,
|
||||
"apiKey": self.api_key
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
headers = {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
|
||||
response = self.post_fn(self.identity_ep, data=data, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
|
||||
api_data = response.json()
|
||||
self.token = self._parse_token(api_data)
|
||||
|
||||
if self.token:
|
||||
self.authenticated = True
|
||||
user_regions = self._parse_endpoints(api_data)
|
||||
self.regions = self._make_region_list(user_regions)
|
||||
self.tenant_id = self._parse_tenant_id(api_data)
|
||||
|
||||
else:
|
||||
self.regions = []
|
||||
self.token = None
|
||||
|
||||
response.connection.close()
|
||||
|
||||
return self.authenticated
|
||||
|
||||
def list_regions(self):
|
||||
""" Return a list the regions available to the user. """
|
||||
|
||||
return self.regions
|
||||
|
||||
def list_flavors(self):
|
||||
""" Return the dictionary containing flavors id and names """
|
||||
|
||||
return self._flavors
|
||||
|
||||
def _parse_endpoints(self, api_data):
|
||||
"""
|
||||
Parse the JSON-encoded data returned by the Identity Service API.
|
||||
|
||||
Return a list of regions available for Compute v2.
|
||||
|
||||
"""
|
||||
|
||||
region_codes = []
|
||||
|
||||
for ep_type in api_data['access']['serviceCatalog']:
|
||||
if ep_type['name'] == "cloudServersOpenStack" \
|
||||
and ep_type['type'] == "compute":
|
||||
|
||||
for ep in ep_type['endpoints']:
|
||||
if ep['versionId'] == "2":
|
||||
region_codes.append(ep['region'])
|
||||
|
||||
return region_codes
|
||||
|
||||
def _parse_token(self, api_data):
|
||||
""" Parse the token from the JSON-encoded data returned by the API. """
|
||||
|
||||
try:
|
||||
token = api_data['access']['token']['id']
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
return token
|
||||
|
||||
def _parse_tenant_id(self, api_data):
|
||||
""" """
|
||||
try:
|
||||
roles = api_data['access']['user']['roles']
|
||||
for role in roles:
|
||||
if 'tenantId' in role and role['name'] == 'compute:default':
|
||||
return role['tenantId']
|
||||
return None
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def _make_region_list(self, region_codes):
|
||||
"""
|
||||
Make a list of regions for use in the GUI.
|
||||
|
||||
Returns a list of key-value pairs in the form:
|
||||
<API's Region Name>: <libcloud's Region Name>
|
||||
eg,
|
||||
[
|
||||
{'DFW': 'dfw'}
|
||||
{'ORD': 'ord'},
|
||||
...
|
||||
]
|
||||
|
||||
"""
|
||||
|
||||
region_list = []
|
||||
|
||||
for ep in ENDPOINT_ARGS_MAP:
|
||||
if ENDPOINT_ARGS_MAP[ep]['region'] in region_codes:
|
||||
region_list.append({ENDPOINT_ARGS_MAP[ep]['region']: ep})
|
||||
|
||||
return region_list
|
||||
|
||||
def set_region(self, region):
|
||||
""" Set self.region and self.driver. Returns True or False. """
|
||||
|
||||
try:
|
||||
self.driver = self.driver_cls(self.username, self.api_key,
|
||||
region=region)
|
||||
self.storage_driver = self.storage_driver_cls(self.username, self.api_key,
|
||||
region=region)
|
||||
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
self.region = region
|
||||
return True
|
||||
|
||||
def get_image(self, image_id):
|
||||
return self.driver.get_image(image_id)
|
||||
|
||||
|
||||
def get_provider(cloud_settings):
|
||||
"""
|
||||
Utility function to retrieve a cloud provider instance already authenticated and with the
|
||||
region set
|
||||
|
||||
:param cloud_settings: cloud settings dictionary
|
||||
:return: a provider instance or None on errors
|
||||
"""
|
||||
try:
|
||||
username = cloud_settings['cloud_user_name']
|
||||
apikey = cloud_settings['cloud_api_key']
|
||||
region = cloud_settings['cloud_region']
|
||||
except KeyError as e:
|
||||
log.error("Unable to create cloud provider: {}".format(e))
|
||||
return
|
||||
|
||||
provider = RackspaceCtrl(username, apikey)
|
||||
|
||||
if not provider.authenticate():
|
||||
log.error("Authentication failed for cloud provider")
|
||||
return
|
||||
|
||||
if not region:
|
||||
region = provider.list_regions().values()[0]
|
||||
|
||||
if not provider.set_region(region):
|
||||
log.error("Unable to set cloud provider region")
|
||||
return
|
||||
|
||||
return provider
|
||||
@@ -1,538 +0,0 @@
|
||||
from contextlib import contextmanager
|
||||
import io
|
||||
import json
|
||||
from socket import error as socket_error
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
from ..qt import QtCore
|
||||
|
||||
from .exceptions import KeyPairExists
|
||||
from .rackspace_ctrl import get_provider
|
||||
from ..topology import Topology
|
||||
from ..servers import Servers
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def ssh_client(host, key_string):
|
||||
"""
|
||||
Context manager wrapping a SSHClient instance: the client connects on
|
||||
enter and close the connection on exit
|
||||
"""
|
||||
|
||||
import paramiko
|
||||
|
||||
class AllowAndForgetPolicy(paramiko.MissingHostKeyPolicy):
|
||||
|
||||
"""
|
||||
Custom policy for server host keys: we simply accept the key
|
||||
the server sent to us without storing it.
|
||||
"""
|
||||
|
||||
def missing_host_key(self, *args, **kwargs):
|
||||
"""
|
||||
According to MissingHostKeyPolicy protocol, to accept
|
||||
the key, simply return.
|
||||
"""
|
||||
return
|
||||
|
||||
client = paramiko.SSHClient()
|
||||
try:
|
||||
f_key = io.StringIO(key_string)
|
||||
key = paramiko.RSAKey.from_private_key(f_key)
|
||||
client.set_missing_host_key_policy(AllowAndForgetPolicy())
|
||||
client.connect(hostname=host, username="root", pkey=key)
|
||||
yield client
|
||||
except socket_error as e:
|
||||
log.debug("SSH connection socket error to {}: {}".format(host, e))
|
||||
yield None
|
||||
except Exception as e:
|
||||
log.debug("SSH connection error to {}: {}".format(host, e))
|
||||
yield None
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
class ListInstancesThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Helper class to retrieve data from the provider in a separate thread,
|
||||
avoid freezing the gui
|
||||
"""
|
||||
instancesReady = QtCore.pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent, provider):
|
||||
super().__init__(parent)
|
||||
self._provider = provider
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
instances = self._provider.list_instances()
|
||||
log.debug('Instance list: {}'.format([(i.name, i.state) for i in instances]))
|
||||
self.instancesReady.emit(instances)
|
||||
except Exception as e:
|
||||
log.info('list_instances error: {}'.format(e))
|
||||
|
||||
|
||||
class CreateInstanceThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Helper class to create instances in a separate thread
|
||||
"""
|
||||
instanceCreated = QtCore.pyqtSignal(object, object)
|
||||
|
||||
def __init__(self, parent, provider, name, flavor_id, image_id):
|
||||
super().__init__(parent)
|
||||
self._provider = provider
|
||||
self._name = name
|
||||
self._flavor_id = flavor_id
|
||||
self._image_id = image_id
|
||||
|
||||
def run(self):
|
||||
log.debug("Creating cloud keypair with name {}".format(self._name))
|
||||
try:
|
||||
k = self._provider.create_key_pair(self._name)
|
||||
except KeyPairExists:
|
||||
log.debug("Cloud keypair with name {} exists. Recreating.".format(self._name))
|
||||
# delete keypairs if they already exist
|
||||
self._provider.delete_key_pair_by_name(self._name)
|
||||
k = self._provider.create_key_pair(self._name)
|
||||
|
||||
log.debug("Creating cloud server with name {}".format(self._name))
|
||||
i = self._provider.create_instance(self._name, self._flavor_id, self._image_id, k)
|
||||
log.debug("Cloud server {} created".format(self._name))
|
||||
|
||||
self.instanceCreated.emit(i, k)
|
||||
|
||||
|
||||
class DeleteInstanceThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Helper class to remove an instance in a separate thread
|
||||
"""
|
||||
instanceDeleted = QtCore.pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent, provider, instance):
|
||||
super().__init__(parent)
|
||||
self._provider = provider
|
||||
self._instance = instance
|
||||
|
||||
def run(self):
|
||||
if self._provider.delete_instance(self._instance):
|
||||
self.instanceDeleted.emit(self._instance)
|
||||
|
||||
|
||||
class StartGNS3ServerThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Perform an SSH connection to the instances in a separate thread,
|
||||
outside the GUI event loop, and start GNS3 server
|
||||
"""
|
||||
gns3server_started = QtCore.pyqtSignal(str, str, str)
|
||||
|
||||
# This is for testing without pushing to github
|
||||
# commands = '''
|
||||
# DEBIAN_FRONTEND=noninteractive dpkg --configure -a
|
||||
# DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get -y update
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy dist-upgrade
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get -y install git python3-setuptools python3-netifaces python3-pip python3-zmq dynamips qemu-system
|
||||
# DEBIAN_FRONTEND=noninteractive apt-get -y install libc6:i386 libstdc++6:i386 libssl1.0.0:i386
|
||||
# ln -s /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.4
|
||||
# mkdir -p /opt/gns3
|
||||
# tar xzf /tmp/gns3-server.tgz -C /opt/gns3
|
||||
# cd /opt/gns3/gns3-server; pip3 install -r dev-requirements.txt
|
||||
# cd /opt/gns3/gns3-server; python3 ./setup.py install
|
||||
# ln -sf /usr/bin/dynamips /usr/local/bin/dynamips
|
||||
# wget 'https://github.com/GNS3/iouyap/releases/download/0.95/iouyap.tar.gz'
|
||||
# python -c 'import struct; open("/etc/hostid", "w").write(struct.pack("i", 00000000))'
|
||||
# hostname gns3-iouvm
|
||||
# tar xzf iouyap.tar.gz -C /usr/local/bin
|
||||
# killall python3 gns3server gns3dms
|
||||
# '''
|
||||
|
||||
commands = '''
|
||||
DEBIAN_FRONTEND=noninteractive dpkg --configure -a
|
||||
DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy dist-upgrade
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y install git python3-setuptools python3-netifaces python3-pip python3-zmq dynamips qemu-system
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y install libc6:i386 libstdc++6:i386 libssl1.0.0:i386
|
||||
ln -s /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.4
|
||||
mkdir -p /opt/gns3
|
||||
cd /opt/gns3; git clone https://github.com/planctechnologies/gns3-server.git
|
||||
cd /opt/gns3/gns3-server; git checkout dev; git pull
|
||||
cd /opt/gns3/gns3-server; pip3 install -r dev-requirements.txt
|
||||
cd /opt/gns3/gns3-server; python3 ./setup.py install
|
||||
ln -sf /usr/bin/dynamips /usr/local/bin/dynamips
|
||||
wget 'https://github.com/GNS3/iouyap/releases/download/0.95/iouyap-64-bit.tar.gz'
|
||||
tar xzf iouyap-64-bit.tar.gz -C /usr/local/bin
|
||||
python -c 'import struct; open("/etc/hostid", "w").write(struct.pack("i", 00000000))'
|
||||
hostname gns3-iouvm # set hostname for iou
|
||||
wget -O vpcs http://sourceforge.net/projects/vpcs/files/0.6/vpcs_0.6_Linux64/download
|
||||
cp vpcs /usr/local/bin/vpcs
|
||||
chmod a+x /usr/local/bin/vpcs
|
||||
killall python3 gns3server gns3dms
|
||||
'''
|
||||
|
||||
def __init__(self, parent, host, private_key_string, server_id, username, api_key, region, dead_time):
|
||||
super().__init__(parent)
|
||||
self._host = host
|
||||
self._private_key_string = private_key_string
|
||||
self._server_id = server_id
|
||||
self._username = username
|
||||
self._api_key = api_key
|
||||
self._region = region
|
||||
self._dead_time = dead_time
|
||||
|
||||
def exec_command(self, client, cmd, wait_time=-1):
|
||||
|
||||
cmd += '; exit $?'
|
||||
|
||||
stdout_data = b''
|
||||
stderr_data = b''
|
||||
|
||||
log.debug('cmd: {}'.format(cmd))
|
||||
# Send the command (non-blocking)
|
||||
stdin, stdout, stderr = client.exec_command(cmd)
|
||||
|
||||
# Wait for the command to terminate
|
||||
wait = int(wait_time)
|
||||
while not stdout.channel.exit_status_ready() and wait != 0:
|
||||
time.sleep(1)
|
||||
wait -= 1
|
||||
|
||||
stdout_data = stdout.read()
|
||||
stderr_data = stderr.read()
|
||||
log.debug('exit status: {}'.format(stdout.channel.exit_status))
|
||||
log.debug('stdout: {}'.format(stdout_data.decode('utf-8')))
|
||||
log.debug('stderr: {}'.format(stderr_data.decode('utf-8')))
|
||||
return stdout_data, stderr_data
|
||||
|
||||
def run(self):
|
||||
# We might be attempting a connection before the instance is fully booted, so retry
|
||||
# when the ssh connection fails.
|
||||
ssh_connected = False
|
||||
while not ssh_connected:
|
||||
with ssh_client(self._host, self._private_key_string) as client:
|
||||
if client is None:
|
||||
time.sleep(1)
|
||||
continue
|
||||
ssh_connected = True
|
||||
|
||||
# This is for testing without pushing to github
|
||||
# os.system('rm -rf /tmp/gns3-server')
|
||||
# os.system('cp -a /Users/jseutter/projects/gns3-server /tmp/gns3-server')
|
||||
# os.system('cd /tmp; tar czf /tmp/gns3-server.tgz gns3-server')
|
||||
# sftp = client.open_sftp()
|
||||
# sftp.put('/tmp/gns3-server.tgz', '/tmp/gns3-server.tgz')
|
||||
# sftp.close()
|
||||
|
||||
for cmd in [l for l in self.commands.splitlines() if l.strip()]:
|
||||
self.exec_command(client, cmd)
|
||||
|
||||
data = {
|
||||
'instance_id': self._server_id,
|
||||
'cloud_user_name': self._username,
|
||||
'cloud_api_key': self._api_key,
|
||||
'cloud_region': self._region,
|
||||
'dead_time': self._dead_time,
|
||||
}
|
||||
# TODO: Properly escape the data portion of the command line
|
||||
start_cmd = '/usr/bin/python3 /opt/gns3/gns3-server/gns3server/start_server.py -d -v --ip={} --data="{}" 2>/tmp/gns3-stderr.log'.format(self._host, data)
|
||||
stdout, stderr = self.exec_command(client, start_cmd, wait_time=15)
|
||||
response = stdout.decode('utf-8')
|
||||
self.gns3server_started.emit(str(self._server_id), str(self._host), str(response))
|
||||
|
||||
|
||||
class WSConnectThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Establish a websocket connection with the remote gns3server
|
||||
instance. Run outside the GUI event loop.
|
||||
"""
|
||||
established = QtCore.pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent, provider, server_id, host, port, ca_file,
|
||||
auth_user, auth_password, ssh_pkey, instance_id):
|
||||
super().__init__(parent)
|
||||
self._provider = provider
|
||||
self._server_id = server_id
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._ca_file = ca_file
|
||||
self._auth_user = auth_user
|
||||
self._auth_password = auth_password
|
||||
self._ssh_pkey = ssh_pkey
|
||||
self._instance_id = instance_id
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Establish a websocket connection to gns3server on the cloud instance.
|
||||
"""
|
||||
|
||||
log.debug('WSConnectThread.run() begin')
|
||||
servers = Servers.instance()
|
||||
server = servers.getCloudServer(self._host, self._port, self._ca_file,
|
||||
self._auth_user, self._auth_password, self._ssh_pkey,
|
||||
self._instance_id)
|
||||
log.debug('after getCloudServer call. {}'.format(server))
|
||||
self.established.emit(str(self._server_id))
|
||||
|
||||
log.debug('WSConnectThread.run() end')
|
||||
# emit signal on success
|
||||
self.established.emit(self._server_id)
|
||||
|
||||
|
||||
class UploadProjectThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Zip and Upload project to the cloud
|
||||
"""
|
||||
|
||||
# signals to update the progress dialog.
|
||||
error = QtCore.pyqtSignal(str, bool)
|
||||
completed = QtCore.pyqtSignal()
|
||||
update = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent, cloud_settings, project_path, images_path):
|
||||
super().__init__(parent)
|
||||
self.cloud_settings = cloud_settings
|
||||
self.project_path = project_path
|
||||
self.images_path = images_path
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
log.info("Exporting project to cloud")
|
||||
self.update.emit(0)
|
||||
|
||||
zipped_project_file = self.zip_project_dir()
|
||||
|
||||
self.update.emit(10) # update progress to 10%
|
||||
|
||||
provider = get_provider(self.cloud_settings)
|
||||
provider.upload_file(zipped_project_file, 'projects/' + os.path.basename(zipped_project_file))
|
||||
|
||||
self.update.emit(20) # update progress to 20%
|
||||
|
||||
topology = Topology.instance()
|
||||
images = set([node.settings()["image"] for node in topology.nodes() if 'image' in node.settings()])
|
||||
|
||||
for i, image in enumerate(images):
|
||||
provider.upload_file(image, 'images/' + os.path.relpath(image, self.images_path))
|
||||
self.update.emit(20 + (float(i) / len(images) * 80))
|
||||
|
||||
self.completed.emit()
|
||||
except Exception as e:
|
||||
log.exception("Error exporting project to cloud")
|
||||
self.error.emit("Error exporting project: {}".format(e), True)
|
||||
|
||||
def zip_project_dir(self):
|
||||
"""
|
||||
Zips project files
|
||||
:return: path to zipped project file
|
||||
"""
|
||||
project_name = os.path.basename(self.project_path)
|
||||
output_filename = os.path.join(tempfile.gettempdir(), project_name + ".zip")
|
||||
project_dir = os.path.dirname(self.project_path)
|
||||
relroot = os.path.abspath(os.path.join(project_dir, os.pardir))
|
||||
with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip_file:
|
||||
for root, dirs, files in os.walk(project_dir):
|
||||
# add directory (needed for empty dirs)
|
||||
zip_file.write(root, os.path.relpath(root, relroot))
|
||||
for file in files:
|
||||
filename = os.path.join(root, file)
|
||||
if os.path.isfile(filename) and not self._should_exclude(filename): # regular files only
|
||||
arcname = os.path.join(os.path.relpath(root, relroot), file)
|
||||
zip_file.write(filename, arcname)
|
||||
|
||||
return output_filename
|
||||
|
||||
def _should_exclude(self, filename):
|
||||
"""
|
||||
Returns True if file should be excluded from zip of project files
|
||||
:param filename:
|
||||
:return: True if file should be excluded from zip, False otherwise
|
||||
"""
|
||||
return filename.endswith('.ghost')
|
||||
|
||||
def stop(self):
|
||||
self.quit()
|
||||
|
||||
|
||||
class UploadFilesThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Uploads files to cloud files
|
||||
|
||||
:param cloud_settings:
|
||||
:param files_to_upload: list of tuples of (file path, file name to save in cloud)
|
||||
"""
|
||||
|
||||
error = QtCore.pyqtSignal(str, bool)
|
||||
completed = QtCore.pyqtSignal()
|
||||
update = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent, cloud_settings, files_to_upload):
|
||||
super().__init__(parent)
|
||||
self._cloud_settings = cloud_settings
|
||||
self._files_to_upload = files_to_upload
|
||||
|
||||
def run(self):
|
||||
self.update.emit(0)
|
||||
|
||||
try:
|
||||
for i, file_to_upload in enumerate(self._files_to_upload):
|
||||
provider = get_provider(self._cloud_settings)
|
||||
|
||||
log.debug('Uploading image {} to cloud as {}'.format(file_to_upload[0], file_to_upload[1]))
|
||||
provider.upload_file(file_to_upload[0], file_to_upload[1])
|
||||
|
||||
self.update.emit((i + 1) * 100 / len(self._files_to_upload))
|
||||
log.debug('Uploading image completed')
|
||||
except Exception as e:
|
||||
log.exception("Error uploading images to cloud")
|
||||
self.error.emit("Error uploading images: {}".format(e), True)
|
||||
|
||||
self.completed.emit()
|
||||
|
||||
def stop(self):
|
||||
self.quit()
|
||||
|
||||
|
||||
class DownloadProjectThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Downloads project from cloud storage
|
||||
"""
|
||||
|
||||
# signals to update the progress dialog.
|
||||
error = QtCore.pyqtSignal(str, bool)
|
||||
completed = QtCore.pyqtSignal()
|
||||
update = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent, cloud_project_file_name, project_dest_path, images_dest_path, cloud_settings):
|
||||
super().__init__(parent)
|
||||
self.project_name = cloud_project_file_name
|
||||
self.project_dest_path = project_dest_path
|
||||
self.images_dest_path = images_dest_path
|
||||
self.cloud_settings = cloud_settings
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.update.emit(0)
|
||||
provider = get_provider(self.cloud_settings)
|
||||
zip_file = provider.download_file(self.project_name)
|
||||
zip_file = zipfile.ZipFile(zip_file, mode='r')
|
||||
zip_file.extractall(self.project_dest_path)
|
||||
zip_file.close()
|
||||
project_name = zip_file.namelist()[0].strip('/')
|
||||
|
||||
self.update.emit(20)
|
||||
|
||||
with open(os.path.join(self.project_dest_path, project_name, project_name + '.gns3'), 'r') as f:
|
||||
project_settings = json.loads(f.read())
|
||||
|
||||
images = set()
|
||||
for node in project_settings["topology"].get("nodes", []):
|
||||
if "properties" in node and "image" in node["properties"]:
|
||||
images.add(node["properties"]["image"])
|
||||
|
||||
image_names_in_cloud = provider.find_storage_image_names(images)
|
||||
|
||||
for i, image in enumerate(images):
|
||||
dest_path = os.path.join(self.images_dest_path, *image_names_in_cloud[image].split('/')[1:])
|
||||
|
||||
if not os.path.exists(os.path.dirname(dest_path)):
|
||||
os.makedirs(os.path.dirname(dest_path))
|
||||
|
||||
provider.download_file(image_names_in_cloud[image], dest_path)
|
||||
self.update.emit(20 + (float(i) / len(images) * 80))
|
||||
|
||||
self.completed.emit()
|
||||
except Exception as e:
|
||||
log.exception("Error importing project from cloud")
|
||||
self.error.emit("Error importing project: {}".format(e), True)
|
||||
|
||||
def stop(self):
|
||||
self.quit()
|
||||
|
||||
|
||||
class DownloadImagesThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Downloads multiple files from cloud files
|
||||
"""
|
||||
|
||||
error = QtCore.pyqtSignal(str, bool)
|
||||
completed = QtCore.pyqtSignal()
|
||||
update = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, cloud_settings, images_dest_path, image_names):
|
||||
super().__init__()
|
||||
self._cloud_settings = cloud_settings
|
||||
self._images_dest_path = images_dest_path
|
||||
self._image_names = image_names
|
||||
|
||||
def run(self):
|
||||
self.update.emit(0)
|
||||
try:
|
||||
provider = get_provider(self._cloud_settings)
|
||||
image_names_in_cloud = provider.find_storage_image_names(self._image_names)
|
||||
|
||||
for i, image in enumerate(self._image_names):
|
||||
dest_path = os.path.join(self._images_dest_path, *image_names_in_cloud[image].split('/')[1:])
|
||||
|
||||
if not os.path.exists(os.path.dirname(dest_path)):
|
||||
os.makedirs(os.path.dirname(dest_path))
|
||||
|
||||
provider.download_file(image_names_in_cloud[image], dest_path)
|
||||
|
||||
self.update.emit(i * 100 / len(self._image_names))
|
||||
|
||||
self.completed.emit()
|
||||
except Exception as e:
|
||||
log.exception("Error importing project from cloud")
|
||||
self.error.emit("Error importing project: {}".format(e), True)
|
||||
|
||||
def stop(self):
|
||||
self.quit()
|
||||
|
||||
|
||||
class DeleteProjectThread(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Deletes project from cloud storage
|
||||
"""
|
||||
|
||||
# signals to update the progress dialog.
|
||||
error = QtCore.pyqtSignal(str, bool)
|
||||
completed = QtCore.pyqtSignal()
|
||||
update = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent, project_file_name, cloud_settings):
|
||||
super().__init__(parent)
|
||||
self.project_file_name = project_file_name
|
||||
self.cloud_settings = cloud_settings
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
provider = get_provider(self.cloud_settings)
|
||||
provider.delete_file(self.project_file_name)
|
||||
self.completed.emit()
|
||||
except Exception as e:
|
||||
log.exception("Error deleting project")
|
||||
self.error.emit("Error deleting project: {}".format(e), True)
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_cloud_projects(cloud_settings):
|
||||
provider = get_provider(cloud_settings)
|
||||
return provider.list_projects()
|
||||
@@ -1,252 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
"""
|
||||
|
||||
from PyQt4.QtCore import pyqtSignal
|
||||
from PyQt4.QtCore import QThread
|
||||
|
||||
import ast
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from .cloud.utils import ssh_client
|
||||
from .cloud.exceptions import KeyPairExists
|
||||
|
||||
from .servers import Servers
|
||||
from .topology import Topology
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CloudBuilder(QThread):
|
||||
|
||||
"""
|
||||
"""
|
||||
# Notify with progress amount and instance_id
|
||||
progressUpdate = pyqtSignal(object, str)
|
||||
|
||||
# Notify with current state and instance_id
|
||||
stateChange = pyqtSignal(object, str)
|
||||
|
||||
# Notify when instance is ready with instance_id
|
||||
buildComplete = pyqtSignal(str)
|
||||
|
||||
# Notify when the instance has been created with instance and keypair
|
||||
instanceCreated = pyqtSignal(object, object)
|
||||
|
||||
# Notify when the public ip is available with ip and instance_id
|
||||
instanceHasIP = pyqtSignal(str, str)
|
||||
|
||||
# Notify when instance id exists with builder and instance_id
|
||||
instanceIdExists = pyqtSignal(object, str)
|
||||
|
||||
def __init__(self, parent, cloud_provider, ca_dir):
|
||||
super(QThread, self).__init__(parent)
|
||||
# Store our parent so it can be passed to threads we spawn.
|
||||
self._parent = parent
|
||||
self._provider = cloud_provider
|
||||
self._ca_dir = ca_dir
|
||||
self._start_at_create = False
|
||||
self._start_at_setup = False
|
||||
self._instance = None
|
||||
|
||||
def startAtCreate(self, instance_name, flavor_id, image_id):
|
||||
self._start_at_create = True
|
||||
self._instance_name = instance_name
|
||||
self._flavor_id = flavor_id
|
||||
self._image_id = image_id
|
||||
|
||||
def startAtSetup(self, instance, keypair):
|
||||
self._start_at_setup = True
|
||||
self._instance = instance
|
||||
self._key_pair = keypair
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
log.debug('CloudBuilder.run')
|
||||
if self._start_at_create:
|
||||
log.debug('CloudBuilder._start_at_create')
|
||||
self._createInstance(self._provider, self._instance_name, self._flavor_id,
|
||||
self._image_id)
|
||||
log.debug('got here 3')
|
||||
if self._start_at_setup:
|
||||
log.debug('CloudBuilder start at setup')
|
||||
self._instanceCreated(self._instance, self._key_pair)
|
||||
except Exception:
|
||||
log.exception("CloudBuilder trapped an exception:")
|
||||
log.error('CloudBuilder stopped in error state.')
|
||||
|
||||
def _createInstance(self, provider, name, flavor_id, image_id):
|
||||
log.debug("Creating cloud keypair with name {}".format(name))
|
||||
key_pair = None
|
||||
while key_pair is None:
|
||||
try:
|
||||
key_pair = provider.create_key_pair(name)
|
||||
except KeyPairExists:
|
||||
log.debug("Deleting old key pair with name {}.".format(name))
|
||||
self._provider.delete_key_pair_by_name(name)
|
||||
except Exception as e:
|
||||
log.debug("create_key_pair exception {}".format(e))
|
||||
|
||||
log.debug("Creating cloud server with name {}".format(name))
|
||||
instance = None
|
||||
while instance is None:
|
||||
try:
|
||||
instance = self._provider.create_instance(name, flavor_id, image_id, key_pair)
|
||||
except Exception as e:
|
||||
log.debug("create_instance exception {}".format(e))
|
||||
log.debug("Cloud server {} created".format(name))
|
||||
self._instanceCreated(instance, key_pair)
|
||||
|
||||
def _instanceCreated(self, instance, key_pair):
|
||||
log.debug('CloudBuilder._instanceCreated {}'.format(instance.id))
|
||||
self._instance = instance
|
||||
self._instance_id = instance.id
|
||||
self._key_pair = key_pair
|
||||
self.instanceIdExists.emit(self, instance.id)
|
||||
self.instanceCreated.emit(instance, key_pair)
|
||||
self._waitForPublicIP()
|
||||
|
||||
def _waitForPublicIP(self):
|
||||
public_ip = None
|
||||
while public_ip is None:
|
||||
time.sleep(10)
|
||||
try:
|
||||
instance = self._provider.get_instance(self._instance)
|
||||
# Look for public ip address
|
||||
for ip in instance.public_ips:
|
||||
# Don't use the ipv6 address
|
||||
if ':' not in ip:
|
||||
public_ip = ip
|
||||
break
|
||||
except Exception as e:
|
||||
log.debug('list_instances error: {}'.format(e))
|
||||
|
||||
# updated info, keep it.
|
||||
self._instance = instance
|
||||
self._public_ip = public_ip
|
||||
self.instanceHasIP.emit(self._public_ip, self._instance.id)
|
||||
time.sleep(60)
|
||||
self._startGNS3Server(1800)
|
||||
|
||||
def _startGNS3Server(self, dead_time):
|
||||
commands = '''
|
||||
DEBIAN_FRONTEND=noninteractive dpkg --configure -a
|
||||
DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy dist-upgrade
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y install git python3-setuptools python3-netifaces python3-pip python3-zmq dynamips qemu-system
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y install libc6:i386 libstdc++6:i386 libssl1.0.0:i386
|
||||
ln -s /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.4
|
||||
mkdir -p /opt/gns3
|
||||
cd /opt/gns3; git clone https://github.com/planctechnologies/gns3-server.git
|
||||
cd /opt/gns3/gns3-server; git checkout dev; git pull
|
||||
cd /opt/gns3/gns3-server; pip3 install -r dev-requirements.txt
|
||||
cd /opt/gns3/gns3-server; python3 ./setup.py install
|
||||
ln -sf /usr/bin/dynamips /usr/local/bin/dynamips
|
||||
wget 'https://github.com/GNS3/iouyap/releases/download/0.95/iouyap.tar.gz'
|
||||
tar xzf iouyap.tar.gz -C /usr/local/bin
|
||||
python -c 'import struct; open("/etc/hostid", "w").write(struct.pack("i", 00000000))'
|
||||
hostname gns3-iouvm # set hostname for iou
|
||||
wget 'http://downloads.sourceforge.net/project/vpcs/0.6/vpcs_0.6_Linux64'
|
||||
cp vpcs_0.6_Linux64 /usr/local/bin/vpcs
|
||||
chmod a+x /usr/local/bin/vpcs
|
||||
killall python3 gns3server gns3dms
|
||||
'''
|
||||
|
||||
def exec_command(client, cmd, wait_time=-1):
|
||||
|
||||
cmd += '; exit $?'
|
||||
|
||||
stdout_data = b''
|
||||
stderr_data = b''
|
||||
|
||||
log.debug('cmd: {}'.format(cmd))
|
||||
# Send the command (non-blocking)
|
||||
stdin, stdout, stderr = client.exec_command(cmd)
|
||||
|
||||
# Wait for the command to terminate
|
||||
wait = int(wait_time)
|
||||
while not stdout.channel.exit_status_ready() and wait != 0:
|
||||
time.sleep(1)
|
||||
wait -= 1
|
||||
|
||||
stdout_data = stdout.read()
|
||||
stderr_data = stderr.read()
|
||||
log.debug('exit status: {}'.format(stdout.channel.exit_status))
|
||||
log.debug('stdout: {}'.format(stdout_data.decode('utf-8')))
|
||||
log.debug('stderr: {}'.format(stderr_data.decode('utf-8')))
|
||||
return stdout_data, stderr_data
|
||||
|
||||
# We might be attempting a connection before the instance is fully booted, so retry
|
||||
# when the ssh connection fails.
|
||||
ssh_connected = False
|
||||
response = None
|
||||
while not ssh_connected:
|
||||
with ssh_client(self._public_ip, self._key_pair.private_key) as client:
|
||||
if client is None:
|
||||
time.sleep(1)
|
||||
continue
|
||||
ssh_connected = True
|
||||
|
||||
for cmd in [l for l in commands.splitlines() if l.strip()]:
|
||||
exec_command(client, cmd)
|
||||
|
||||
data = {
|
||||
'instance_id': self._instance_id,
|
||||
'cloud_user_name': self._provider.username,
|
||||
'cloud_api_key': self._provider.api_key,
|
||||
'cloud_region': self._provider.region,
|
||||
'dead_time': dead_time,
|
||||
}
|
||||
# TODO: Properly escape the data portion of the command line
|
||||
start_cmd = '/usr/bin/python3 /opt/gns3/gns3-server/gns3server/start_server.py -d -v --ip={} --data="{}" 2>/tmp/gns3-stderr.log'.format(self._public_ip, data)
|
||||
stdout, stderr = exec_command(client, start_cmd, wait_time=15)
|
||||
response = stdout.decode('utf-8')
|
||||
|
||||
log.debug(response)
|
||||
data = ast.literal_eval(response)
|
||||
# TODO: have the server return the port it is running on
|
||||
port = 8000
|
||||
|
||||
username = data['WEB_USERNAME']
|
||||
password = data['WEB_PASSWORD']
|
||||
|
||||
ssl_cert = ''.join(data['SSL_CRT'])
|
||||
ca_filename = 'cloud_server_{}.crt'.format(self._public_ip)
|
||||
ca_dir = self._ca_dir
|
||||
ca_file = os.path.join(ca_dir, ca_filename)
|
||||
try:
|
||||
os.makedirs(ca_dir)
|
||||
except FileExistsError:
|
||||
pass
|
||||
with open(ca_file, 'wb') as ca_fh:
|
||||
ca_fh.write(ssl_cert.encode('utf-8'))
|
||||
|
||||
topology = Topology.instance()
|
||||
top_instance = topology.getInstance(self._instance_id)
|
||||
top_instance.set_later_attributes(self._public_ip, port, ssl_cert, ca_file)
|
||||
|
||||
servers = Servers.instance()
|
||||
server = servers.getCloudServer(self._public_ip, port, ca_file, username, password,
|
||||
self._key_pair.private_key, self._instance_id)
|
||||
servers.save()
|
||||
log.debug('Cloud server gns3server started.')
|
||||
self.buildComplete.emit(self._instance_id)
|
||||
@@ -1,427 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from collections import namedtuple
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
|
||||
from libcloud.compute.types import NodeState
|
||||
|
||||
from .qt import QtCore, QtGui
|
||||
from .cloud.utils import (ListInstancesThread, DeleteInstanceThread)
|
||||
from .topology import Topology
|
||||
from .servers import Servers
|
||||
|
||||
|
||||
# this widget was promoted on Creator, must use absolute imports
|
||||
from gns3.ui.cloud_inspector_view_ui import Ui_CloudInspectorView
|
||||
from gns3.cloud_builder import CloudBuilder
|
||||
from gns3.cloud_instances import CloudInstances
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
POLLING_TIMER = 10000 # in milliseconds
|
||||
|
||||
|
||||
class RunningInstanceState(NodeState):
|
||||
|
||||
"""
|
||||
GNS3 states for running instances
|
||||
"""
|
||||
GNS3SERVER_STARTING = -1
|
||||
GNS3SERVER_STARTED = -2
|
||||
WS_CONNECTED = -3
|
||||
|
||||
|
||||
class InstanceTableModel(QtCore.QAbstractTableModel):
|
||||
|
||||
"""
|
||||
A custom table model storing data of cloud instances
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InstanceTableModel, self).__init__(*args, **kwargs)
|
||||
self._header_data = ['Instance', '', 'Size', 'Devices'] # status has an empty header label
|
||||
self._width = len(self._header_data)
|
||||
self._instances = {}
|
||||
self._ids = []
|
||||
self.flavors = {}
|
||||
|
||||
@property
|
||||
def instanceIds(self):
|
||||
return self._ids
|
||||
|
||||
def clear(self):
|
||||
self._instances = {}
|
||||
self._ids = []
|
||||
self.reset()
|
||||
|
||||
def _get_status_icon_path(self, instance):
|
||||
"""
|
||||
Return a string pointing to the graphic resource
|
||||
"""
|
||||
if instance.state == RunningInstanceState.WS_CONNECTED:
|
||||
return ':/icons/led_green.svg'
|
||||
elif instance.state in (RunningInstanceState.STOPPED,
|
||||
RunningInstanceState.TERMINATED,
|
||||
RunningInstanceState.UNKNOWN):
|
||||
return ':/icons/led_red.svg'
|
||||
else:
|
||||
return ':/icons/led_yellow.svg'
|
||||
|
||||
def rowCount(self, QModelIndex_parent=None, *args, **kwargs):
|
||||
return len(self._instances)
|
||||
|
||||
def columnCount(self, QModelIndex_parent=None, *args, **kwargs):
|
||||
return self._width if len(self._instances) else 0
|
||||
|
||||
def data(self, index, role=None):
|
||||
instance = self._instances.get(self._ids[index.row()])
|
||||
col = index.column()
|
||||
|
||||
if role == QtCore.Qt.DecorationRole:
|
||||
if col == 1:
|
||||
# status
|
||||
return QtGui.QIcon(self._get_status_icon_path(instance))
|
||||
|
||||
elif role == QtCore.Qt.DisplayRole:
|
||||
if col == 0:
|
||||
# name
|
||||
return instance.name
|
||||
elif col == 2:
|
||||
# size
|
||||
try:
|
||||
# for Rackspace instances, update flavor id with a verbose description
|
||||
return self.flavors.get(instance.extra['flavorId'])
|
||||
except KeyError:
|
||||
# fallback to libcloud size property
|
||||
if instance.size:
|
||||
return instance.size.ram
|
||||
# giveup on showing size
|
||||
return 'Unknown'
|
||||
elif col == 3:
|
||||
# devices
|
||||
count = 0
|
||||
topology = Topology.instance()
|
||||
for node in topology.nodes():
|
||||
id = node._server.instance_id or 0
|
||||
if instance.id == id:
|
||||
count += 1
|
||||
return count
|
||||
return None
|
||||
|
||||
def headerData(self, section, orientation, role=None):
|
||||
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
|
||||
try:
|
||||
return self._header_data[section]
|
||||
except IndexError:
|
||||
return None
|
||||
return super(InstanceTableModel, self).headerData(section, orientation, role)
|
||||
|
||||
def addInstance(self, instance):
|
||||
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
|
||||
if not len(self._instances):
|
||||
self.beginInsertColumns(QtCore.QModelIndex(), 0, self._width - 1)
|
||||
self.endInsertColumns()
|
||||
self._ids.append(instance.id)
|
||||
self._instances[instance.id] = instance
|
||||
self.endInsertRows()
|
||||
|
||||
def getInstance(self, index):
|
||||
"""
|
||||
Retrieve the i-th instance if index is in range
|
||||
"""
|
||||
try:
|
||||
return self._instances.get(self._ids[index])
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def removeInstance(self, instance):
|
||||
self.removeInstanceById(instance.id)
|
||||
|
||||
def removeInstanceById(self, instance_id):
|
||||
try:
|
||||
index = self._ids.index(instance_id)
|
||||
self.beginRemoveRows(QtCore.QModelIndex(), index, index)
|
||||
del self._instances[instance_id]
|
||||
del self._ids[index]
|
||||
self.endRemoveRows()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def updateInstanceFields(self, instance, field_names):
|
||||
"""
|
||||
Update model data and notify connected views
|
||||
"""
|
||||
if instance.id in self._ids:
|
||||
index = self._ids.index(instance.id)
|
||||
current = self._instances[instance.id]
|
||||
for field in field_names:
|
||||
setattr(current, field, getattr(instance, field))
|
||||
first_index = self.createIndex(index, 0)
|
||||
last_index = self.createIndex(index, self.columnCount() - 1)
|
||||
self.dataChanged.emit(first_index, last_index)
|
||||
else:
|
||||
self.addInstance(instance)
|
||||
|
||||
def getInstanceById(self, instance_id):
|
||||
return self._instances.get(instance_id, None)
|
||||
|
||||
|
||||
class CloudInspectorView(QtGui.QWidget, Ui_CloudInspectorView):
|
||||
|
||||
"""
|
||||
Table view showing data coming from InstanceTableModel
|
||||
|
||||
Signals:
|
||||
instanceSelected(int) Emitted when users click and select an instance on the inspector.
|
||||
Param int is the ID of the instance
|
||||
"""
|
||||
instanceSelected = QtCore.pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent):
|
||||
super(QtGui.QWidget, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._provider = None
|
||||
self._settings = None
|
||||
self._project_instances_id = []
|
||||
self._main_window = None
|
||||
|
||||
self._model = InstanceTableModel() # shortcut for self.uiInstancesTableView.model()
|
||||
self.uiInstancesTableView.setModel(self._model)
|
||||
self.uiInstancesTableView.verticalHeader().hide()
|
||||
self.uiInstancesTableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.uiInstancesTableView.horizontalHeader().setStretchLastSection(True)
|
||||
# connections
|
||||
self.uiInstancesTableView.customContextMenuRequested.connect(self._contextMenu)
|
||||
self.uiInstancesTableView.clicked.connect(self._rowChanged)
|
||||
self.uiCreateInstanceButton.clicked.connect(self._create_new_instance)
|
||||
|
||||
self._pollingTimer = QtCore.QTimer(self)
|
||||
self._pollingTimer.timeout.connect(self._polling_slot)
|
||||
|
||||
# map flavor ids to combobox indexes
|
||||
self.flavor_index_id = []
|
||||
|
||||
# A dictionary of {image_id, CloudBuilder}
|
||||
self._builders = {}
|
||||
|
||||
def _get_flavor_index(self, flavor_id):
|
||||
try:
|
||||
return self.flavor_index_id.index(flavor_id)
|
||||
except ValueError:
|
||||
return -1
|
||||
|
||||
def load(self, main_win, instance_ids):
|
||||
"""
|
||||
Fill the model data layer with instance info loaded from the topology file
|
||||
"""
|
||||
self._main_window = main_win
|
||||
self._provider = main_win.cloudProvider
|
||||
self._settings = main_win.cloudSettings()
|
||||
log.info('CloudInspectorView.load')
|
||||
|
||||
for instance_id in instance_ids:
|
||||
self._project_instances_id.append(instance_id)
|
||||
|
||||
update_thread = ListInstancesThread(self, self._provider)
|
||||
update_thread.instancesReady.connect(self._update_model)
|
||||
update_thread.start()
|
||||
self._pollingTimer.start(POLLING_TIMER)
|
||||
# fill sizes comboboxes
|
||||
for id, name in self._provider.list_flavors().items():
|
||||
self.uiCreateInstanceComboBox.addItem(name)
|
||||
self.flavor_index_id.append(id)
|
||||
# select default flavor
|
||||
new_instance_flavor = self._settings["new_instance_flavor"]
|
||||
self.uiCreateInstanceComboBox.setCurrentIndex(self._get_flavor_index(new_instance_flavor))
|
||||
|
||||
def addInstance(self, instance):
|
||||
"""
|
||||
Add a new instance to the inspector
|
||||
"""
|
||||
self._project_instances_id.append(instance.id)
|
||||
|
||||
def clear(self):
|
||||
"""
|
||||
Clear contents and stop polling timer
|
||||
"""
|
||||
self._model.clear()
|
||||
self._pollingTimer.stop()
|
||||
self._project_instances_id = []
|
||||
|
||||
def _contextMenu(self, pos):
|
||||
# create actions
|
||||
delete_action = QtGui.QAction("Delete", self)
|
||||
delete_action.triggered.connect(self._deleteSelectedInstance)
|
||||
# create context menu and add actions
|
||||
menu = QtGui.QMenu(self.uiInstancesTableView)
|
||||
menu.addAction(delete_action)
|
||||
# show the menu
|
||||
menu.popup(self.uiInstancesTableView.viewport().mapToGlobal(pos))
|
||||
|
||||
def _deleteSelectedInstance(self):
|
||||
"""
|
||||
Delete the instance corresponding to the selected table row
|
||||
"""
|
||||
sel = self.uiInstancesTableView.selectedIndexes()
|
||||
if len(sel) and self._provider is not None:
|
||||
index = sel[0].row()
|
||||
instance = self._model.getInstance(index)
|
||||
|
||||
# warn user this is destructive
|
||||
msg = "Do you want to remove the instance and any devices running on it?"
|
||||
proceed = QtGui.QMessageBox.question(self, 'Warning', msg,
|
||||
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||
|
||||
if proceed == QtGui.QMessageBox.Yes:
|
||||
# disconnect and remove the server
|
||||
servers = Servers.instance()
|
||||
cs = servers.cloudServerById(instance.id)
|
||||
if cs is not None:
|
||||
servers.removeCloudServer(cs)
|
||||
|
||||
# remove instance from the the topology
|
||||
topology = Topology.instance()
|
||||
topology.removeInstance(instance.id)
|
||||
|
||||
delete_thread = DeleteInstanceThread(self, self._provider, instance)
|
||||
delete_thread.instanceDeleted.connect(self._main_window.remove_instance_from_project)
|
||||
delete_thread.start()
|
||||
|
||||
instance.name = 'Deleting...'
|
||||
self._model.updateInstanceFields(instance, ['name'])
|
||||
|
||||
def _rowChanged(self, index):
|
||||
"""
|
||||
This slot is invoked every time users change the current selected row on the
|
||||
inspector
|
||||
"""
|
||||
selection = self.uiInstancesTableView.selectionModel().selection()
|
||||
if selection.isEmpty():
|
||||
return
|
||||
|
||||
item = selection.indexes()[0]
|
||||
if item.isValid():
|
||||
instance = self._model.getInstance(item.row())
|
||||
self.instanceSelected.emit(instance.id)
|
||||
|
||||
def _polling_slot(self):
|
||||
"""
|
||||
Sync model data with instances status
|
||||
"""
|
||||
if self._provider is None:
|
||||
return
|
||||
|
||||
update_thread = ListInstancesThread(self, self._provider)
|
||||
update_thread.instancesReady.connect(self._update_model)
|
||||
update_thread.start()
|
||||
|
||||
def _instanceBuilt(self, id):
|
||||
"""
|
||||
This slot is called when instance has finished building.
|
||||
"""
|
||||
instance = self._model.getInstanceById(id)
|
||||
instance.state = RunningInstanceState.WS_CONNECTED
|
||||
self._model.updateInstanceFields(instance, ['state'])
|
||||
|
||||
if self._main_window.loading_cloud_project:
|
||||
project = self._main_window.project()
|
||||
path = project.topologyPath()
|
||||
with open(path, "r") as f:
|
||||
json_topology = json.load(f)
|
||||
topology = Topology.instance()
|
||||
topology.load(json_topology)
|
||||
self._main_window.loading_cloud_project = False
|
||||
|
||||
def _update_model(self, instances):
|
||||
if not instances:
|
||||
return
|
||||
|
||||
# Filter instances to only those in the current project
|
||||
project_instances = [i for i in instances if i.id in self._project_instances_id]
|
||||
|
||||
# populate underlying model if this is the first call
|
||||
if self._model.rowCount() == 0 and len(project_instances) > 0:
|
||||
self._populate_model(project_instances)
|
||||
self._rebuild_instances(project_instances)
|
||||
|
||||
instance_manager = CloudInstances.instance()
|
||||
instance_manager.update_instances(instances)
|
||||
|
||||
# Clean up removed instances
|
||||
real = set(i.id for i in project_instances)
|
||||
current = set(self._model.instanceIds)
|
||||
for i in current.difference(real):
|
||||
self._model.removeInstanceById(i)
|
||||
self.uiInstancesTableView.resizeColumnsToContents()
|
||||
|
||||
# Update instance status
|
||||
for i in project_instances:
|
||||
# get the customized instance state from self._model
|
||||
model_instance = self._model.getInstanceById(i.id)
|
||||
|
||||
# update model instance state if needed
|
||||
if i.state != RunningInstanceState.RUNNING:
|
||||
self._model.updateInstanceFields(i, ['state'])
|
||||
|
||||
def _populate_model(self, instances):
|
||||
log.info('CloudInspectorView._populate_model')
|
||||
self._model.flavors = self._provider.list_flavors()
|
||||
# filter instances for current project
|
||||
for inst in instances:
|
||||
self._model.addInstance(inst)
|
||||
self.uiInstancesTableView.resizeColumnsToContents()
|
||||
|
||||
def _create_new_instance(self):
|
||||
idx = self.uiCreateInstanceComboBox.currentIndex()
|
||||
flavor_id = self.flavor_index_id[idx]
|
||||
image_id = self._settings['default_image']
|
||||
|
||||
name, ok = QtGui.QInputDialog.getText(self,
|
||||
"New instance",
|
||||
"Choose a name for the instance and press Ok,\n"
|
||||
"then wait for the instance to appear in the inspector.")
|
||||
|
||||
if ok:
|
||||
self.createInstance(name, flavor_id, image_id)
|
||||
|
||||
def createInstance(self, instance_name, flavor_id, image_id):
|
||||
if not instance_name.endswith("-gns3"):
|
||||
instance_name += "-gns3"
|
||||
# TODO: Add a keys_dir to projectSettings
|
||||
ca_dir = os.path.join(self._main_window.projectSettings()["project_files_dir"], "keys")
|
||||
|
||||
builder = CloudBuilder(self, self._provider, ca_dir)
|
||||
builder.startAtCreate(instance_name, flavor_id, image_id)
|
||||
builder.instanceCreated.connect(self._main_window.add_instance_to_project)
|
||||
builder.instanceCreated.connect(CloudInstances.instance().add_instance)
|
||||
builder.instanceIdExists.connect(self._associateBuilderWithInstance)
|
||||
builder.instanceHasIP.connect(CloudInstances.instance().update_host_for_instance)
|
||||
builder.buildComplete.connect(self._instanceBuilt)
|
||||
builder.start()
|
||||
return builder
|
||||
|
||||
def _associateBuilderWithInstance(self, builder, instance_id):
|
||||
self._builders[instance_id] = builder
|
||||
|
||||
def _rebuild_instances(self, instances):
|
||||
# TODO: Add a keys_dir to projectSettings
|
||||
ca_dir = os.path.join(self._main_window.projectSettings()["project_files_dir"], "keys")
|
||||
|
||||
for instance in instances:
|
||||
log.debug('CloudInspectorView._rebuild_instances {}'.format(instance.name))
|
||||
builder = CloudBuilder(self, self._provider, ca_dir)
|
||||
cloud_instance = CloudInstances.instance().get_instance(instance.id)
|
||||
public_key = cloud_instance.public_key
|
||||
private_key = cloud_instance.private_key
|
||||
# Fake a KeyPair object because we don't store it.
|
||||
keypair = namedtuple('KeyPair', ['private_key', 'public_key'])(private_key, public_key)
|
||||
builder.startAtSetup(instance, keypair)
|
||||
builder.instanceCreated.connect(self._main_window.add_instance_to_project)
|
||||
builder.instanceCreated.connect(CloudInstances.instance().add_instance)
|
||||
builder.instanceIdExists.connect(self._associateBuilderWithInstance)
|
||||
builder.instanceHasIP.connect(CloudInstances.instance().update_host_for_instance)
|
||||
builder.buildComplete.connect(self._instanceBuilt)
|
||||
builder.start()
|
||||
return builder
|
||||
@@ -1,154 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Keeps track of all cloud instances the app has started.
|
||||
"""
|
||||
|
||||
from .qt import QtCore
|
||||
from gns3.topology import TopologyInstance
|
||||
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CloudInstances(QtCore.QObject):
|
||||
|
||||
"""
|
||||
This class stores the instances that gns3 gui has started. This can be different than the list
|
||||
of instances in the topology that can be changed when switching projects. This list is not touched
|
||||
when switching projects and is stored in the .ini file.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CloudInstances, self).__init__(*args, **kwargs)
|
||||
self._instances = []
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
"""
|
||||
Singleton to return only one instance of CloudInstances.
|
||||
|
||||
:returns: instance of CloudInstances
|
||||
"""
|
||||
|
||||
if not hasattr(CloudInstances, "_instance"):
|
||||
CloudInstances._instance = CloudInstances()
|
||||
return CloudInstances._instance
|
||||
|
||||
@property
|
||||
def instances(self):
|
||||
return self._instances
|
||||
|
||||
def clear(self):
|
||||
self._instances.clear()
|
||||
|
||||
def add(self, topology_instance):
|
||||
self._instances.append(topology_instance)
|
||||
|
||||
def add_instance(self, instance, keypair):
|
||||
if instance is None:
|
||||
return
|
||||
existing = self.get_instance(instance.id)
|
||||
if existing is None:
|
||||
ti = TopologyInstance(instance.name, instance.id, instance.extra['flavorId'],
|
||||
instance.extra['imageId'], keypair.private_key, keypair.public_key)
|
||||
self._instances.append(ti)
|
||||
self.save()
|
||||
|
||||
def update_instances(self, instances):
|
||||
"""
|
||||
Compare with the existing list of instances to purge instances that no
|
||||
longer exist.
|
||||
"""
|
||||
save_needed = False
|
||||
# Look for instances that have been deleted
|
||||
for stored in self._instances:
|
||||
found = False
|
||||
for dynamic in instances:
|
||||
if stored.id == dynamic.id:
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
self._instances.remove(stored)
|
||||
save_needed = True
|
||||
|
||||
if save_needed:
|
||||
self.save()
|
||||
|
||||
def update_host_for_instance(self, host, instance_id):
|
||||
"""
|
||||
Update the public IP for the instance.
|
||||
"""
|
||||
for instance in self.instances:
|
||||
if instance.id == instance_id:
|
||||
if instance.host != host:
|
||||
instance.host = host
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the list of cloud instances to the config file
|
||||
"""
|
||||
log.debug('Saving cloud instances')
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup("CloudInstances")
|
||||
settings.remove("")
|
||||
|
||||
# Save the instances
|
||||
settings.beginWriteArray("cloud_instance", len(self._instances))
|
||||
index = 0
|
||||
for instance in self._instances:
|
||||
settings.setArrayIndex(index)
|
||||
for name in instance.fields():
|
||||
value = getattr(instance, name) if not None else ""
|
||||
log.debug('{}={}'.format(name, str(value)[0:60]))
|
||||
settings.setValue(name, value)
|
||||
index += 1
|
||||
settings.endArray()
|
||||
settings.endGroup()
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load instance info from the config file to the topology
|
||||
"""
|
||||
log.debug('Loading cloud instances')
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup("CloudInstances")
|
||||
|
||||
# Load the instances
|
||||
size = settings.beginReadArray("cloud_instance")
|
||||
for index in range(0, size):
|
||||
settings.setArrayIndex(index)
|
||||
info = {}
|
||||
for name in TopologyInstance.fields():
|
||||
value = settings.value(name, "")
|
||||
log.debug('{}={}'.format(name, str(value)[0:60]))
|
||||
info[name] = value
|
||||
ti = TopologyInstance(**info)
|
||||
self._instances.append(ti)
|
||||
|
||||
def get_instance(self, instance_id):
|
||||
"""
|
||||
Retrieve a TopologyInstance objects if present
|
||||
"""
|
||||
for i in self._instances:
|
||||
if i.id == instance_id:
|
||||
return i
|
||||
return None
|
||||
@@ -36,10 +36,6 @@ except ImportError:
|
||||
|
||||
class ConsoleCmd(cmd.Cmd):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
cmd.Cmd.__init__(self)
|
||||
|
||||
def do_version(self, args):
|
||||
"""
|
||||
Show the version of GNS3 and its dependencies.
|
||||
@@ -194,7 +190,7 @@ class ConsoleCmd(cmd.Cmd):
|
||||
|
||||
name = node.name()
|
||||
console_port = node.console()
|
||||
console_host = node.server().host
|
||||
console_host = node.server().host()
|
||||
try:
|
||||
from .telnet_console import telnetConsole
|
||||
telnetConsole(name, console_host, console_port)
|
||||
|
||||
@@ -20,6 +20,8 @@ import sys
|
||||
import struct
|
||||
import inspect
|
||||
import datetime
|
||||
|
||||
from .qt import QtCore
|
||||
from .topology import Topology
|
||||
from .version import __version__
|
||||
from .console_cmd import ConsoleCmd
|
||||
@@ -38,12 +40,12 @@ class ConsoleView(PyCutExt, ConsoleCmd):
|
||||
# Set introduction message
|
||||
bitness = struct.calcsize("P") * 8
|
||||
current_year = datetime.date.today().year
|
||||
self.intro = "GNS3 management console. Running GNS3 version {} on {} ({}-bit).\n" \
|
||||
"Copyright (c) 2006-{} GNS3 Technologies.".format(__version__, platform.system(), bitness, current_year)
|
||||
self.intro = "GNS3 management console. Running GNS3 version {} on {} ({}-bit) with Qt {}.\n" \
|
||||
"Copyright (c) 2006-{} GNS3 Technologies.".format(__version__, platform.system(), bitness, QtCore.QT_VERSION_STR, current_year)
|
||||
|
||||
# Parent class initialization
|
||||
try:
|
||||
PyCutExt.__init__(self, None, self.intro, parent=parent)
|
||||
super().__init__(None, self.intro, parent=parent)
|
||||
|
||||
# dynamically get all the available commands so we can color them
|
||||
methods = inspect.getmembers(self, predicate=inspect.ismethod)
|
||||
@@ -186,8 +188,7 @@ class ConsoleView(PyCutExt, ConsoleCmd):
|
||||
if node:
|
||||
if node.name():
|
||||
name = " {}:".format(node.name())
|
||||
server = "from {}:{}".format(node.server().host,
|
||||
node.server().port)
|
||||
server = "from {}".format(node.server().url())
|
||||
|
||||
text = "Server error {server}:{name} {message}".format(server=server,
|
||||
name=name,
|
||||
|
||||
@@ -27,24 +27,32 @@ except ImportError:
|
||||
# raven is not installed with deb package in order to simplify packaging
|
||||
RAVEN_AVAILABLE = False
|
||||
|
||||
|
||||
from .utils.get_resource import get_resource
|
||||
from .version import __version__
|
||||
from .servers import Servers
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Dev build
|
||||
if __version__[4] != 0:
|
||||
import faulthandler
|
||||
# Display a traceback in case of segfault crash. Usefull when frozen
|
||||
# Not enabled by default for security reason
|
||||
log.info("Enable catching segfault")
|
||||
faulthandler.enable()
|
||||
|
||||
|
||||
class CrashReport:
|
||||
|
||||
"""
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "sync+https://d21f3e7abc3f48f88e9ed700cae2d936:2824d6b1321b4a16aa90dd71f337d42f@app.getsentry.com/38506"
|
||||
DSN = "sync+https://a86f12c42f7746288a81af9a9c1145a4:db8b6973bd2c448ea0a98675119ff8ee@app.getsentry.com/38506"
|
||||
if hasattr(sys, "frozen"):
|
||||
cacert = os.path.join(os.getcwd(), "cacert.pem")
|
||||
if os.path.isfile(cacert):
|
||||
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))
|
||||
@@ -53,17 +61,26 @@ class CrashReport:
|
||||
def __init__(self):
|
||||
self._client = None
|
||||
|
||||
# We don't want sentry making noise if an error is catched when you 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
|
||||
|
||||
def captureException(self, exception, value, tb):
|
||||
if not RAVEN_AVAILABLE:
|
||||
return
|
||||
if os.path.exists(".git"):
|
||||
log.warning("A .git directory exist crash report is turn off for developers")
|
||||
return
|
||||
from .servers import Servers
|
||||
|
||||
local_server = Servers.instance().localServerSettings()
|
||||
if local_server["report_errors"]:
|
||||
if self._client is None:
|
||||
self._client = raven.Client(CrashReport.DSN, release=__version__)
|
||||
self._client.tags_context({
|
||||
context = {
|
||||
"os:name": platform.system(),
|
||||
"os:release": platform.release(),
|
||||
"os:win_32": " ".join(platform.win32_ver()),
|
||||
@@ -75,7 +92,9 @@ class CrashReport:
|
||||
"python:bit": struct.calcsize("P") * 8,
|
||||
"python:encoding": sys.getdefaultencoding(),
|
||||
"python:frozen": "{}".format(hasattr(sys, "frozen"))
|
||||
})
|
||||
}
|
||||
context = self._add_qt_informations(context)
|
||||
self._client.tags_context(context)
|
||||
try:
|
||||
report = self._client.captureException((exception, value, tb))
|
||||
except Exception as e:
|
||||
@@ -83,6 +102,17 @@ class CrashReport:
|
||||
return
|
||||
log.info("Crash report sent with event ID: {}".format(self._client.get_ident(report)))
|
||||
|
||||
def _add_qt_informations(self, context):
|
||||
try:
|
||||
from .qt import QtCore
|
||||
import sip
|
||||
except ImportError:
|
||||
return context
|
||||
context["pyqt:version"] = QtCore.PYQT_VERSION_STR
|
||||
context["qt:version"] = QtCore.QT_VERSION_STR
|
||||
context["sip:version"] = sip.SIP_VERSION_STR
|
||||
return context
|
||||
|
||||
@classmethod
|
||||
def instance(cls):
|
||||
if cls._instance is None:
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ..qt import QtGui
|
||||
from ..qt import QtWidgets
|
||||
from ..version import __version__
|
||||
from ..ui.about_dialog_ui import Ui_AboutDialog
|
||||
|
||||
|
||||
class AboutDialog(QtGui.QDialog, Ui_AboutDialog):
|
||||
class AboutDialog(QtWidgets.QDialog, Ui_AboutDialog):
|
||||
|
||||
"""
|
||||
About dialog.
|
||||
@@ -28,7 +28,7 @@ class AboutDialog(QtGui.QDialog, Ui_AboutDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
# dynamically add the current version number
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
Dialog to configure and update node settings using widget pages.
|
||||
"""
|
||||
|
||||
from ..qt import QtGui
|
||||
from ..qt import QtWidgets
|
||||
from ..ui.configuration_dialog_ui import Ui_configurationDialog
|
||||
from .node_configurator_dialog import ConfigurationError
|
||||
from .node_properties_dialog import ConfigurationError
|
||||
|
||||
|
||||
class ConfigurationDialog(QtGui.QDialog, Ui_configurationDialog):
|
||||
class ConfigurationDialog(QtWidgets.QDialog, Ui_configurationDialog):
|
||||
|
||||
"""
|
||||
Configuration dialog implementation.
|
||||
@@ -37,7 +37,7 @@ class ConfigurationDialog(QtGui.QDialog, Ui_configurationDialog):
|
||||
|
||||
def __init__(self, name, settings, configuration_page, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.uiTitleLabel.setText(name)
|
||||
@@ -55,11 +55,11 @@ class ConfigurationDialog(QtGui.QDialog, Ui_configurationDialog):
|
||||
:param button: button that was clicked (QAbstractButton)
|
||||
"""
|
||||
|
||||
if button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Cancel):
|
||||
QtGui.QDialog.reject(self)
|
||||
if button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel):
|
||||
QtWidgets.QDialog.reject(self)
|
||||
else:
|
||||
try:
|
||||
self._configuration_page.saveSettings(self._settings)
|
||||
except ConfigurationError:
|
||||
return
|
||||
QtGui.QDialog.accept(self)
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets
|
||||
from ..ui.exec_command_dialog_ui import Ui_ExecCommandDialog
|
||||
|
||||
|
||||
class ExecCommandDialog(QtGui.QDialog, Ui_ExecCommandDialog):
|
||||
class ExecCommandDialog(QtWidgets.QDialog, Ui_ExecCommandDialog):
|
||||
|
||||
"""
|
||||
Execute a command and display its output.
|
||||
@@ -27,7 +27,7 @@ class ExecCommandDialog(QtGui.QDialog, Ui_ExecCommandDialog):
|
||||
|
||||
def __init__(self, parent, command, params):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.setWindowTitle("Executing {}".format(command))
|
||||
@@ -57,4 +57,4 @@ class ExecCommandDialog(QtGui.QDialog, Ui_ExecCommandDialog):
|
||||
|
||||
self._process.kill()
|
||||
self._process.waitForFinished()
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ..qt import QtCore, QtGui, QtWebKit
|
||||
from ..qt import QtCore, QtGui, QtWebKitWidgets, QtWidgets
|
||||
from ..ui.getting_started_dialog_ui import Ui_GettingStartedDialog
|
||||
from ..utils.get_resource import get_resource
|
||||
from ..local_config import LocalConfig
|
||||
|
||||
|
||||
class GettingStartedDialog(QtGui.QDialog, Ui_GettingStartedDialog):
|
||||
class GettingStartedDialog(QtWidgets.QDialog, Ui_GettingStartedDialog):
|
||||
|
||||
"""
|
||||
GettingStarted dialog.
|
||||
@@ -32,17 +32,16 @@ class GettingStartedDialog(QtGui.QDialog, Ui_GettingStartedDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.uiWebView.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.uiWebView.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.adjustSize()
|
||||
self.uiWebView.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
|
||||
self.uiWebView.page().setLinkDelegationPolicy(QtWebKitWidgets.QWebPage.DelegateAllLinks)
|
||||
self.uiWebView.linkClicked.connect(self._urlClickedSlot)
|
||||
self._local_config = LocalConfig.instance()
|
||||
gui_settings = self._local_config.loadSectionSettings("GUI", {"hide_getting_started_dialog": False})
|
||||
self.uiCheckBox.setChecked(gui_settings["hide_getting_started_dialog"])
|
||||
settings = parent.settings()
|
||||
self.uiCheckBox.setChecked(settings["hide_getting_started_dialog"])
|
||||
getting_started = get_resource(os.path.join("static", "getting_started.html"))
|
||||
if getting_started and not (sys.platform.startswith("win") and not sys.maxsize > 2 ** 32):
|
||||
# do not show the page on Windows 32-bit (crash when no Internet connection)
|
||||
@@ -67,8 +66,10 @@ class GettingStartedDialog(QtGui.QDialog, Ui_GettingStartedDialog):
|
||||
:param result: ignored
|
||||
"""
|
||||
|
||||
self._local_config.saveSectionSettings("GUI", {"hide_getting_started_dialog": self.uiCheckBox.isChecked()})
|
||||
QtGui.QDialog.done(self, result)
|
||||
settings = self.parentWidget().settings()
|
||||
settings["hide_getting_started_dialog"] = self.uiCheckBox.isChecked()
|
||||
self.parentWidget().setSettings(settings)
|
||||
super().done(result)
|
||||
|
||||
def _urlClickedSlot(self, url):
|
||||
"""
|
||||
@@ -78,4 +79,4 @@ class GettingStartedDialog(QtGui.QDialog, Ui_GettingStartedDialog):
|
||||
"""
|
||||
|
||||
if QtGui.QDesktopServices.openUrl(url) is False:
|
||||
QtGui.QMessageBox.critical(self, "Getting started", "Failed to open the URL: {}".format(url))
|
||||
QtWidgets.QMessageBox.critical(self, "Getting started", "Failed to open the URL: {}".format(url))
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from ..qt import QtGui
|
||||
from ..qt import QtWidgets
|
||||
from ..topology import Topology
|
||||
from ..ui.idlepc_dialog_ui import Ui_IdlePCDialog
|
||||
|
||||
|
||||
class IdlePCDialog(QtGui.QDialog, Ui_IdlePCDialog):
|
||||
class IdlePCDialog(QtWidgets.QDialog, Ui_IdlePCDialog):
|
||||
|
||||
"""
|
||||
Idle-PC dialog.
|
||||
@@ -31,10 +31,10 @@ class IdlePCDialog(QtGui.QDialog, Ui_IdlePCDialog):
|
||||
|
||||
def __init__(self, router, idlepcs, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self._applySlot)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self._helpSlot)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applySlot)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self._helpSlot)
|
||||
|
||||
self._router = router
|
||||
self._idlepcs = idlepcs
|
||||
@@ -59,8 +59,7 @@ Finding the right idle-pc value is a trial and error process, consisting of appl
|
||||
|
||||
Select each value that appears in the list and click Apply, and note the CPU usage a few moments later. When you have found the value that minimises the CPU usage, apply that value.
|
||||
"""
|
||||
|
||||
QtGui.QMessageBox.information(self, "Hints for Idle-PC", help_text)
|
||||
QtWidgets.QMessageBox.information(self, "Hints for Idle-PC", help_text)
|
||||
|
||||
def _applySlot(self):
|
||||
"""
|
||||
@@ -68,7 +67,7 @@ Select each value that appears in the list and click Apply, and note the CPU usa
|
||||
"""
|
||||
|
||||
if not self.uiComboBox.count():
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "Sorry could not find a valid Idle-PC value, please check again with Cisco IOS in a different state")
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "Sorry could not find a valid Idle-PC value, please check again with Cisco IOS in a different state")
|
||||
return
|
||||
|
||||
idlepc = self.uiComboBox.itemData(self.uiComboBox.currentIndex())
|
||||
@@ -90,4 +89,4 @@ Select each value that appears in the list and click Apply, and note the CPU usa
|
||||
|
||||
if result:
|
||||
self._applySlot()
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
"""
|
||||
Dialog for importing cloud projects
|
||||
"""
|
||||
|
||||
from ..ui.import_cloud_project_dialog_ui import Ui_ImportCloudProjectDialog
|
||||
from ..qt import QtGui
|
||||
from ..cloud.utils import get_cloud_projects, DownloadProjectThread, DeleteProjectThread
|
||||
from ..utils.progress_dialog import ProgressDialog
|
||||
|
||||
|
||||
class ImportCloudProjectDialog(QtGui.QDialog, Ui_ImportCloudProjectDialog):
|
||||
|
||||
"""
|
||||
Import cloud project dialog implementation.
|
||||
"""
|
||||
|
||||
def __init__(self, parent, project_dest_path, images_dest_path, cloud_settings):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.project_dest_path = project_dest_path
|
||||
self.images_dest_path = images_dest_path
|
||||
self.cloud_settings = cloud_settings
|
||||
|
||||
self.uiImportProjectAction.clicked.connect(self._importProject)
|
||||
self.uiDeleteProjectAction.clicked.connect(self._deleteProject)
|
||||
self._listCloudProjects()
|
||||
|
||||
def _listCloudProjects(self):
|
||||
self.listWidget.clear()
|
||||
self.projects = get_cloud_projects(self.cloud_settings)
|
||||
self.listWidget.addItems(list(self.projects.keys()))
|
||||
|
||||
def _importProject(self):
|
||||
project_file_name = self.projects[self.listWidget.currentItem().text()]
|
||||
|
||||
download_thread = DownloadProjectThread(
|
||||
self,
|
||||
project_file_name,
|
||||
self.project_dest_path,
|
||||
self.images_dest_path,
|
||||
self.cloud_settings
|
||||
)
|
||||
progress_dialog = ProgressDialog(download_thread, "Importing project", "Downloading project files...", "Cancel",
|
||||
parent=self.parent())
|
||||
|
||||
progress_dialog.show()
|
||||
progress_dialog.exec_()
|
||||
|
||||
self.close()
|
||||
|
||||
def _deleteProject(self):
|
||||
project_file_name = self.projects[self.listWidget.currentItem().text()]
|
||||
|
||||
button_clicked = QtGui.QMessageBox.question(
|
||||
self,
|
||||
"Delete project",
|
||||
"Are you sure you want to delete project " + self.listWidget.currentItem().text(),
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
|
||||
QtGui.QMessageBox.Yes
|
||||
)
|
||||
|
||||
if button_clicked == QtGui.QMessageBox.Yes:
|
||||
delete_project_thread = DeleteProjectThread(self, project_file_name, self.cloud_settings)
|
||||
progress_dialog = ProgressDialog(delete_project_thread, "Deleting project", "Deleting project files...",
|
||||
"Cancel", parent=self)
|
||||
progress_dialog.show()
|
||||
progress_dialog.exec_()
|
||||
|
||||
self._listCloudProjects()
|
||||
@@ -16,12 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.new_project_dialog_ui import Ui_NewProjectDialog
|
||||
from ..settings import ENABLE_CLOUD
|
||||
|
||||
|
||||
class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
class NewProjectDialog(QtWidgets.QDialog, Ui_NewProjectDialog):
|
||||
|
||||
"""
|
||||
New project dialog.
|
||||
@@ -33,7 +32,7 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
|
||||
def __init__(self, parent, showed_from_startup=False):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._main_window = parent
|
||||
@@ -46,8 +45,6 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
self.uiLocationBrowserToolButton.clicked.connect(self._projectPathSlot)
|
||||
self.uiOpenProjectPushButton.clicked.connect(self._openProjectActionSlot)
|
||||
self.uiRecentProjectsPushButton.clicked.connect(self._showRecentProjectsSlot)
|
||||
if not ENABLE_CLOUD:
|
||||
self.uiCloudRadioButton.hide()
|
||||
|
||||
if not showed_from_startup:
|
||||
self.uiOpenProjectPushButton.hide()
|
||||
@@ -72,8 +69,9 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
Slot to select the a new project location.
|
||||
"""
|
||||
|
||||
path = QtGui.QFileDialog.getSaveFileName(self, "Project location", os.path.join(self._main_window.projectsDirPath(),
|
||||
self.uiNameLineEdit.text()))
|
||||
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Project location", os.path.join(self._main_window.projectsDirPath(),
|
||||
self.uiNameLineEdit.text()))
|
||||
|
||||
if path:
|
||||
self.uiLocationLineEdit.setText(path)
|
||||
|
||||
@@ -104,7 +102,7 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
lot to show all the recent projects in a menu.
|
||||
"""
|
||||
|
||||
menu = QtGui.QMenu()
|
||||
menu = QtWidgets.QMenu()
|
||||
menu.triggered.connect(self._menuTriggeredSlot)
|
||||
for action in self._main_window._recent_file_actions:
|
||||
menu.addAction(action)
|
||||
@@ -115,26 +113,23 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
if result:
|
||||
project_name = self.uiNameLineEdit.text()
|
||||
project_location = self.uiLocationLineEdit.text()
|
||||
if self.uiCloudRadioButton.isChecked():
|
||||
project_type = "cloud"
|
||||
else:
|
||||
project_type = "local"
|
||||
project_type = "local"
|
||||
|
||||
if not project_name:
|
||||
QtGui.QMessageBox.critical(self, "New project", "Project name is empty")
|
||||
QtWidgets.QMessageBox.critical(self, "New project", "Project name is empty")
|
||||
return
|
||||
|
||||
if not project_location:
|
||||
QtGui.QMessageBox.critical(self, "New project", "Project location is empty")
|
||||
QtWidgets.QMessageBox.critical(self, "New project", "Project location is empty")
|
||||
return
|
||||
|
||||
if os.path.isdir(project_location):
|
||||
reply = QtGui.QMessageBox.question(self,
|
||||
"New project",
|
||||
"Location {} already exists, overwrite it?".format(project_location),
|
||||
QtGui.QMessageBox.Yes,
|
||||
QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.No:
|
||||
reply = QtWidgets.QMessageBox.question(self,
|
||||
"New project",
|
||||
"Location {} already exists, overwrite it?".format(project_location),
|
||||
QtWidgets.QMessageBox.Yes,
|
||||
QtWidgets.QMessageBox.No)
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
self._project_settings["project_name"] = project_name
|
||||
@@ -142,4 +137,4 @@ class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
|
||||
self._project_settings["project_files_dir"] = project_location
|
||||
self._project_settings["project_type"] = project_type
|
||||
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
@@ -22,14 +22,14 @@ Dialog to configure and update node settings using widget pages.
|
||||
from gns3.http_client import HTTPClient
|
||||
from gns3.progress import Progress
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..ui.node_configurator_dialog_ui import Ui_NodeConfiguratorDialog
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.node_properties_dialog_ui import Ui_NodePropertiesDialog
|
||||
|
||||
|
||||
class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
class NodePropertiesDialog(QtWidgets.QDialog, Ui_NodePropertiesDialog):
|
||||
|
||||
"""
|
||||
Node configurator implementation.
|
||||
Node properties implementation.
|
||||
|
||||
:param node_items: list of NodeItem instances
|
||||
:param parent: parent widget
|
||||
@@ -37,31 +37,30 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
|
||||
def __init__(self, node_items, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._node_items = node_items
|
||||
self._parent_items = {}
|
||||
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(False)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(False)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(False)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(False)
|
||||
|
||||
self.previousItem = None
|
||||
self.previousPage = None
|
||||
|
||||
# load the empty page widget by default
|
||||
self.uiEmptyPageWidget = self.uiConfigStackedWidget.findChildren(QtGui.QWidget, "uiEmptyPageWidget")[0]
|
||||
self.uiEmptyPageWidget = self.uiConfigStackedWidget.findChildren(QtWidgets.QWidget, "uiEmptyPageWidget")[0]
|
||||
self.uiConfigStackedWidget.setCurrentWidget(self.uiEmptyPageWidget)
|
||||
|
||||
self._loadNodeItems()
|
||||
self.splitter.setSizes([250, 600])
|
||||
self._loadNodeItems()
|
||||
|
||||
self.uiNodesTreeWidget.itemClicked.connect(self.showConfigurationPageSlot)
|
||||
HTTPClient.setProgressCallback(Progress(self, min_duration=0))
|
||||
|
||||
def _loadNodeItems(self):
|
||||
"""
|
||||
Loads the nodes into the Node configurator QTreeWidget
|
||||
Loads the nodes into the Node properties QTreeWidget
|
||||
"""
|
||||
|
||||
# create the parent (group) items
|
||||
@@ -71,7 +70,7 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
group_name = " {} group".format(str(node_item.node()))
|
||||
parent = group_name
|
||||
if parent not in self._parent_items:
|
||||
item = QtGui.QTreeWidgetItem(self.uiNodesTreeWidget, [group_name])
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiNodesTreeWidget, [group_name])
|
||||
item.setIcon(0, QtGui.QIcon(node_item.node().defaultSymbol()))
|
||||
item.setExpanded(True)
|
||||
self._parent_items[parent] = item
|
||||
@@ -81,11 +80,19 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
if not node_item.node().initialized():
|
||||
continue
|
||||
parent = " {} group".format(str(node_item.node()))
|
||||
item = ConfigurationPageItem(self._parent_items[parent], node_item)
|
||||
ConfigurationPageItem(self._parent_items[parent], node_item)
|
||||
|
||||
# sort the tree
|
||||
self.uiNodesTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
|
||||
|
||||
if len(self._node_items) == 1:
|
||||
parent = " {} group".format(str(node_item.node()))
|
||||
item = self._parent_items[parent].child(0)
|
||||
item.setSelected(True)
|
||||
self.uiNodesTreeWidget.setCurrentItem(item)
|
||||
self.showConfigurationPageSlot(item, 0)
|
||||
self.splitter.setSizes([0, 600])
|
||||
|
||||
def showConfigurationPageSlot(self, item, column):
|
||||
"""
|
||||
Shows a configuration page widget.
|
||||
@@ -122,11 +129,11 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
self.uiConfigStackedWidget.setCurrentWidget(page)
|
||||
|
||||
if page != self.uiEmptyPageWidget:
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(True)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(True)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(True)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(True)
|
||||
else:
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(False)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(False)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(False)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(False)
|
||||
|
||||
def on_uiButtonBox_clicked(self, button):
|
||||
"""
|
||||
@@ -136,18 +143,15 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
"""
|
||||
|
||||
try:
|
||||
from gns3.main_window import MainWindow
|
||||
if button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply):
|
||||
if button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply):
|
||||
self.applySettings()
|
||||
elif button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset):
|
||||
elif button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset):
|
||||
self.resetSettings()
|
||||
elif button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Cancel):
|
||||
HTTPClient.setProgressCallback(Progress(MainWindow.instance()))
|
||||
QtGui.QDialog.reject(self)
|
||||
elif button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel):
|
||||
QtWidgets.QDialog.reject(self)
|
||||
else:
|
||||
self.applySettings()
|
||||
HTTPClient.setProgressCallback(Progress(MainWindow.instance()))
|
||||
QtGui.QDialog.accept(self)
|
||||
QtWidgets.QDialog.accept(self)
|
||||
except ConfigurationError:
|
||||
pass
|
||||
|
||||
@@ -208,7 +212,7 @@ class NodeConfiguratorDialog(QtGui.QDialog, Ui_NodeConfiguratorDialog):
|
||||
child.setSettings(child.node().settings().copy())
|
||||
|
||||
|
||||
class ConfigurationPageItem(QtGui.QTreeWidgetItem):
|
||||
class ConfigurationPageItem(QtWidgets.QTreeWidgetItem):
|
||||
|
||||
"""
|
||||
Item for the QTreeWidget instance.
|
||||
@@ -221,7 +225,7 @@ class ConfigurationPageItem(QtGui.QTreeWidgetItem):
|
||||
def __init__(self, parent, node_item):
|
||||
|
||||
self._node = node_item.node()
|
||||
QtGui.QTreeWidgetItem.__init__(self, parent, [self._node.name()])
|
||||
super().__init__(parent, [self._node.name()])
|
||||
|
||||
# return the configuration page widget used to configure the node.
|
||||
self._page = self._node.configPage()
|
||||
@@ -242,7 +246,7 @@ class ConfigurationPageItem(QtGui.QTreeWidgetItem):
|
||||
|
||||
def page(self):
|
||||
"""
|
||||
Returns the page widget to be displayed by the node configurator.
|
||||
Returns the page widget to be displayed by the node properties dialog.
|
||||
|
||||
:returns: QWidget instance
|
||||
"""
|
||||
@@ -285,4 +289,4 @@ class ConfigurationError(Exception):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
Exception.__init__(self)
|
||||
super().__init__()
|
||||
@@ -19,19 +19,15 @@
|
||||
Dialog to load module and built-in preference pages.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets
|
||||
from ..ui.preferences_dialog_ui import Ui_PreferencesDialog
|
||||
from ..pages.server_preferences_page import ServerPreferencesPage
|
||||
from ..pages.general_preferences_page import GeneralPreferencesPage
|
||||
from ..pages.cloud_preferences_page import CloudPreferencesPage
|
||||
from ..pages.packet_capture_preferences_page import PacketCapturePreferencesPage
|
||||
from ..modules import MODULES
|
||||
from ..settings import ENABLE_CLOUD
|
||||
from ..http_client import HTTPClient
|
||||
from ..progress import Progress
|
||||
|
||||
|
||||
class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog):
|
||||
|
||||
"""
|
||||
Preferences dialog implementation.
|
||||
@@ -41,17 +37,16 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.uiTreeWidget.currentItemChanged.connect(self._showPreferencesPageSlot)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self._applyPreferences)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferences)
|
||||
self._items = []
|
||||
self._loadPreferencePages()
|
||||
|
||||
# select the first available page
|
||||
self.uiTreeWidget.setCurrentItem(self._items[0])
|
||||
HTTPClient.setProgressCallback(Progress(self, min_duration=0))
|
||||
|
||||
def _loadPreferencePages(self):
|
||||
"""
|
||||
@@ -64,14 +59,12 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
ServerPreferencesPage,
|
||||
PacketCapturePreferencesPage,
|
||||
]
|
||||
if ENABLE_CLOUD:
|
||||
pages.append(CloudPreferencesPage)
|
||||
|
||||
for page in pages:
|
||||
preferences_page = page(self)
|
||||
preferences_page.loadPreferences()
|
||||
name = preferences_page.windowTitle()
|
||||
item = QtGui.QTreeWidgetItem(self.uiTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiTreeWidget)
|
||||
item.setText(0, name)
|
||||
item.setData(0, QtCore.Qt.UserRole, preferences_page)
|
||||
self.uiStackedWidget.addWidget(preferences_page)
|
||||
@@ -85,7 +78,7 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
preferences_page = cls()
|
||||
preferences_page.loadPreferences()
|
||||
name = preferences_page.windowTitle()
|
||||
item = QtGui.QTreeWidgetItem(parent)
|
||||
item = QtWidgets.QTreeWidgetItem(parent)
|
||||
item.setText(0, name)
|
||||
item.setData(0, QtCore.Qt.UserRole, preferences_page)
|
||||
self.uiStackedWidget.addWidget(preferences_page)
|
||||
@@ -139,9 +132,7 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
Closes this dialog.
|
||||
"""
|
||||
|
||||
from gns3.main_window import MainWindow
|
||||
HTTPClient.setProgressCallback(Progress(MainWindow.instance()))
|
||||
QtGui.QDialog.reject(self)
|
||||
QtWidgets.QDialog.reject(self)
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
@@ -149,11 +140,10 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
|
||||
"""
|
||||
|
||||
# close the nodes dock to refresh the node list
|
||||
main_window = self.parentWidget()
|
||||
from ..main_window import MainWindow
|
||||
main_window = MainWindow.instance()
|
||||
main_window.uiNodesDockWidget.setVisible(False)
|
||||
main_window.uiNodesDockWidget.setWindowTitle("")
|
||||
|
||||
if self._applyPreferences():
|
||||
from gns3.main_window import MainWindow
|
||||
HTTPClient.setProgressCallback(Progress(MainWindow.instance()))
|
||||
QtGui.QDialog.accept(self)
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
236
gns3/dialogs/setup_wizard.py
Normal file
236
gns3/dialogs/setup_wizard.py
Normal file
@@ -0,0 +1,236 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from gns3.qt import QtCore, QtWidgets
|
||||
from gns3.servers import Servers
|
||||
from ..gns3_vm import GNS3VM
|
||||
from ..dialogs.preferences_dialog import PreferencesDialog
|
||||
from ..ui.setup_wizard_ui import Ui_SetupWizard
|
||||
from ..utils.progress_dialog import ProgressDialog
|
||||
from ..utils.wait_for_vm_worker import WaitForVMWorker
|
||||
|
||||
|
||||
class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
|
||||
|
||||
"""
|
||||
Base class for VM wizard.
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
|
||||
if sys.platform.startswith("darwin"):
|
||||
# we want to see the cancel button on OSX
|
||||
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
|
||||
|
||||
self._server = Servers.instance().localServer()
|
||||
self.uiRefreshPushButton.clicked.connect(self._refreshVMListSlot)
|
||||
self.uiVmwareRadioButton.clicked.connect(self._listVMwareVMsSlot)
|
||||
self.uiVirtualBoxRadioButton.clicked.connect(self._listVirtualBoxVMsSlot)
|
||||
settings = parent.settings()
|
||||
self.uiShowCheckBox.setChecked(settings["hide_setup_wizard"])
|
||||
|
||||
# by default all radio buttons are unchecked
|
||||
self.uiVmwareRadioButton.setAutoExclusive(False)
|
||||
self.uiVirtualBoxRadioButton.setAutoExclusive(False)
|
||||
self.uiVmwareRadioButton.setChecked(False)
|
||||
self.uiVirtualBoxRadioButton.setChecked(False)
|
||||
|
||||
def _listVMwareVMsSlot(self):
|
||||
"""
|
||||
Slot to refresh the VMware VMs list.
|
||||
"""
|
||||
|
||||
self.uiVirtualBoxRadioButton.setChecked(False)
|
||||
from gns3.modules import VMware
|
||||
settings = VMware.instance().settings()
|
||||
if not os.path.exists(settings["vmrun_path"]):
|
||||
QtWidgets.QMessageBox.critical(self, "VMware", "VMware vmrun tool could not be found, VMware or the VIX API is probably not installed")
|
||||
return
|
||||
self._refreshVMListSlot()
|
||||
|
||||
def _listVirtualBoxVMsSlot(self):
|
||||
"""
|
||||
Slot to refresh the VirtualBox VMs list.
|
||||
"""
|
||||
|
||||
self.uiVmwareRadioButton.setChecked(False)
|
||||
from gns3.modules import VirtualBox
|
||||
settings = VirtualBox.instance().settings()
|
||||
if not os.path.exists(settings["vboxmanage_path"]):
|
||||
QtWidgets.QMessageBox.critical(self, "VirtualBox", "VBoxManage could not be found, VirtualBox is probably not installed")
|
||||
return
|
||||
self._refreshVMListSlot()
|
||||
|
||||
def showit(self):
|
||||
"""
|
||||
Either this dialog should be automatically showed at startup.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return not self.uiShowCheckBox.isChecked()
|
||||
|
||||
def _setPreferencesPane(self, dialog, name):
|
||||
"""
|
||||
Finds the first child of the QTreeWidgetItem name.
|
||||
|
||||
:param dialog: PreferencesDialog instance
|
||||
:param name: QTreeWidgetItem name
|
||||
|
||||
:returns: current QWidget
|
||||
"""
|
||||
|
||||
pane = dialog.uiTreeWidget.findItems(name, QtCore.Qt.MatchFixedString)[0]
|
||||
child_pane = pane.child(0)
|
||||
dialog.uiTreeWidget.setCurrentItem(child_pane)
|
||||
return dialog.uiStackedWidget.currentWidget()
|
||||
|
||||
def validateCurrentPage(self):
|
||||
"""
|
||||
Validates the settings.
|
||||
"""
|
||||
|
||||
gns3_vm = GNS3VM.instance()
|
||||
servers = Servers.instance()
|
||||
if self.currentPage() == self.uiVMWizardPage:
|
||||
vmname = self.uiVMListComboBox.currentText()
|
||||
if vmname:
|
||||
# save the GNS3 VM settings
|
||||
vm_settings = {"auto_start": True,
|
||||
"vmname": vmname,
|
||||
"vmx_path": self.uiVMListComboBox.currentData()}
|
||||
if self.uiVmwareRadioButton.isChecked():
|
||||
vm_settings["virtualization"] = "VMware"
|
||||
elif self.uiVirtualBoxRadioButton.isChecked():
|
||||
vm_settings["virtualization"] = "VirtualBox"
|
||||
gns3_vm.setSettings(vm_settings)
|
||||
servers.save()
|
||||
|
||||
# start the GNS3 VM
|
||||
servers.initVMServer()
|
||||
worker = WaitForVMWorker()
|
||||
progress_dialog = ProgressDialog(worker, "GNS3 VM", "Starting the GNS3 VM...", "Cancel", busy=True, parent=self)
|
||||
progress_dialog.show()
|
||||
if progress_dialog.exec_():
|
||||
gns3_vm.adjustLocalServerIP()
|
||||
else:
|
||||
return False
|
||||
elif self.currentPage() == self.uiAddVMsWizardPage:
|
||||
|
||||
use_local_server = self.uiLocalRadioButton.isChecked()
|
||||
if use_local_server:
|
||||
# deactivate the GNS3 VM if using the local server
|
||||
vm_settings = {"auto_start": False}
|
||||
gns3_vm.setSettings(vm_settings)
|
||||
servers.save()
|
||||
from gns3.modules import Dynamips
|
||||
Dynamips.instance().setSettings({"use_local_server": use_local_server})
|
||||
if sys.platform.startswith("linux"):
|
||||
# IOU only works on Linux
|
||||
from gns3.modules import IOU
|
||||
IOU.instance().setSettings({"use_local_server": use_local_server})
|
||||
from gns3.modules import Qemu
|
||||
Qemu.instance().setSettings({"use_local_server": use_local_server})
|
||||
from gns3.modules import VPCS
|
||||
VPCS.instance().setSettings({"use_local_server": use_local_server})
|
||||
|
||||
dialog = PreferencesDialog(self)
|
||||
if self.uiAddIOSRouterCheckBox.isChecked():
|
||||
self._setPreferencesPane(dialog, "Dynamips").uiNewIOSRouterPushButton.clicked.emit(False)
|
||||
if self.uiAddIOUDeviceCheckBox.isChecked():
|
||||
self._setPreferencesPane(dialog, "IOS on UNIX").uiNewIOUDevicePushButton.clicked.emit(False)
|
||||
if self.uiAddQemuVMcheckBox.isChecked():
|
||||
self._setPreferencesPane(dialog, "QEMU").uiNewQemuVMPushButton.clicked.emit(False)
|
||||
if self.uiAddVirtualBoxVMcheckBox.isChecked():
|
||||
self._setPreferencesPane(dialog, "VirtualBox").uiNewVirtualBoxVMPushButton.clicked.emit(False)
|
||||
if self.uiAddVMwareVMcheckBox.isChecked():
|
||||
self._setPreferencesPane(dialog, "VMware").uiNewVMwareVMPushButton.clicked.emit(False)
|
||||
dialog.exec_()
|
||||
return True
|
||||
|
||||
def _refreshVMListSlot(self):
|
||||
"""
|
||||
Refresh the list of VM available in VMware or VirtualBox.
|
||||
"""
|
||||
|
||||
if not Servers.instance().localServerIsRunning():
|
||||
QtWidgets.QMessageBox.critical(self, "Local server", "{}".format("Local server is not running"))
|
||||
return
|
||||
server = Servers.instance().localServer()
|
||||
if self.uiVmwareRadioButton.isChecked():
|
||||
server.get("/vmware/vms", self._getVMsFromServerCallback)
|
||||
elif self.uiVirtualBoxRadioButton.isChecked():
|
||||
server.get("/virtualbox/vms", self._getVMsFromServerCallback)
|
||||
|
||||
def _getVMsFromServerCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
Callback for getVMsFromServer.
|
||||
|
||||
:param progress_dialog: QProgressDialog instance
|
||||
:param result: server response
|
||||
:param error: indicates an error (boolean)
|
||||
"""
|
||||
|
||||
if error:
|
||||
QtWidgets.QMessageBox.critical(self, "VM List", "{}".format(result["message"]))
|
||||
else:
|
||||
self.uiVMListComboBox.clear()
|
||||
for vm in result:
|
||||
if self.uiVmwareRadioButton.isChecked():
|
||||
self.uiVMListComboBox.addItem(vm["vmname"], vm["vmx_path"])
|
||||
else:
|
||||
self.uiVMListComboBox.addItem(vm["vmname"], "")
|
||||
gns3_vm = Servers.instance().vmSettings()
|
||||
index = self.uiVMListComboBox.findText(gns3_vm["vmname"])
|
||||
if index != -1:
|
||||
self.uiVMListComboBox.setCurrentIndex(index)
|
||||
else:
|
||||
index = self.uiVMListComboBox.findText("GNS3 VM")
|
||||
if index != -1:
|
||||
self.uiVMListComboBox.setCurrentIndex(index)
|
||||
else:
|
||||
QtWidgets.QMessageBox.critical(self, "GNS3 VM", "Could not find a VM named 'GNS3 VM', is it imported in VMware or VirtualBox?")
|
||||
|
||||
def done(self, result):
|
||||
"""
|
||||
This dialog is closed.
|
||||
|
||||
:param result: ignored
|
||||
"""
|
||||
|
||||
settings = self.parentWidget().settings()
|
||||
settings["hide_setup_wizard"] = self.uiShowCheckBox.isChecked()
|
||||
self.parentWidget().setSettings(settings)
|
||||
super().done(result)
|
||||
|
||||
def nextId(self):
|
||||
"""
|
||||
Wizard rules!
|
||||
"""
|
||||
|
||||
current_id = self.currentId()
|
||||
if self.page(current_id) == self.uiServerWizardPage and not self.uiVMRadioButton.isChecked():
|
||||
# skip the GNS3 VM page if using the local server.
|
||||
return self.uiServerWizardPage.nextId() + 1
|
||||
return QtWidgets.QWizard.nextId(self)
|
||||
@@ -24,7 +24,7 @@ import re
|
||||
import time
|
||||
import os
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets
|
||||
from ..utils.progress_dialog import ProgressDialog
|
||||
from ..utils.process_files_worker import ProcessFilesWorker
|
||||
from ..ui.snapshots_dialog_ui import Ui_SnapshotsDialog
|
||||
@@ -32,7 +32,7 @@ from ..topology import Topology
|
||||
from ..node import Node
|
||||
|
||||
|
||||
class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
class SnapshotsDialog(QtWidgets.QDialog, Ui_SnapshotsDialog):
|
||||
|
||||
"""
|
||||
Snapshots dialog implementation.
|
||||
@@ -42,7 +42,7 @@ class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
|
||||
def __init__(self, parent, project_path, project_files_dir):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._project_path = project_path
|
||||
@@ -70,7 +70,7 @@ class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
snapshot_name = match.group(1)
|
||||
snapshot_date = match.group(2)[:2] + '/' + match.group(2)[2:4] + '/' + match.group(2)[4:]
|
||||
snapshot_time = match.group(3)[:2] + ':' + match.group(3)[2:4] + ':' + match.group(3)[4:]
|
||||
item = QtGui.QListWidgetItem(self.uiSnapshotsList)
|
||||
item = QtWidgets.QListWidgetItem(self.uiSnapshotsList)
|
||||
item.setText("{} on {} at {}".format(snapshot_name, snapshot_date, snapshot_time))
|
||||
item.setData(QtCore.Qt.UserRole, os.path.join(snapshot_dir, snapshot))
|
||||
|
||||
@@ -89,7 +89,7 @@ class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
Slot to create a snapshot.
|
||||
"""
|
||||
|
||||
snapshot_name, ok = QtGui.QInputDialog.getText(self, "Snapshot", "Snapshot name:", QtGui.QLineEdit.Normal, "Unnamed")
|
||||
snapshot_name, ok = QtWidgets.QInputDialog.getText(self, "Snapshot", "Snapshot name:", QtWidgets.QLineEdit.Normal, "Unnamed")
|
||||
if ok and snapshot_name:
|
||||
from ..main_window import MainWindow
|
||||
MainWindow.instance().saveProject(self._project_path)
|
||||
@@ -134,9 +134,9 @@ class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
snapshot_name = match.group(1)
|
||||
else:
|
||||
snapshot_name = "Unknown"
|
||||
reply = QtGui.QMessageBox.question(self, "Snapshots", "This will discard any changes made to your project since the snapshot \"{}\" was taken?".format(snapshot_name),
|
||||
QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
|
||||
if reply == QtGui.QMessageBox.Cancel:
|
||||
reply = QtWidgets.QMessageBox.question(self, "Snapshots", "This will discard any changes made to your project since the snapshot \"{}\" was taken?".format(snapshot_name),
|
||||
QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Cancel)
|
||||
if reply == QtWidgets.QMessageBox.Cancel:
|
||||
return
|
||||
|
||||
# stop all the nodes
|
||||
@@ -167,7 +167,7 @@ class SnapshotsDialog(QtGui.QDialog, Ui_SnapshotsDialog):
|
||||
os.remove(self._project_path)
|
||||
shutil.copy(os.path.join(snapshot_path, os.path.basename(self._project_path)), self._project_path)
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(self, "Restore snapshot", "Cannot restore snapshot: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "Restore snapshot", "Cannot restore snapshot: {}".format(e))
|
||||
else:
|
||||
worker = ProcessFilesWorker(snapshot_path, os.path.dirname(self._project_path), skip_dirs=["snapshots"])
|
||||
progress_dialog = ProgressDialog(worker, "Restoring snapshot", "Copying project files...", "Cancel", parent=self)
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
Style editor to edit Shape items.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets, QtGui
|
||||
from ..ui.style_editor_dialog_ui import Ui_StyleEditorDialog
|
||||
|
||||
|
||||
class StyleEditorDialog(QtGui.QDialog, Ui_StyleEditorDialog):
|
||||
class StyleEditorDialog(QtWidgets.QDialog, Ui_StyleEditorDialog):
|
||||
|
||||
"""
|
||||
Style editor dialog.
|
||||
@@ -34,13 +34,13 @@ class StyleEditorDialog(QtGui.QDialog, Ui_StyleEditorDialog):
|
||||
|
||||
def __init__(self, parent, items):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._items = items
|
||||
self.uiColorPushButton.clicked.connect(self._setColorSlot)
|
||||
self.uiBorderColorPushButton.clicked.connect(self._setBorderColorSlot)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
|
||||
self.uiBorderStyleComboBox.addItem("Solid", QtCore.Qt.SolidLine)
|
||||
self.uiBorderStyleComboBox.addItem("Dash", QtCore.Qt.DashLine)
|
||||
@@ -74,7 +74,7 @@ class StyleEditorDialog(QtGui.QDialog, Ui_StyleEditorDialog):
|
||||
Slot to select the filling color.
|
||||
"""
|
||||
|
||||
color = QtGui.QColorDialog.getColor(self._color, self, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
||||
color = QtWidgets.QColorDialog.getColor(self._color, self, "Select Color", QtWidgets.QColorDialog.ShowAlphaChannel)
|
||||
if color.isValid():
|
||||
self._color = color
|
||||
self.uiColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._color.red(),
|
||||
@@ -87,7 +87,7 @@ class StyleEditorDialog(QtGui.QDialog, Ui_StyleEditorDialog):
|
||||
Slot to select the border color.
|
||||
"""
|
||||
|
||||
color = QtGui.QColorDialog.getColor(self._border_color, self, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
||||
color = QtWidgets.QColorDialog.getColor(self._border_color, self, "Select Color", QtWidgets.QColorDialog.ShowAlphaChannel)
|
||||
if color.isValid():
|
||||
self._border_color = color
|
||||
self.uiBorderColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._border_color.red(),
|
||||
@@ -118,4 +118,4 @@ class StyleEditorDialog(QtGui.QDialog, Ui_StyleEditorDialog):
|
||||
|
||||
if result:
|
||||
self._applyPreferencesSlot()
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
@@ -16,15 +16,21 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Dialog to change the topology symbol of NodeItems
|
||||
Dialog to change node symbols.
|
||||
"""
|
||||
|
||||
from ..qt import QtSvg, QtCore, QtGui
|
||||
import os
|
||||
|
||||
from ..qt import QtSvg, QtCore, QtGui, QtWidgets
|
||||
from ..items.svg_node_item import SvgNodeItem
|
||||
from ..items.pixmap_node_item import PixmapNodeItem
|
||||
from ..ui.symbol_selection_dialog_ui import Ui_SymbolSelectionDialog
|
||||
from ..node import Node
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SymbolSelectionDialog(QtGui.QDialog, Ui_SymbolSelectionDialog):
|
||||
class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog):
|
||||
|
||||
"""
|
||||
Symbol selection dialog.
|
||||
@@ -33,48 +39,37 @@ class SymbolSelectionDialog(QtGui.QDialog, Ui_SymbolSelectionDialog):
|
||||
:param items: list of items
|
||||
"""
|
||||
|
||||
def __init__(self, parent, items=None, symbol=None, category=None):
|
||||
def __init__(self, parent, items=None, symbol=None):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._items = items
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
self.uiSymbolToolButton.clicked.connect(self._symbolBrowserSlot)
|
||||
self._symbols_dir = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.PicturesLocation)
|
||||
|
||||
selected_symbol = symbol
|
||||
selected_category = category
|
||||
if not self._items:
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).hide()
|
||||
|
||||
# current categories
|
||||
categories = {"Routers": Node.routers,
|
||||
"Switches": Node.switches,
|
||||
"End devices": Node.end_devices,
|
||||
"Security devices": Node.security_devices
|
||||
}
|
||||
|
||||
index = 0
|
||||
for name, category in categories.items():
|
||||
self.uiCategoryComboBox.addItem(name, category)
|
||||
if category == selected_category:
|
||||
self.uiCategoryComboBox.setCurrentIndex(index)
|
||||
index += 1
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).hide()
|
||||
else:
|
||||
self.uiCategoryLabel.hide()
|
||||
self.uiCategoryComboBox.hide()
|
||||
custom_symbol = items[0].defaultRenderer().objectName()
|
||||
if not custom_symbol:
|
||||
symbol_name = items[0].node().defaultSymbol()
|
||||
else:
|
||||
symbol_name = custom_symbol
|
||||
selected_symbol = symbol_name
|
||||
first_item = items[0]
|
||||
if isinstance(first_item, SvgNodeItem):
|
||||
custom_symbol = first_item.renderer().objectName()
|
||||
if not custom_symbol:
|
||||
symbol_name = first_item.node().defaultSymbol()
|
||||
else:
|
||||
symbol_name = custom_symbol
|
||||
selected_symbol = symbol_name
|
||||
elif isinstance(first_item, PixmapNodeItem):
|
||||
self.uiSymbolLineEdit.setText(first_item.pixmapSymbolPath())
|
||||
|
||||
self.uiSymbolListWidget.setIconSize(QtCore.QSize(64, 64))
|
||||
symbol_resources = QtCore.QResource(":/symbols")
|
||||
for symbol in symbol_resources.children():
|
||||
if symbol.endswith(".normal.svg"):
|
||||
name = symbol[:-11]
|
||||
item = QtGui.QListWidgetItem(self.uiSymbolListWidget)
|
||||
if symbol.endswith(".svg"):
|
||||
name = os.path.splitext(symbol)[0]
|
||||
item = QtWidgets.QListWidgetItem(self.uiSymbolListWidget)
|
||||
item.setText(name)
|
||||
resource_path = ":/symbols/" + symbol
|
||||
svg_renderer = QtSvg.QSvgRenderer(resource_path)
|
||||
@@ -95,28 +90,47 @@ class SymbolSelectionDialog(QtGui.QDialog, Ui_SymbolSelectionDialog):
|
||||
current = self.uiSymbolListWidget.currentItem()
|
||||
if current:
|
||||
name = current.text()
|
||||
path = ":/symbols/{}.normal.svg".format(name)
|
||||
default_renderer = QtSvg.QSvgRenderer(path)
|
||||
default_renderer.setObjectName(path)
|
||||
path = ":/symbols/{}.selected.svg".format(name)
|
||||
hover_renderer = QtSvg.QSvgRenderer(path)
|
||||
hover_renderer.setObjectName(path)
|
||||
path = ":/symbols/{}.svg".format(name)
|
||||
renderer = QtSvg.QSvgRenderer(path)
|
||||
renderer.setObjectName(path)
|
||||
for item in self._items:
|
||||
item.setDefaultRenderer(default_renderer)
|
||||
item.setHoverRenderer(hover_renderer)
|
||||
if isinstance(item, SvgNodeItem):
|
||||
item.setSharedRenderer(renderer)
|
||||
else:
|
||||
log.warning("Built-in SVG symbol cannot be applied on Pixmap node item")
|
||||
|
||||
def getSymbols(self):
|
||||
symbol_path = self.uiSymbolLineEdit.text()
|
||||
pixmap = QtGui.QPixmap(symbol_path)
|
||||
if not pixmap.isNull():
|
||||
for item in self._items:
|
||||
if isinstance(item, PixmapNodeItem):
|
||||
item.setPixmap(pixmap)
|
||||
else:
|
||||
log.warning("Custom pixmap symbol cannot be applied on SVG node item")
|
||||
|
||||
current = self.uiSymbolListWidget.currentItem()
|
||||
if current:
|
||||
def getSymbol(self):
|
||||
|
||||
if self.uiSymbolListWidget.isEnabled():
|
||||
current = self.uiSymbolListWidget.currentItem()
|
||||
name = current.text()
|
||||
normal_symbol = ":/symbols/{}.normal.svg".format(name)
|
||||
selected_symbol = ":/symbols/{}.selected.svg".format(name)
|
||||
return normal_symbol, selected_symbol
|
||||
normal_symbol = ":/symbols/{}.svg".format(name)
|
||||
else:
|
||||
normal_symbol = self.uiSymbolLineEdit.text()
|
||||
return normal_symbol
|
||||
|
||||
def getCategory(self):
|
||||
def _symbolBrowserSlot(self):
|
||||
|
||||
return self.uiCategoryComboBox.itemData(self.uiCategoryComboBox.currentIndex())
|
||||
# supported image file formats
|
||||
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*.*)"
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Image", self._symbols_dir, file_formats)
|
||||
if not path:
|
||||
return
|
||||
|
||||
self._symbols_dir = os.path.dirname(path)
|
||||
self.uiSymbolListWidget.setEnabled(False)
|
||||
self.uiSymbolLineEdit.clear()
|
||||
self.uiSymbolLineEdit.setText(path)
|
||||
self.uiSymbolLineEdit.setToolTip('<img src="{}"/>'.format(path))
|
||||
|
||||
def done(self, result):
|
||||
"""
|
||||
@@ -127,4 +141,4 @@ class SymbolSelectionDialog(QtGui.QDialog, Ui_SymbolSelectionDialog):
|
||||
|
||||
if result and self._items:
|
||||
self._applyPreferencesSlot()
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
@@ -19,12 +19,11 @@
|
||||
Text editor to edit Note items.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets
|
||||
from ..ui.text_editor_dialog_ui import Ui_TextEditorDialog
|
||||
|
||||
|
||||
class TextEditorDialog(QtGui.QDialog, Ui_TextEditorDialog):
|
||||
|
||||
class TextEditorDialog(QtWidgets.QDialog, Ui_TextEditorDialog):
|
||||
"""
|
||||
Text editor dialog.
|
||||
|
||||
@@ -34,22 +33,20 @@ class TextEditorDialog(QtGui.QDialog, Ui_TextEditorDialog):
|
||||
|
||||
def __init__(self, parent, items):
|
||||
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._items = items
|
||||
self.uiFontPushButton.clicked.connect(self._setFontSlot)
|
||||
self.uiColorPushButton.clicked.connect(self._setColorSlot)
|
||||
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
|
||||
|
||||
# use the first item in the list as the model
|
||||
first_item = items[0]
|
||||
self._color = first_item.defaultTextColor()
|
||||
self._setColor(first_item.defaultTextColor())
|
||||
self.uiRotationSpinBox.setValue(first_item.rotation())
|
||||
self.uiColorPushButton.setStyleSheet("background-color: {}".format(self._color.name()))
|
||||
self.uiPlainTextEdit.setPlainText(first_item.toPlainText())
|
||||
self.uiPlainTextEdit.setFont(first_item.font())
|
||||
self.uiPlainTextEdit.setStyleSheet("color : {}".format(self._color.name()))
|
||||
|
||||
if not first_item.editable():
|
||||
self.uiPlainTextEdit.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
|
||||
@@ -58,12 +55,23 @@ class TextEditorDialog(QtGui.QDialog, Ui_TextEditorDialog):
|
||||
self.uiApplyTextToAllItemsCheckBox.setChecked(True)
|
||||
self.uiApplyTextToAllItemsCheckBox.hide()
|
||||
|
||||
def _setColor(self, color):
|
||||
self._color = color
|
||||
self.uiColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(color.red(),
|
||||
color.green(),
|
||||
color.blue(),
|
||||
color.alpha()))
|
||||
self.uiPlainTextEdit.setStyleSheet("color: rgba({}, {}, {}, {});".format(color.red(),
|
||||
color.green(),
|
||||
color.blue(),
|
||||
color.alpha()))
|
||||
|
||||
def _setFontSlot(self):
|
||||
"""
|
||||
Slot to select the font.
|
||||
"""
|
||||
|
||||
selected_font, ok = QtGui.QFontDialog.getFont(self.uiPlainTextEdit.font(), self)
|
||||
selected_font, ok = QtWidgets.QFontDialog.getFont(self.uiPlainTextEdit.font(), self)
|
||||
if ok:
|
||||
self.uiPlainTextEdit.setFont(selected_font)
|
||||
|
||||
@@ -72,11 +80,9 @@ class TextEditorDialog(QtGui.QDialog, Ui_TextEditorDialog):
|
||||
Slot to select the color.
|
||||
"""
|
||||
|
||||
color = QtGui.QColorDialog.getColor(self._color, self)
|
||||
color = QtWidgets.QColorDialog.getColor(self._color, self, None, QtWidgets.QColorDialog.ShowAlphaChannel)
|
||||
if color.isValid():
|
||||
self._color = color
|
||||
self.uiColorPushButton.setStyleSheet("background-color: {}".format(self._color.name()))
|
||||
self.uiPlainTextEdit.setStyleSheet("color : {}".format(self._color.name()))
|
||||
self._setColor(color)
|
||||
|
||||
def _applyPreferencesSlot(self):
|
||||
"""
|
||||
@@ -99,4 +105,4 @@ class TextEditorDialog(QtGui.QDialog, Ui_TextEditorDialog):
|
||||
|
||||
if result:
|
||||
self._applyPreferencesSlot()
|
||||
QtGui.QDialog.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
241
gns3/dialogs/vm_wizard.py
Normal file
241
gns3/dialogs/vm_wizard.py
Normal file
@@ -0,0 +1,241 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.servers import Servers
|
||||
|
||||
|
||||
class VMWizard(QtWidgets.QWizard):
|
||||
|
||||
"""
|
||||
Base class for VM wizard.
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
|
||||
if sys.platform.startswith("darwin"):
|
||||
# we want to see the cancel button on OSX
|
||||
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
|
||||
|
||||
self._server = Servers.instance().localServer()
|
||||
self.uiRemoteRadioButton.toggled.connect(self._remoteServerToggledSlot)
|
||||
self.uiVMRadioButton.toggled.connect(self._vmToggledSlot)
|
||||
self.uiLocalRadioButton.toggled.connect(self._localToggledSlot)
|
||||
self.uiLoadBalanceCheckBox.toggled.connect(self._loadBalanceToggledSlot)
|
||||
|
||||
# The list of images combo box (Qemu support multiple images)
|
||||
self._images_combo_boxes = set()
|
||||
|
||||
# The list of radio button for existing image or new images
|
||||
self._radio_existing_images_buttons = set()
|
||||
|
||||
def refreshImageStepsButtons(self):
|
||||
"""
|
||||
When changing the server type (remote or local)
|
||||
Refresh all the image selectors
|
||||
"""
|
||||
for radio_button in self._radio_existing_images_buttons:
|
||||
radio_button.setChecked(radio_button.isChecked())
|
||||
|
||||
def _vmToggledSlot(self, checked):
|
||||
"""
|
||||
Slot for when the VM radio button is toggled.
|
||||
|
||||
:param checked: either the button is checked or not
|
||||
"""
|
||||
if checked:
|
||||
self.uiRemoteServersGroupBox.setEnabled(False)
|
||||
self.uiRemoteServersGroupBox.hide()
|
||||
self.refreshImageStepsButtons()
|
||||
|
||||
def _remoteServerToggledSlot(self, checked):
|
||||
"""
|
||||
Slot for when the remote server radio button is toggled.
|
||||
|
||||
:param checked: either the button is checked or not
|
||||
"""
|
||||
|
||||
if checked:
|
||||
self.uiRemoteServersGroupBox.setEnabled(True)
|
||||
self.uiRemoteServersGroupBox.show()
|
||||
self.refreshImageStepsButtons()
|
||||
|
||||
def _localToggledSlot(self, checked):
|
||||
"""
|
||||
Slot for when the local server radio button is toggled.
|
||||
|
||||
:param checked: either the button is checked or not
|
||||
"""
|
||||
if checked:
|
||||
self.uiRemoteServersGroupBox.setEnabled(False)
|
||||
self.uiRemoteServersGroupBox.hide()
|
||||
self.refreshImageStepsButtons()
|
||||
|
||||
def setStartId(self, index):
|
||||
"""
|
||||
Which page should we use when starting the Wizard
|
||||
"""
|
||||
super().setStartId(index)
|
||||
# If we skip the initial page (choosing a server)
|
||||
# we check the settings
|
||||
if index != 0:
|
||||
self.uiLocalRadioButton.setChecked(True)
|
||||
|
||||
def initializePage(self, page_id):
|
||||
|
||||
if self.page(page_id) == self.uiServerWizardPage:
|
||||
self.uiRemoteServersComboBox.clear()
|
||||
for server in Servers.instance().remoteServers().values():
|
||||
self.uiRemoteServersComboBox.addItem(server.url(), server)
|
||||
|
||||
def validateCurrentPage(self):
|
||||
"""
|
||||
Validates the server.
|
||||
"""
|
||||
|
||||
if self.currentPage() == self.uiServerWizardPage:
|
||||
if self.uiRemoteRadioButton.isChecked():
|
||||
if not Servers.instance().remoteServers():
|
||||
QtWidgets.QMessageBox.critical(self, "Remote server", "There is no remote server registered in your preferences")
|
||||
return False
|
||||
self._server = self.uiRemoteServersComboBox.itemData(self.uiRemoteServersComboBox.currentIndex())
|
||||
elif self.uiVMRadioButton.isChecked():
|
||||
gns3_vm_server = Servers.instance().vmServer()
|
||||
if gns3_vm_server is None:
|
||||
QtWidgets.QMessageBox.critical(self, "GNS3 VM", "The GNS3 VM is not running")
|
||||
return False
|
||||
self._server = gns3_vm_server
|
||||
else:
|
||||
self._server = Servers.instance().localServer()
|
||||
return True
|
||||
|
||||
def _loadBalanceToggledSlot(self, checked):
|
||||
"""
|
||||
Slot for when the load balance checkbox is toggled.
|
||||
|
||||
:param checked: either the box is checked or not
|
||||
"""
|
||||
|
||||
if checked:
|
||||
self.uiRemoteServersComboBox.setEnabled(False)
|
||||
else:
|
||||
self.uiRemoteServersComboBox.setEnabled(True)
|
||||
|
||||
def addImageSelector(self, radio_button, combo_box, line_edit, browser, image_selector, create_button=None, create_image_wizard=None):
|
||||
"""
|
||||
Add a remote image selector
|
||||
|
||||
:param radio_button: Radio button which toggle display of the listbox
|
||||
:param combo_box: The image choice combo box
|
||||
:param line_edit: The edit for the image
|
||||
:param browser: file upload browser button
|
||||
:param image_selector: function which display an image selector and return path
|
||||
:param create_button: Image create button None if you don't need one
|
||||
:param create_image_wizard: Wizard Class for creating a new image
|
||||
"""
|
||||
|
||||
combo_box.currentIndexChanged.connect(lambda index: self._imageListIndexChangedSlot(index, combo_box, line_edit))
|
||||
self._images_combo_boxes.add(combo_box)
|
||||
|
||||
browser.clicked.connect(lambda: self._imageBrowserSlot(line_edit, image_selector))
|
||||
|
||||
if create_button:
|
||||
assert create_image_wizard is not None
|
||||
create_button.clicked.connect(lambda: self._imageCreateSlot(line_edit, create_image_wizard))
|
||||
|
||||
self._existingImageToggledSlot(True, combo_box, line_edit, browser, create_button)
|
||||
radio_button.toggled.connect(lambda checked: self._existingImageToggledSlot(checked, combo_box, line_edit, browser, create_button))
|
||||
self._radio_existing_images_buttons.add(radio_button)
|
||||
|
||||
def _imageCreateSlot(self, line_edit, create_image_wizard):
|
||||
create_dialog = create_image_wizard(self, self.uiNameLineEdit.text())
|
||||
if QtWidgets.QDialog.Accepted == create_dialog.exec_():
|
||||
line_edit.setText(create_dialog.uiLocationLineEdit.text())
|
||||
|
||||
def _imageBrowserSlot(self, line_edit, image_selector):
|
||||
"""
|
||||
Slot to open a file browser and select an image.
|
||||
"""
|
||||
|
||||
server = Servers.instance().getServerFromString(self.getSettings()["server"])
|
||||
path = image_selector(self, server)
|
||||
if not path:
|
||||
return
|
||||
line_edit.clear()
|
||||
line_edit.setText(path)
|
||||
|
||||
def _imageListIndexChangedSlot(self, index, combo_box, line_edit):
|
||||
"""
|
||||
User select a different image in the combo box
|
||||
"""
|
||||
item = combo_box.itemData(index)
|
||||
if item and item["filename"]:
|
||||
line_edit.setText(item["filename"])
|
||||
else:
|
||||
line_edit.setText("")
|
||||
|
||||
def _existingImageToggledSlot(self, checked, combo_box, line_edit, browser, create_button):
|
||||
"""
|
||||
User select the option of using an existing image
|
||||
"""
|
||||
|
||||
if create_button:
|
||||
create_button.hide()
|
||||
|
||||
if checked:
|
||||
combo_box.show()
|
||||
browser.hide()
|
||||
line_edit.hide()
|
||||
if combo_box.count() > 0:
|
||||
line_edit.setText(combo_box.itemData(combo_box.currentIndex())["filename"])
|
||||
else:
|
||||
combo_box.hide()
|
||||
line_edit.setText("")
|
||||
line_edit.show()
|
||||
browser.show()
|
||||
if create_button and self.uiLocalRadioButton.isChecked():
|
||||
create_button.show()
|
||||
|
||||
def loadImagesList(self, endpoint):
|
||||
"""
|
||||
Fill the list box with available Images"
|
||||
|
||||
:param endpoint: server endpoint with the list of Images
|
||||
"""
|
||||
|
||||
self._server.get(endpoint, self._getImagesFromServerCallback)
|
||||
|
||||
def _getImagesFromServerCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
Callback for loadImagesList.
|
||||
|
||||
:param result: server response
|
||||
:param error: indicates an error (boolean)
|
||||
"""
|
||||
|
||||
if error:
|
||||
QtWidgets.QMessageBox.critical(self, "Images", "Error while getting the VMs: {}".format(result["message"]))
|
||||
return
|
||||
|
||||
for combo_box in self._images_combo_boxes:
|
||||
combo_box.clear()
|
||||
for vm in result:
|
||||
combo_box.addItem(vm["filename"], vm)
|
||||
171
gns3/gns3_vm.py
Normal file
171
gns3/gns3_vm.py
Normal file
@@ -0,0 +1,171 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Manages the GNS3 VM.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from .qt import QtNetwork
|
||||
from .servers import Servers
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GNS3VM:
|
||||
|
||||
"""
|
||||
GNS3 VM management class.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self._is_running = False
|
||||
|
||||
def settings(self):
|
||||
"""
|
||||
Returns the GNS3 VM settings.
|
||||
|
||||
:returns: GNS3 VM settings (dict)
|
||||
"""
|
||||
|
||||
return Servers.instance().vmSettings()
|
||||
|
||||
def setSettings(self, settings):
|
||||
"""
|
||||
Set new GNS3 VM settings.
|
||||
|
||||
:param settings: GNS3 VM settings (dict)
|
||||
"""
|
||||
|
||||
Servers.instance().setVMsettings(settings)
|
||||
|
||||
@staticmethod
|
||||
def execute_vmrun(subcommand, args, timeout=60):
|
||||
|
||||
from gns3.modules.vmware import VMware
|
||||
vmware_settings = VMware.instance().settings()
|
||||
vmrun_path = vmware_settings["vmrun_path"]
|
||||
if sys.platform.startswith("darwin"):
|
||||
command = [vmrun_path, "-T", "fusion", subcommand]
|
||||
else:
|
||||
host_type = vmware_settings["host_type"]
|
||||
command = [vmrun_path, "-T", host_type, subcommand]
|
||||
command.extend(args)
|
||||
log.debug("Executing vmrun with command: {}".format(command))
|
||||
output = subprocess.check_output(command, timeout=timeout)
|
||||
return output.decode("utf-8", errors="ignore").strip()
|
||||
|
||||
@staticmethod
|
||||
def execute_vboxmanage(subcommand, args, timeout=60):
|
||||
|
||||
from gns3.modules.virtualbox import VirtualBox
|
||||
virtualbox_settings = VirtualBox.instance().settings()
|
||||
vboxmanage_path = virtualbox_settings["vboxmanage_path"]
|
||||
command = [vboxmanage_path, "--nologo", subcommand]
|
||||
command.extend(args)
|
||||
log.debug("Executing VBoxManage with command: {}".format(command))
|
||||
output = subprocess.check_output(command, timeout=timeout)
|
||||
return output.decode("utf-8", errors="ignore").strip()
|
||||
|
||||
def autoStart(self):
|
||||
"""
|
||||
Automatically start the GNS3 VM at startup.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
vm_settings = Servers.instance().vmSettings()
|
||||
return vm_settings["auto_start"]
|
||||
|
||||
def adjustLocalServerIP(self):
|
||||
"""
|
||||
Adjust the local server IP address to be in the same subnet as the GNS3 VM.
|
||||
|
||||
:returns: the local server IP/host address
|
||||
"""
|
||||
|
||||
servers = Servers.instance()
|
||||
local_server_settings = servers.localServerSettings()
|
||||
if Servers.instance().vmSettings()["adjust_local_server_ip"]:
|
||||
vm_server = servers.vmServer()
|
||||
vm_ip_address = vm_server.host()
|
||||
log.debug("GNS3 VM IP address is {}".format(vm_ip_address))
|
||||
|
||||
for interface in QtNetwork.QNetworkInterface.allInterfaces():
|
||||
for address in interface.addressEntries():
|
||||
ip = address.ip().toString()
|
||||
prefix_length = address.prefixLength()
|
||||
subnet = QtNetwork.QHostAddress.parseSubnet("{}/{}".format(ip, prefix_length))
|
||||
if QtNetwork.QHostAddress(vm_ip_address).isInSubnet(subnet):
|
||||
if local_server_settings["host"] != ip:
|
||||
log.info("Adjust local server IP address to {}".format(ip))
|
||||
servers.setLocalServerSettings({"host": ip})
|
||||
servers.registerLocalServer()
|
||||
servers.save()
|
||||
return ip
|
||||
return local_server_settings["host"]
|
||||
|
||||
def setRunning(self, value):
|
||||
"""
|
||||
Sets either the GNS3 VM is running or not.
|
||||
|
||||
:param value: boolean
|
||||
"""
|
||||
|
||||
self._is_running = value
|
||||
|
||||
def isRunning(self):
|
||||
"""
|
||||
Returns either the GNS3 VM is running or not.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return self._is_running
|
||||
|
||||
def shutdown(self, force=False):
|
||||
"""
|
||||
Gracefully shutdowns the GNS3 VM.
|
||||
"""
|
||||
|
||||
vm_settings = self.settings()
|
||||
if self._is_running and (vm_settings["auto_stop"] or force):
|
||||
try:
|
||||
if vm_settings["virtualization"] == "VMware":
|
||||
self.execute_vmrun("stop", [vm_settings["vmx_path"], "soft"])
|
||||
elif vm_settings["virtualization"] == "VirtualBox":
|
||||
self.execute_vboxmanage("controlvm", [vm_settings["vmname"], "acpipowerbutton"], timeout=3)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
pass
|
||||
except subprocess.TimeoutExpired:
|
||||
log.warning("Could not ACPI shutdown the VM (timeout expired)")
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
"""
|
||||
Singleton to return only on instance of GNS3VM
|
||||
|
||||
:returns: instance of GNS3VM
|
||||
"""
|
||||
|
||||
if not hasattr(GNS3VM, "_instance") or GNS3VM._instance is None:
|
||||
GNS3VM._instance = GNS3VM()
|
||||
return GNS3VM._instance
|
||||
@@ -24,16 +24,18 @@ import os
|
||||
import pickle
|
||||
import functools
|
||||
|
||||
from .qt import QtCore, QtGui, QtNetwork
|
||||
from .qt import QtCore, QtGui, QtSvg, QtNetwork, QtWidgets
|
||||
from .servers import Servers
|
||||
from .items.node_item import NodeItem
|
||||
from .dialogs.node_configurator_dialog import NodeConfiguratorDialog
|
||||
from .items.svg_node_item import SvgNodeItem
|
||||
from .items.pixmap_node_item import PixmapNodeItem
|
||||
from .dialogs.node_properties_dialog import NodePropertiesDialog
|
||||
from .link import Link
|
||||
from .node import Node
|
||||
from .modules import MODULES
|
||||
from .modules.builtin.cloud import Cloud
|
||||
from .modules.module_error import ModuleError
|
||||
from .settings import GRAPHICS_VIEW_SETTINGS, GRAPHICS_VIEW_SETTING_TYPES
|
||||
from .settings import GRAPHICS_VIEW_SETTINGS
|
||||
from .topology import Topology
|
||||
from .ports.port import Port
|
||||
from .dialogs.style_editor_dialog import StyleEditorDialog
|
||||
@@ -41,6 +43,7 @@ from .dialogs.text_editor_dialog import TextEditorDialog
|
||||
from .dialogs.symbol_selection_dialog import SymbolSelectionDialog
|
||||
from .dialogs.idlepc_dialog import IdlePCDialog
|
||||
from .local_config import LocalConfig
|
||||
from .progress import Progress
|
||||
|
||||
# link items
|
||||
from .items.link_item import LinkItem
|
||||
@@ -53,11 +56,13 @@ from .items.shape_item import ShapeItem
|
||||
from .items.rectangle_item import RectangleItem
|
||||
from .items.ellipse_item import EllipseItem
|
||||
from .items.image_item import ImageItem
|
||||
from .items.pixmap_image_item import PixmapImageItem
|
||||
from .items.svg_image_item import SvgImageItem
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GraphicsView(QtGui.QGraphicsView):
|
||||
class GraphicsView(QtWidgets.QGraphicsView):
|
||||
|
||||
"""
|
||||
Graphics view that displays the scene.
|
||||
@@ -67,11 +72,10 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
# Our parent is the central widget which parent
|
||||
# is the main window.
|
||||
# Our parent is the central widget which parent is the main window.
|
||||
self._main_window = parent.parent()
|
||||
|
||||
QtGui.QGraphicsView.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
self._settings = {}
|
||||
self._loadSettings()
|
||||
|
||||
@@ -83,22 +87,28 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
self._dragging = False
|
||||
self._last_mouse_position = None
|
||||
self._topology = Topology.instance()
|
||||
self._background_warning_msgbox = QtGui.QErrorMessage(self)
|
||||
self._background_warning_msgbox = QtWidgets.QErrorMessage(self)
|
||||
self._background_warning_msgbox.setWindowTitle("Layer position")
|
||||
|
||||
# set the scene
|
||||
scene = QtGui.QGraphicsScene(parent=self)
|
||||
scene = QtWidgets.QGraphicsScene(parent=self)
|
||||
width = self._settings["scene_width"]
|
||||
height = self._settings["scene_height"]
|
||||
scene.setSceneRect(-(width / 2), -(height / 2), width, height)
|
||||
self.setScene(scene)
|
||||
|
||||
# set the custom flags for this view
|
||||
self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
|
||||
self.setCacheMode(QtGui.QGraphicsView.CacheBackground)
|
||||
self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
|
||||
self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
|
||||
self.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
|
||||
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
|
||||
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
|
||||
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorViewCenter)
|
||||
|
||||
# default directories for QFileDialog
|
||||
self._import_configs_from_dir = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DocumentsLocation)
|
||||
self._import_config_dir = ""
|
||||
self._export_configs_to_dir = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DocumentsLocation)
|
||||
self._export_config_dir = ""
|
||||
|
||||
self._local_addresses = ['0.0.0.0', '127.0.0.1', 'localhost', '::1', '0:0:0:0:0:0:0:1', '::', QtNetwork.QHostInfo.localHostName()]
|
||||
|
||||
@@ -133,21 +143,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
Loads the settings from the persistent settings file.
|
||||
"""
|
||||
|
||||
local_config = LocalConfig.instance()
|
||||
# restore the graphics view settings from QSettings (for backward compatibility)
|
||||
legacy_settings = {}
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.__class__.__name__)
|
||||
for name in GRAPHICS_VIEW_SETTINGS.keys():
|
||||
if settings.contains(name):
|
||||
legacy_settings[name] = settings.value(name, type=GRAPHICS_VIEW_SETTING_TYPES[name])
|
||||
settings.remove("")
|
||||
settings.endGroup()
|
||||
|
||||
if legacy_settings:
|
||||
local_config.saveSectionSettings(self.__class__.__name__, legacy_settings)
|
||||
|
||||
self._settings = local_config.loadSectionSettings(self.__class__.__name__, GRAPHICS_VIEW_SETTINGS)
|
||||
self._settings = LocalConfig.instance().loadSectionSettings(self.__class__.__name__, GRAPHICS_VIEW_SETTINGS)
|
||||
|
||||
def settings(self):
|
||||
"""
|
||||
@@ -228,15 +224,19 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
self._adding_ellipse = False
|
||||
self.setCursor(QtCore.Qt.ArrowCursor)
|
||||
|
||||
def addImage(self, pixmap, image_path):
|
||||
def addImage(self, image, image_path):
|
||||
"""
|
||||
Adds an image.
|
||||
|
||||
:param pixmap: QPixmap instance
|
||||
:param image: QPixmap or QSvgRenderer instance
|
||||
:param image_path: path to the image
|
||||
"""
|
||||
|
||||
image_item = ImageItem(pixmap, image_path)
|
||||
if isinstance(image, QtSvg.QSvgRenderer):
|
||||
# use a SVG image item if this is a valid SVG file
|
||||
image_item = SvgImageItem(image, image_path)
|
||||
else:
|
||||
image_item = PixmapImageItem(image, image_path)
|
||||
# center the image on the scene
|
||||
x = image_item.pos().x() - (image_item.boundingRect().width() / 2)
|
||||
y = image_item.pos().y() - (image_item.boundingRect().height() / 2)
|
||||
@@ -359,13 +359,13 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
if not source_port:
|
||||
return
|
||||
if not source_item.node().initialized():
|
||||
QtGui.QMessageBox.critical(self, "Connection", "This node hasn't been initialized correctly")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "This node hasn't been initialized correctly")
|
||||
return
|
||||
if not source_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Port {} isn't free".format(source_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Port {} isn't free".format(source_port.name()))
|
||||
return
|
||||
if not source_port.isHotPluggable() and source_item.node().status() == Node.started:
|
||||
QtGui.QMessageBox.critical(self, "Connection", "A new link cannot be added because {} is running".format(source_item.node().name()))
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "A new link cannot be added because {} is running".format(source_item.node().name()))
|
||||
return
|
||||
if source_port.linkType() == "Serial":
|
||||
self._newlink = SerialLinkItem(source_item, source_port, self.mapToScene(event.pos()), None, adding_flag=True)
|
||||
@@ -377,42 +377,46 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
source_port = self._newlink.sourcePort()
|
||||
destination_item = item
|
||||
if source_item == destination_item:
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Cannot connect to itself!")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Cannot connect to itself!")
|
||||
return
|
||||
destination_port = destination_item.connectToPort()
|
||||
if not destination_port:
|
||||
return
|
||||
if not destination_item.node().initialized():
|
||||
QtGui.QMessageBox.critical(self, "Connection", "This node hasn't been initialized correctly")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "This node hasn't been initialized correctly")
|
||||
return
|
||||
if not destination_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Port {} isn't free".format(destination_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Port {} isn't free".format(destination_port.name()))
|
||||
return
|
||||
if not destination_port.isHotPluggable() and destination_item.node().status() == Node.started:
|
||||
QtGui.QMessageBox.critical(self, "Connection", "A new link cannot be added because {} is running".format(destination_item.node().name()))
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "A new link cannot be added because {} is running".format(destination_item.node().name()))
|
||||
return
|
||||
if source_port.isStub() or destination_port.isStub():
|
||||
pass
|
||||
elif source_port.linkType() != destination_port.linkType():
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Cannot connect this port!")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Cannot connect this port!")
|
||||
return
|
||||
|
||||
if source_item.node().server().protocol() != destination_item.node().server().protocol():
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Sorry, you cannot connect a device running on an insecure server to a device running on a secure server.")
|
||||
return
|
||||
|
||||
if isinstance(source_item.node(), Cloud) and isinstance(destination_item.node(), Cloud):
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Sorry, you cannot connect a cloud to another cloud!")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Sorry, you cannot connect a cloud to another cloud!")
|
||||
return
|
||||
|
||||
source_host = source_item.node().server().host
|
||||
destination_host = destination_item.node().server().host
|
||||
source_host = source_item.node().server().host()
|
||||
destination_host = destination_item.node().server().host()
|
||||
|
||||
# check that the node can be connected to a cloud
|
||||
if (isinstance(source_item.node(), Cloud) or isinstance(destination_item.node(), Cloud)) and source_host != destination_host:
|
||||
QtGui.QMessageBox.critical(self, "Connection", "This device can only be connected to a cloud on the same host")
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "This device can only be connected to a cloud on the same host")
|
||||
return
|
||||
|
||||
# check if the 2 nodes can communicate
|
||||
if (source_host in self._local_addresses and destination_host not in self._local_addresses) or \
|
||||
(destination_host in self._local_addresses and source_host not in self._local_addresses):
|
||||
QtGui.QMessageBox.critical(self, "Connection", "Server {} cannot communicate with server {}, most likely because your local server host binding is set to a local address".format(source_host, destination_host))
|
||||
QtWidgets.QMessageBox.critical(self, "Connection", "Server {} cannot communicate with server {}, most likely because your local server host binding is set to a local address".format(source_host, destination_host))
|
||||
return
|
||||
|
||||
if self._newlink in self.scene().items():
|
||||
@@ -472,7 +476,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
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)
|
||||
QtGui.QApplication.sendEvent(self._main_window, key)
|
||||
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)
|
||||
elif event.button() == QtCore.Qt.LeftButton and self._adding_note:
|
||||
@@ -502,7 +506,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
self.setCursor(QtCore.Qt.ArrowCursor)
|
||||
self._adding_ellipse = False
|
||||
else:
|
||||
QtGui.QGraphicsView.mousePressEvent(self, event)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
"""
|
||||
@@ -520,7 +524,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
else:
|
||||
if item is not None and not event.modifiers() & QtCore.Qt.ControlModifier:
|
||||
item.setSelected(True)
|
||||
QtGui.QGraphicsView.mouseReleaseEvent(self, event)
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
def wheelEvent(self, event):
|
||||
"""
|
||||
@@ -529,18 +533,21 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
:param: QWheelEvent instance
|
||||
"""
|
||||
|
||||
if event.modifiers() == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical:
|
||||
# CTRL is pressed then use the mouse wheel to zoom in or out.
|
||||
self.scaleView(pow(2.0, event.delta() / 240.0))
|
||||
if event.modifiers() == QtCore.Qt.ControlModifier:
|
||||
# event.delta() added for Qt4 compatibility
|
||||
delta = event.angleDelta() if hasattr(event, 'angleDelta') else event.delta()
|
||||
if delta is not None and delta.x() == 0:
|
||||
# CTRL is pressed then use the mouse wheel to zoom in or out.
|
||||
self.scaleView(pow(2.0, delta.y() / 240.0))
|
||||
else:
|
||||
QtGui.QGraphicsView.wheelEvent(self, event)
|
||||
super().wheelEvent(event)
|
||||
|
||||
def scaleView(self, scale_factor):
|
||||
"""
|
||||
Scales the view (zoom in and out).
|
||||
"""
|
||||
|
||||
factor = self.matrix().scale(scale_factor, scale_factor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width()
|
||||
factor = self.transform().scale(scale_factor, scale_factor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width()
|
||||
if (factor < 0.10 or factor > 10):
|
||||
return
|
||||
self.scale(scale_factor, scale_factor)
|
||||
@@ -556,12 +563,10 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
# check if we are editing an NoteItem instance, then send the delete key event to it
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NoteItem) and item.hasFocus():
|
||||
QtGui.QGraphicsView.keyPressEvent(self, event)
|
||||
super().keyPressEvent(event)
|
||||
return
|
||||
self.deleteActionSlot()
|
||||
QtGui.QGraphicsView.keyPressEvent(self, event)
|
||||
else:
|
||||
QtGui.QGraphicsView.keyPressEvent(self, event)
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""
|
||||
@@ -578,7 +583,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
hBar = self.horizontalScrollBar()
|
||||
vBar = self.verticalScrollBar()
|
||||
delta = mapped_global_pos - self._last_mouse_position
|
||||
hBar.setValue(hBar.value() + (delta.x() if QtGui.QApplication.isRightToLeft() else -delta.x()))
|
||||
hBar.setValue(hBar.value() + (delta.x() if QtWidgets.QApplication.isRightToLeft() else -delta.x()))
|
||||
vBar.setValue(vBar.value() - delta.y())
|
||||
self._last_mouse_position = mapped_global_pos
|
||||
if self._adding_link and self._newlink and self._newlink in self.scene().items():
|
||||
@@ -591,7 +596,12 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
# show item coords in the status bar
|
||||
coords = "X: {} Y: {} Z: {}".format(item.x(), item.y(), item.zValue())
|
||||
self._main_window.uiStatusBar.showMessage(coords, 2000)
|
||||
QtGui.QGraphicsView.mouseMoveEvent(self, event)
|
||||
|
||||
# force the children to redraw because of a problem with QGraphicsEffect
|
||||
for item in self.scene().selectedItems():
|
||||
for child in item.childItems():
|
||||
child.update()
|
||||
super().mouseMoveEvent(event)
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
"""
|
||||
@@ -601,26 +611,36 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
"""
|
||||
|
||||
item = self.itemAt(event.pos())
|
||||
if not self._adding_link and isinstance(item, NodeItem) and item.node().initialized():
|
||||
item.setSelected(True)
|
||||
if isinstance(item, NodeItem):
|
||||
self.consoleToNode(item.node())
|
||||
else:
|
||||
self.configureSlot()
|
||||
|
||||
if not self._adding_link:
|
||||
if isinstance(item, NodeItem) and item.node().initialized():
|
||||
item.setSelected(True)
|
||||
if item.node().status() == Node.stopped:
|
||||
self.configureSlot()
|
||||
return
|
||||
else:
|
||||
self.consoleFromItems(self.scene().selectedItems())
|
||||
return
|
||||
elif isinstance(item, NoteItem) and isinstance(item.parentItem(), NodeItem):
|
||||
if item.parentItem().node().initialized():
|
||||
item.parentItem().setSelected(True)
|
||||
self.changeHostnameActionSlot()
|
||||
return
|
||||
else:
|
||||
QtGui.QGraphicsView.mouseDoubleClickEvent(self, event)
|
||||
super().mouseDoubleClickEvent(event)
|
||||
|
||||
def configureSlot(self, items=None):
|
||||
"""
|
||||
Opens the node configurator.
|
||||
Opens the node properties dialog.
|
||||
"""
|
||||
|
||||
if not items:
|
||||
items = self.scene().selectedItems()
|
||||
node_configurator = NodeConfiguratorDialog(items, self._main_window)
|
||||
node_configurator.setModal(True)
|
||||
node_configurator.show()
|
||||
node_configurator.exec_()
|
||||
with Progress.instance().context(min_duration=0):
|
||||
node_properties = NodePropertiesDialog(items, self._main_window)
|
||||
node_properties.setModal(True)
|
||||
node_properties.show()
|
||||
node_properties.exec_()
|
||||
for item in items:
|
||||
item.setSelected(False)
|
||||
|
||||
@@ -655,7 +675,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
if event.keyboardModifiers() == QtCore.Qt.ShiftModifier:
|
||||
max_nodes_per_line = 10 # max number of nodes on a single line
|
||||
offset = 100 # spacing between elements
|
||||
integer, ok = QtGui.QInputDialog.getInteger(self, "Nodes", "Number of nodes:", 2, 1, 100, 1)
|
||||
integer, ok = QtWidgets.QInputDialog.getInt(self, "Nodes", "Number of nodes:", 2, 1, 100, 1)
|
||||
if ok:
|
||||
for node_number in range(integer):
|
||||
node_item = self.createNode(node_data, event.pos())
|
||||
@@ -672,7 +692,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
if len(event.mimeData().urls()) == 0:
|
||||
return
|
||||
if len(event.mimeData().urls()) > 1:
|
||||
QtGui.QMessageBox.critical(self, "Project files", "Please drop only one file")
|
||||
QtWidgets.QMessageBox.critical(self, "Project files", "Please drop only one file")
|
||||
return
|
||||
path = event.mimeData().urls()[0].toLocalFile()
|
||||
if os.path.isfile(path) and self._main_window.checkForUnsavedChanges():
|
||||
@@ -688,7 +708,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
:param pos: position where to display the menu
|
||||
"""
|
||||
|
||||
menu = QtGui.QMenu()
|
||||
menu = QtWidgets.QMenu()
|
||||
self.populateDeviceContextualMenu(menu)
|
||||
menu.exec_(pos)
|
||||
menu.clear()
|
||||
@@ -705,109 +725,116 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
return
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem), items)):
|
||||
configure_action = QtGui.QAction("Configure", menu)
|
||||
configure_action = QtWidgets.QAction("Configure", menu)
|
||||
configure_action.setIcon(QtGui.QIcon(':/icons/configuration.svg'))
|
||||
configure_action.triggered.connect(self.configureActionSlot)
|
||||
menu.addAction(configure_action)
|
||||
|
||||
# Action: Change hostname
|
||||
change_hostname_action = QtGui.QAction("Change hostname", menu)
|
||||
change_hostname_action = QtWidgets.QAction("Change hostname", menu)
|
||||
change_hostname_action.setIcon(QtGui.QIcon(':/icons/show-hostname.svg'))
|
||||
self.connect(change_hostname_action, QtCore.SIGNAL('triggered()'), self.changeHostnameActionSlot)
|
||||
change_hostname_action.triggered.connect(self.changeHostnameActionSlot)
|
||||
menu.addAction(change_hostname_action)
|
||||
|
||||
# Action: Change symbol
|
||||
change_symbol_action = QtGui.QAction("Change symbol", menu)
|
||||
change_symbol_action = QtWidgets.QAction("Change symbol", menu)
|
||||
change_symbol_action.setIcon(QtGui.QIcon(':/icons/node_conception.svg'))
|
||||
self.connect(change_symbol_action, QtCore.SIGNAL('triggered()'), self.changeSymbolActionSlot)
|
||||
change_symbol_action.triggered.connect(self.changeSymbolActionSlot)
|
||||
menu.addAction(change_symbol_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "vmDir"), items)):
|
||||
# Action: Show in file manager
|
||||
show_in_file_manager_action = QtWidgets.QAction("Show in file manager", menu)
|
||||
show_in_file_manager_action.setIcon(QtGui.QIcon(':/icons/open.svg'))
|
||||
show_in_file_manager_action.triggered.connect(self.showInFileManagerSlot)
|
||||
menu.addAction(show_in_file_manager_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "console"), items)):
|
||||
console_action = QtGui.QAction("Console", menu)
|
||||
console_action = QtWidgets.QAction("Console", menu)
|
||||
console_action.setIcon(QtGui.QIcon(':/icons/console.svg'))
|
||||
console_action.triggered.connect(self.consoleActionSlot)
|
||||
menu.addAction(console_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "auxConsole"), items)):
|
||||
aux_console_action = QtGui.QAction("Auxiliary console", menu)
|
||||
aux_console_action = QtWidgets.QAction("Auxiliary console", menu)
|
||||
aux_console_action.setIcon(QtGui.QIcon(':/icons/aux-console.svg'))
|
||||
aux_console_action.triggered.connect(self.auxConsoleActionSlot)
|
||||
menu.addAction(aux_console_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "importConfig"), items)):
|
||||
import_config_action = QtGui.QAction("Import config", menu)
|
||||
import_config_action = QtWidgets.QAction("Import config", menu)
|
||||
import_config_action.setIcon(QtGui.QIcon(':/icons/import_config.svg'))
|
||||
import_config_action.triggered.connect(self.importConfigActionSlot)
|
||||
menu.addAction(import_config_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "exportConfig"), items)):
|
||||
export_config_action = QtGui.QAction("Export config", menu)
|
||||
export_config_action = QtWidgets.QAction("Export config", menu)
|
||||
export_config_action.setIcon(QtGui.QIcon(':/icons/export_config.svg'))
|
||||
export_config_action.triggered.connect(self.exportConfigActionSlot)
|
||||
menu.addAction(export_config_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "saveConfig"), items)):
|
||||
save_config_action = QtGui.QAction("Save config", menu)
|
||||
save_config_action = QtWidgets.QAction("Save config", menu)
|
||||
save_config_action.setIcon(QtGui.QIcon(':/icons/save.svg'))
|
||||
save_config_action.triggered.connect(self.saveConfigActionSlot)
|
||||
menu.addAction(save_config_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "startPacketCapture"), items)):
|
||||
capture_action = QtGui.QAction("Capture", menu)
|
||||
capture_action = QtWidgets.QAction("Capture", menu)
|
||||
capture_action.setIcon(QtGui.QIcon(':/icons/inspect.svg'))
|
||||
capture_action.triggered.connect(self.captureActionSlot)
|
||||
menu.addAction(capture_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "idlepc"), items)):
|
||||
idlepc_action = QtGui.QAction("Idle-PC", menu)
|
||||
idlepc_action = QtWidgets.QAction("Idle-PC", menu)
|
||||
idlepc_action.setIcon(QtGui.QIcon(':/icons/calculate.svg'))
|
||||
idlepc_action.triggered.connect(self.idlepcActionSlot)
|
||||
menu.addAction(idlepc_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "idlepc"), items)):
|
||||
auto_idlepc_action = QtGui.QAction("Auto Idle-PC", menu)
|
||||
auto_idlepc_action = QtWidgets.QAction("Auto Idle-PC", menu)
|
||||
auto_idlepc_action.setIcon(QtGui.QIcon(':/icons/calculate.svg'))
|
||||
auto_idlepc_action.triggered.connect(self.autoIdlepcActionSlot)
|
||||
menu.addAction(auto_idlepc_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "start"), items)):
|
||||
start_action = QtGui.QAction("Start", menu)
|
||||
start_action = QtWidgets.QAction("Start", menu)
|
||||
start_action.setIcon(QtGui.QIcon(':/icons/start.svg'))
|
||||
start_action.triggered.connect(self.startActionSlot)
|
||||
menu.addAction(start_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "suspend"), items)):
|
||||
suspend_action = QtGui.QAction("Suspend", menu)
|
||||
suspend_action = QtWidgets.QAction("Suspend", menu)
|
||||
suspend_action.setIcon(QtGui.QIcon(':/icons/pause.svg'))
|
||||
suspend_action.triggered.connect(self.suspendActionSlot)
|
||||
menu.addAction(suspend_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "stop"), items)):
|
||||
stop_action = QtGui.QAction("Stop", menu)
|
||||
stop_action = QtWidgets.QAction("Stop", menu)
|
||||
stop_action.setIcon(QtGui.QIcon(':/icons/stop.svg'))
|
||||
stop_action.triggered.connect(self.stopActionSlot)
|
||||
menu.addAction(stop_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "reload"), items)):
|
||||
reload_action = QtGui.QAction("Reload", menu)
|
||||
reload_action = QtWidgets.QAction("Reload", menu)
|
||||
reload_action.setIcon(QtGui.QIcon(':/icons/reload.svg'))
|
||||
reload_action.triggered.connect(self.reloadActionSlot)
|
||||
menu.addAction(reload_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NoteItem) or isinstance(item, ShapeItem) or isinstance(item, ImageItem), items)):
|
||||
duplicate_action = QtGui.QAction("Duplicate", menu)
|
||||
duplicate_action = QtWidgets.QAction("Duplicate", menu)
|
||||
duplicate_action.setIcon(QtGui.QIcon(':/icons/new.svg'))
|
||||
duplicate_action.triggered.connect(self.duplicateActionSlot)
|
||||
menu.addAction(duplicate_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NoteItem), items)):
|
||||
text_edit_action = QtGui.QAction("Text edit", menu)
|
||||
text_edit_action = QtWidgets.QAction("Text edit", menu)
|
||||
text_edit_action.setIcon(QtGui.QIcon(':/icons/show-hostname.svg')) # TODO: change icon for text edit
|
||||
text_edit_action.triggered.connect(self.textEditActionSlot)
|
||||
menu.addAction(text_edit_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, ShapeItem), items)):
|
||||
style_action = QtGui.QAction("Style", menu)
|
||||
style_action = QtWidgets.QAction("Style", menu)
|
||||
style_action.setIcon(QtGui.QIcon(':/icons/drawing.svg'))
|
||||
style_action.triggered.connect(self.styleActionSlot)
|
||||
menu.addAction(style_action)
|
||||
@@ -816,27 +843,27 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
if True in list(map(lambda item: item.parentItem() is None, items)):
|
||||
|
||||
if len(items) > 1:
|
||||
horizontal_align_action = QtGui.QAction("Align horizontally", menu)
|
||||
horizontal_align_action = QtWidgets.QAction("Align horizontally", menu)
|
||||
horizontal_align_action.setIcon(QtGui.QIcon(':/icons/horizontally.svg'))
|
||||
horizontal_align_action.triggered.connect(self.horizontalAlignmentSlot)
|
||||
menu.addAction(horizontal_align_action)
|
||||
|
||||
vertical_align_action = QtGui.QAction("Align vertically", menu)
|
||||
vertical_align_action = QtWidgets.QAction("Align vertically", menu)
|
||||
vertical_align_action.setIcon(QtGui.QIcon(':/icons/vertically.svg'))
|
||||
vertical_align_action.triggered.connect(self.verticalAlignmentSlot)
|
||||
menu.addAction(vertical_align_action)
|
||||
|
||||
raise_layer_action = QtGui.QAction("Raise one layer", menu)
|
||||
raise_layer_action = QtWidgets.QAction("Raise one layer", menu)
|
||||
raise_layer_action.setIcon(QtGui.QIcon(':/icons/raise_z_value.svg'))
|
||||
raise_layer_action.triggered.connect(self.raiseLayerActionSlot)
|
||||
menu.addAction(raise_layer_action)
|
||||
|
||||
lower_layer_action = QtGui.QAction("Lower one layer", menu)
|
||||
lower_layer_action = QtWidgets.QAction("Lower one layer", menu)
|
||||
lower_layer_action.setIcon(QtGui.QIcon(':/icons/lower_z_value.svg'))
|
||||
lower_layer_action.triggered.connect(self.lowerLayerActionSlot)
|
||||
menu.addAction(lower_layer_action)
|
||||
|
||||
delete_action = QtGui.QAction("Delete", menu)
|
||||
delete_action = QtWidgets.QAction("Delete", menu)
|
||||
delete_action.setIcon(QtGui.QIcon(':/icons/delete.svg'))
|
||||
delete_action.triggered.connect(self.deleteActionSlot)
|
||||
menu.addAction(delete_action)
|
||||
@@ -903,11 +930,11 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem) and item.node().initialized():
|
||||
new_hostname, ok = QtGui.QInputDialog.getText(self, "Change hostname", "Hostname:", QtGui.QLineEdit.Normal, item.node().name())
|
||||
new_hostname, ok = QtWidgets.QInputDialog.getText(self, "Change hostname", "Hostname:", QtWidgets.QLineEdit.Normal, item.node().name())
|
||||
if ok:
|
||||
if hasattr(item.node(), "validateHostname"):
|
||||
if not item.node().validateHostname(new_hostname):
|
||||
QtGui.QMessageBox.critical(self, "Change hostname", "Invalid name detected for this node: {}".format(new_hostname))
|
||||
QtWidgets.QMessageBox.critical(self, "Change hostname", "Invalid name detected for this node: {}".format(new_hostname))
|
||||
continue
|
||||
item.node().update({"name": new_hostname})
|
||||
|
||||
@@ -926,6 +953,29 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
dialog.show()
|
||||
dialog.exec_()
|
||||
|
||||
def showInFileManagerSlot(self):
|
||||
"""
|
||||
Slot to receive events from the show in file manager action in the
|
||||
contextual menu.
|
||||
"""
|
||||
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "vmDir") and item.node().initialized():
|
||||
node = item.node()
|
||||
vm_dir = node.vmDir()
|
||||
if vm_dir is None:
|
||||
QtWidgets.QMessageBox.critical(self, "Show in file manager", "This VM has no working directory")
|
||||
break
|
||||
|
||||
if os.path.exists(vm_dir):
|
||||
log.debug("Open %s in file manage" )
|
||||
if QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(vm_dir)) is False:
|
||||
QtWidgets.QMessageBox.critical(self, "Show in file manager", "Failed to open {}".format(vm_dir))
|
||||
break
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, "Show in file manager", "The device directory is located in {} on {}".format(vm_dir, node.server().url()))
|
||||
break
|
||||
|
||||
def consoleToNode(self, node, aux=False):
|
||||
"""
|
||||
Start a console application to connect to a node.
|
||||
@@ -949,43 +999,32 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
from .serial_console import serialConsole
|
||||
serialConsole(node.name(), node.serialPipe())
|
||||
except (OSError, ValueError) as e:
|
||||
QtGui.QMessageBox.critical(self, "Console", "Cannot start serial console application: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "Console", "Cannot start serial console application: {}".format(e))
|
||||
return False
|
||||
else:
|
||||
name = node.name()
|
||||
if aux:
|
||||
console_port = node.auxConsole()
|
||||
if console_port is None:
|
||||
QtGui.QMessageBox.critical(self, "Console", "AUX console port not allocated for {}".format(name))
|
||||
QtWidgets.QMessageBox.critical(self, "Console", "AUX console port not allocated for {}".format(name))
|
||||
return False
|
||||
else:
|
||||
console_port = node.console()
|
||||
console_host = node.server().host
|
||||
|
||||
console_type = "telnet"
|
||||
if "console_type" in node.settings():
|
||||
console_type = node.settings()["console_type"]
|
||||
|
||||
try:
|
||||
from .telnet_console import telnetConsole
|
||||
from .telnet_console import nodeTelnetConsole
|
||||
from .vnc_console import vncConsole
|
||||
|
||||
telnet_callback = None
|
||||
|
||||
try:
|
||||
if node.server().isCloud():
|
||||
# override target host with localhost
|
||||
console_host = '127.0.0.1'
|
||||
ep = node.server().tunnel.add_endpoint(console_host, console_port)
|
||||
# override target port with local tunneled port
|
||||
local_addr, _ = ep.get()
|
||||
console_port = local_addr[1]
|
||||
|
||||
def cb(*args, **kwargs):
|
||||
node.server().tunnel.remove_endpoint(ep)
|
||||
log.debug('Console DONE on port {}'.format(args[2]))
|
||||
telnet_callback = cb
|
||||
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
telnetConsole(name, console_host, console_port, telnet_callback)
|
||||
if console_type == "telnet":
|
||||
nodeTelnetConsole(name, node.server(), console_port)
|
||||
elif console_type == "vnc":
|
||||
vncConsole(node.server().host(), console_port)
|
||||
except (OSError, ValueError) as e:
|
||||
QtGui.QMessageBox.critical(self, "Console", "Cannot start console application: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "Console", "Cannot start console application: {}".format(e))
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -1062,25 +1101,31 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
return
|
||||
|
||||
if len(items) > 1:
|
||||
path = QtGui.QFileDialog.getExistingDirectory(self, "Import directory", ".", QtGui.QFileDialog.ShowDirsOnly)
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(self, "Import directory", self._import_configs_from_dir, QtWidgets.QFileDialog.ShowDirsOnly)
|
||||
if path:
|
||||
self._import_configs_from_dir = os.path.dirname(path)
|
||||
for item in items:
|
||||
item.node().importConfigFromDirectory(path)
|
||||
else:
|
||||
if not self._import_config_dir:
|
||||
self._import_config_dir = self._main_window.project().filesDir()
|
||||
|
||||
item = items[0]
|
||||
path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(self,
|
||||
"Import config",
|
||||
".",
|
||||
"All files (*.*);;Config files (*.cfg)",
|
||||
"Config files (*.cfg)")
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self,
|
||||
"Import config",
|
||||
self._import_config_dir,
|
||||
"All files (*.*);;Config files (*.cfg)",
|
||||
"Config files (*.cfg)")
|
||||
|
||||
if path:
|
||||
self._import_config_dir = os.path.dirname(path)
|
||||
item.node().importConfig(path)
|
||||
if hasattr(item.node(), "importPrivateConfig"):
|
||||
path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(self,
|
||||
"Import private-config",
|
||||
".",
|
||||
"All files (*.*);;Config files (*.cfg)",
|
||||
"Config files (*.cfg)")
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self,
|
||||
"Import private-config",
|
||||
self._import_config_dir,
|
||||
"All files (*.*);;Config files (*.cfg)",
|
||||
"Config files (*.cfg)")
|
||||
if path:
|
||||
item.node().importPrivateConfig(path)
|
||||
|
||||
@@ -1099,18 +1144,24 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
return
|
||||
|
||||
if len(items) > 1:
|
||||
path = QtGui.QFileDialog.getExistingDirectory(self, "Export directory", ".", QtGui.QFileDialog.ShowDirsOnly)
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(self, "Export directory", self._export_configs_to_dir, QtWidgets.QFileDialog.ShowDirsOnly)
|
||||
if path:
|
||||
self._export_configs_to_dir = os.path.dirname(path)
|
||||
for item in items:
|
||||
item.node().exportConfigToDirectory(path)
|
||||
else:
|
||||
if not self._export_config_dir:
|
||||
self._export_config_dir = self._main_window.project().filesDir()
|
||||
|
||||
item = items[0]
|
||||
if hasattr(item.node(), "importPrivateConfig"):
|
||||
config_path = QtGui.QFileDialog.getSaveFileName(self, "Export startup-config")
|
||||
private_config_path = QtGui.QFileDialog.getSaveFileName(self, "Export private-config")
|
||||
config_path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export startup-config", self._export_config_dir)
|
||||
self._export_config_dir = os.path.dirname(config_path)
|
||||
private_config_path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export private-config", self._export_config_dir)
|
||||
item.node().exportConfig(config_path, private_config_path)
|
||||
else:
|
||||
config_path = QtGui.QFileDialog.getSaveFileName(self, "Export config")
|
||||
config_path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export config", self._export_config_dir)
|
||||
self._export_config_dir = os.path.dirname(config_path)
|
||||
item.node().exportConfig(config_path)
|
||||
|
||||
def saveConfigActionSlot(self):
|
||||
@@ -1139,13 +1190,13 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
key = "Port {} ({} encapsulation: {})".format(port.name(), dlt_name, dlt)
|
||||
ports[key] = [port, dlt]
|
||||
if ports:
|
||||
selection, ok = QtGui.QInputDialog.getItem(self, "Capture on {}".format(node.name()), "Please select a port:", list(ports.keys()), 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(self, "Capture on {}".format(node.name()), "Please select a port:", list(ports.keys()), 0, False)
|
||||
if ok:
|
||||
if selection in ports:
|
||||
port, dlt = ports[selection]
|
||||
node.startPacketCapture(port, port.captureFileName(node.name()), dlt)
|
||||
else:
|
||||
QtGui.QMessageBox.warning(self, "Capture", "No port available for packet capture on {}".format(node.name()))
|
||||
QtWidgets.QMessageBox.warning(self, "Capture", "No port available for packet capture on {}".format(node.name()))
|
||||
|
||||
def idlepcActionSlot(self):
|
||||
"""
|
||||
@@ -1155,16 +1206,11 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
|
||||
items = self.scene().selectedItems()
|
||||
if len(items) != 1:
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "Please select only one router")
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "Please select only one router")
|
||||
return
|
||||
item = items[0]
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "idlepc") and item.node().initialized():
|
||||
router = item.node()
|
||||
# question = QtGui.QMessageBox.question(self, "Auto Idle-PC", "Would you like to automatically find a suitable Idle-PC value (but not optimal)?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||
|
||||
# if question == QtGui.QMessageBox.Yes:
|
||||
# router.computeAutoIdlepc(self._autoIdlepcCallback)
|
||||
# else:
|
||||
router.computeIdlepcs(self._idlepcCallback)
|
||||
|
||||
def _idlepcCallback(self, result, error=False, context={}, **kwargs):
|
||||
@@ -1173,7 +1219,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
"""
|
||||
|
||||
if error:
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "Error: {}".format(result["message"]))
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "Error: {}".format(result["message"]))
|
||||
else:
|
||||
router = context["router"]
|
||||
log.info("{} has received Idle-PC proposals".format(router.name()))
|
||||
@@ -1183,7 +1229,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
dialog.show()
|
||||
dialog.exec_()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "Sorry no Idle-PC values could be computed, please check again with Cisco IOS in a different state")
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "Sorry no Idle-PC values could be computed, please check again with Cisco IOS in a different state")
|
||||
|
||||
def autoIdlepcActionSlot(self):
|
||||
"""
|
||||
@@ -1193,7 +1239,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
|
||||
items = self.scene().selectedItems()
|
||||
if len(items) != 1:
|
||||
QtGui.QMessageBox.critical(self, "Auto Idle-PC", "Please select only one router")
|
||||
QtWidgets.QMessageBox.critical(self, "Auto Idle-PC", "Please select only one router")
|
||||
return
|
||||
item = items[0]
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "idlepc") and item.node().initialized():
|
||||
@@ -1206,16 +1252,22 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
"""
|
||||
|
||||
if error:
|
||||
QtGui.QMessageBox.critical(self, "Auto Idle-PC", "Error: {}".format(result["message"]))
|
||||
QtWidgets.QMessageBox.critical(self, "Auto Idle-PC", "Error: {}".format(result["message"]))
|
||||
else:
|
||||
router = context["router"]
|
||||
idlepc = result["idlepc"]
|
||||
log.info("{} has received the auto idle-pc value: {}".format(router.name(), idlepc))
|
||||
router.setIdlepc(idlepc)
|
||||
# apply the idle-pc to templates with the same IOS image
|
||||
# apply Idle-PC to all routers with the same IOS image
|
||||
ios_image = os.path.basename(router.settings()["image"])
|
||||
for node in Topology.instance().nodes():
|
||||
if hasattr(node, "idlepc") and node.settings()["image"] == ios_image:
|
||||
node.setIdlepc(idlepc)
|
||||
# apply the idle-pc to templates with the same IOS image
|
||||
router.module().updateImageIdlepc(ios_image, idlepc)
|
||||
QtGui.QMessageBox.information(self, "Auto Idle-PC", "Idle-PC value {} has been applied on {}".format(idlepc, router.name()))
|
||||
QtWidgets.QMessageBox.information(self, "Auto Idle-PC", "Idle-PC value {} has been applied on {} and all routers with IOS image {}".format(idlepc,
|
||||
router.name(),
|
||||
ios_image))
|
||||
|
||||
def duplicateActionSlot(self):
|
||||
"""
|
||||
@@ -1320,6 +1372,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
current_zvalue = item.zValue()
|
||||
item.setZValue(current_zvalue - 1)
|
||||
item.update()
|
||||
|
||||
if item.zValue() == -1:
|
||||
self._background_warning_msgbox.showMessage("Object moved to a background layer. You will now have to use the right-click action to select this object in the future and raise it to layer 0 to be able to move it")
|
||||
|
||||
@@ -1338,9 +1391,9 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
question = "Do you want to permanently delete these {} nodes?".format(len(selected_nodes))
|
||||
else:
|
||||
question = "Do you want to permanently delete {}?".format(selected_nodes[0].name())
|
||||
reply = QtGui.QMessageBox.question(self, "Delete", question,
|
||||
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.No:
|
||||
reply = QtWidgets.QMessageBox.question(self, "Delete", question,
|
||||
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem):
|
||||
@@ -1375,14 +1428,19 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
server = node_module.allocateServer(node_class)
|
||||
elif node_data["server"] == "local":
|
||||
server = Servers.instance().localServer()
|
||||
elif node_data["server"] == "cloud":
|
||||
server = Servers.instance().anyCloudServer()
|
||||
elif node_data["server"] == "vm":
|
||||
server = Servers.instance().vmServer()
|
||||
if server is None:
|
||||
QtWidgets.QMessageBox.critical(self, "GNS3 VM", "The GNS3 VM is not running")
|
||||
return
|
||||
elif node_data["server"] == "load-balance":
|
||||
ram = node_data.get("ram", 0)
|
||||
server = Servers.instance().anyRemoteServer(ram)
|
||||
if server is None:
|
||||
QtWidgets.QMessageBox.critical(self, "Remote server", "Cannot load balance: no remote server configured")
|
||||
return
|
||||
else:
|
||||
try:
|
||||
host, port = node_data["server"].rsplit(":", 1)
|
||||
except ValueError:
|
||||
raise ModuleError("Wrong format for server: '{}', please recreate the node in preferences".format(node_data["server"]))
|
||||
server = Servers.instance().getRemoteServer(host, port)
|
||||
server = Servers.instance().getServerFromString(node_data["server"])
|
||||
|
||||
if server is None:
|
||||
return
|
||||
@@ -1391,10 +1449,13 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
node.error_signal.connect(self._main_window.uiConsoleTextEdit.writeError)
|
||||
node.warning_signal.connect(self._main_window.uiConsoleTextEdit.writeWarning)
|
||||
node.server_error_signal.connect(self._main_window.uiConsoleTextEdit.writeServerError)
|
||||
node_item = NodeItem(node, node_data["default_symbol"], node_data["hover_symbol"])
|
||||
if QtSvg.QSvgRenderer(node_data["symbol"]).isValid():
|
||||
node_item = SvgNodeItem(node, node_data["symbol"])
|
||||
else:
|
||||
node_item = PixmapNodeItem(node, node_data["symbol"])
|
||||
node_module.setupNode(node, node_data["name"])
|
||||
except ModuleError as e:
|
||||
QtGui.QMessageBox.critical(self, "Node creation", "{}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "Node creation", "{}".format(e))
|
||||
return
|
||||
|
||||
node_item.setPos(self.mapToScene(pos))
|
||||
|
||||
@@ -18,20 +18,24 @@
|
||||
|
||||
import json
|
||||
import http
|
||||
import ipaddress
|
||||
import uuid
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import pathlib
|
||||
import base64
|
||||
from functools import partial
|
||||
|
||||
from .version import __version__, __version_info__
|
||||
from .qt import QtCore, QtNetwork
|
||||
from .network_client import getNetworkUrl
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HttpBadRequest(Exception):
|
||||
|
||||
"""We raise bad request exception for logging them in Sentry"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -40,7 +44,7 @@ class HTTPClient(QtCore.QObject):
|
||||
"""
|
||||
HTTP client.
|
||||
|
||||
:param url: URL to connect to the server
|
||||
:param settings: Dictionnary with connection information to the server
|
||||
:param network_manager: A QT network manager
|
||||
"""
|
||||
|
||||
@@ -52,35 +56,134 @@ class HTTPClient(QtCore.QObject):
|
||||
connected_signal = QtCore.Signal()
|
||||
connection_error_signal = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, url, network_manager, user=None, password=None):
|
||||
def __init__(self, settings, network_manager):
|
||||
|
||||
super().__init__()
|
||||
self._url = url
|
||||
self._version = ""
|
||||
|
||||
url_settings = urllib.parse.urlparse(url)
|
||||
self.scheme = url_settings.scheme
|
||||
self.host = url_settings.netloc.split(":")[0]
|
||||
self.port = url_settings.port
|
||||
self._user = user
|
||||
self._password = password
|
||||
|
||||
self._scheme = settings.get("protocol", "http")
|
||||
self._host = settings["host"]
|
||||
self._http_host = settings["host"]
|
||||
self._port = int(settings["port"])
|
||||
self._http_port = int(settings["port"])
|
||||
self._user = settings.get("user", None)
|
||||
self._password = settings.get("password", None)
|
||||
self._connected = False
|
||||
self._local = True
|
||||
self._cloud = False
|
||||
self._gns3_vm = False
|
||||
self._ram_limit = settings.get("ram_limit", 0)
|
||||
self._allocated_ram = 0
|
||||
self._accept_insecure_certificate = settings.get("accept_insecure_certificate", None)
|
||||
|
||||
self._network_manager = network_manager
|
||||
|
||||
# A buffer used by progress download
|
||||
self._buffer = {}
|
||||
|
||||
# create an unique ID
|
||||
self._id = HTTPClient._instance_count
|
||||
HTTPClient._instance_count += 1
|
||||
|
||||
def notify_progress_start_query(self, query_id):
|
||||
def getTunnel(self, port):
|
||||
"""
|
||||
Get a tunnel to the remote port.
|
||||
For HTTP standard client it's the same port. For SSH it will create a new tunnel.
|
||||
|
||||
:param port: Remote port
|
||||
:returns: Tuple host, port to connect
|
||||
"""
|
||||
return self._host, port
|
||||
|
||||
def releaseTunnel(self, port):
|
||||
"""
|
||||
Release a tunnel to the remote port.
|
||||
For HTTP standard client it's do nothing
|
||||
|
||||
:param port: Allocated remote port
|
||||
"""
|
||||
pass
|
||||
|
||||
def settings(self):
|
||||
"""
|
||||
Return a dictionnary with server settings
|
||||
"""
|
||||
settings = {"protocol": self.protocol(),
|
||||
"ram_limit": self.RAMLimit(),
|
||||
"host": self.host(),
|
||||
"port": self.port(),
|
||||
"user": self.user(),
|
||||
"password": self._password}
|
||||
if self.protocol() == "https":
|
||||
settings["accept_insecure_certificate"] = self.acceptInsecureCertificate()
|
||||
return settings
|
||||
|
||||
def acceptInsecureCertificate(self, certificate=None):
|
||||
"""
|
||||
Does the server accept this insecure SSL certificate digest
|
||||
|
||||
:param: Certificate digest
|
||||
"""
|
||||
return self._accept_insecure_certificate
|
||||
|
||||
def setAcceptInsecureCertificate(self, certificate):
|
||||
"""
|
||||
Does the server accept this insecure SSL certificate digest
|
||||
|
||||
:param: Certificate digest
|
||||
"""
|
||||
self._accept_insecure_certificate = certificate
|
||||
|
||||
def host(self):
|
||||
"""
|
||||
Host display to user
|
||||
"""
|
||||
return self._host
|
||||
|
||||
def setHost(self, host):
|
||||
self._host = host
|
||||
self._http_host = host
|
||||
|
||||
def port(self):
|
||||
"""
|
||||
Port display to user
|
||||
"""
|
||||
return self._port
|
||||
|
||||
def setPort(self, port):
|
||||
self._port = port
|
||||
self._http_port = port
|
||||
|
||||
def protocol(self):
|
||||
"""
|
||||
Transport protocol
|
||||
"""
|
||||
return self._scheme
|
||||
|
||||
def user(self):
|
||||
"""
|
||||
User login display to GNS3 user
|
||||
"""
|
||||
return self._user
|
||||
|
||||
def setUser(self, user):
|
||||
self._user = user
|
||||
|
||||
def setPassword(self, password):
|
||||
self._password = password
|
||||
|
||||
def notify_progress_start_query(self, query_id, progress_text, response):
|
||||
"""
|
||||
Called when a query start
|
||||
"""
|
||||
if HTTPClient._progress_callback:
|
||||
HTTPClient._progress_callback.add_query_signal.emit(query_id, "Waiting for {scheme}://{host}:{port}".format(scheme=self.scheme, host=self.host, port=self.port))
|
||||
if progress_text:
|
||||
HTTPClient._progress_callback.add_query_signal.emit(query_id, progress_text, response)
|
||||
else:
|
||||
if self._local:
|
||||
HTTPClient._progress_callback.add_query_signal.emit(query_id, "Waiting for local GNS3 server", response)
|
||||
else:
|
||||
HTTPClient._progress_callback.add_query_signal.emit(query_id, "Waiting for {}".format(self.url()), response)
|
||||
|
||||
def notify_progress_end_query(cls, query_id):
|
||||
"""
|
||||
@@ -90,6 +193,20 @@ class HTTPClient(QtCore.QObject):
|
||||
if HTTPClient._progress_callback:
|
||||
HTTPClient._progress_callback.remove_query_signal.emit(query_id)
|
||||
|
||||
def notify_progress_upload(self, query_id, sent, total):
|
||||
"""
|
||||
Called when a query upload progress
|
||||
"""
|
||||
if HTTPClient._progress_callback:
|
||||
HTTPClient._progress_callback.progress(query_id, sent, total)
|
||||
|
||||
def notify_progress_download(self, query_id, sent, total):
|
||||
"""
|
||||
Called when a query download progress
|
||||
"""
|
||||
if HTTPClient._progress_callback:
|
||||
HTTPClient._progress_callback.progress(query_id, sent, total)
|
||||
|
||||
@classmethod
|
||||
def setProgressCallback(cls, progress_callback):
|
||||
"""
|
||||
@@ -107,7 +224,7 @@ class HTTPClient(QtCore.QObject):
|
||||
def url(self):
|
||||
"""Returns current server url"""
|
||||
|
||||
return "{scheme}://{host}:{port}".format(scheme=self.scheme, host=self.host, port=self.port)
|
||||
return getNetworkUrl(self.protocol(), self.host(), self.port(), self.user(), self.settings())
|
||||
|
||||
def id(self):
|
||||
"""
|
||||
@@ -133,6 +250,24 @@ class HTTPClient(QtCore.QObject):
|
||||
|
||||
return self._local
|
||||
|
||||
def setGNS3VM(self, value):
|
||||
"""
|
||||
Sets either this is a connection to the GNS3 VM or not.
|
||||
|
||||
:param value: boolean
|
||||
"""
|
||||
|
||||
self._gns3_vm = value
|
||||
|
||||
def isGNS3VM(self):
|
||||
"""
|
||||
Returns either this is a connection to the GNS3 VM or not.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return self._gns3_vm
|
||||
|
||||
def connected(self):
|
||||
"""
|
||||
Returns if the client is connected.
|
||||
@@ -145,19 +280,41 @@ class HTTPClient(QtCore.QObject):
|
||||
"""
|
||||
Closes the connection with the server.
|
||||
"""
|
||||
|
||||
log.info("Connection to %s closed", self.url())
|
||||
self._connected = False
|
||||
|
||||
def isLocalServerRunning(self):
|
||||
"""
|
||||
Check if a server is already running on this host.
|
||||
Synchronous check if a server is already running on this host.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
try:
|
||||
url = "{scheme}://{host}:{port}/v1/version".format(scheme=self.scheme, host=self.host, port=self.port)
|
||||
|
||||
if self._user is not None:
|
||||
status, json_data = self.getSynchronous("version", timeout=2)
|
||||
if json_data is None or status != 200:
|
||||
return False
|
||||
else:
|
||||
version = json_data.get("version")
|
||||
local_server = json_data.get("local", False)
|
||||
if version != __version__:
|
||||
log.debug("Client version {} differs with server version {}".format(__version__, version))
|
||||
return False
|
||||
if not local_server:
|
||||
log.debug("Running server is not a GNS3 local server (not started with --local)")
|
||||
return False
|
||||
return True
|
||||
|
||||
def getSynchronous(self, endpoint, timeout=2):
|
||||
"""
|
||||
Synchronous check if a server is running
|
||||
|
||||
:returns: Tuple (Status code, json of anwser). Status 0 is a non HTTP error
|
||||
"""
|
||||
try:
|
||||
url = "{protocol}://{host}:{port}/v1/{endpoint}".format(protocol=self._scheme, host=self._http_host, port=self._http_port, endpoint=endpoint)
|
||||
|
||||
log.debug("Synchronous get %s with user %s", url, self._user)
|
||||
if self._user is not None and len(self._user) > 0:
|
||||
auth_handler = urllib.request.HTTPBasicAuthHandler()
|
||||
auth_handler.add_password(realm="GNS3 server",
|
||||
uri=url,
|
||||
@@ -166,69 +323,69 @@ class HTTPClient(QtCore.QObject):
|
||||
opener = urllib.request.build_opener(auth_handler)
|
||||
urllib.request.install_opener(opener)
|
||||
|
||||
response = urllib.request.urlopen(url, timeout=2)
|
||||
response = urllib.request.urlopen(url, timeout=timeout)
|
||||
content_type = response.getheader("CONTENT-TYPE")
|
||||
if response.status == 200 and content_type == "application/json":
|
||||
content = response.read()
|
||||
json_data = json.loads(content.decode("utf-8"))
|
||||
version = json_data.get("version")
|
||||
local_server = json_data.get("local", False)
|
||||
if version != __version__:
|
||||
log.debug("Client version {} differs with server version {}".format(__version__, version))
|
||||
return False
|
||||
if not local_server:
|
||||
log.debug("Running server is not a GNS3 local server (not started with --local)")
|
||||
return False
|
||||
return True
|
||||
except (OSError, urllib.error.HTTPError, http.client.BadStatusLine, ValueError) as e:
|
||||
log.debug("A non GNS3 server is already running on {}:{}: {}".format(self.host, self.port, e))
|
||||
return False
|
||||
if response.status == 200:
|
||||
if content_type == "application/json":
|
||||
content = response.read()
|
||||
json_data = json.loads(content.decode("utf-8"))
|
||||
return response.status, json_data
|
||||
else:
|
||||
return response.status, None
|
||||
except urllib.error.HTTPError as e:
|
||||
log.debug("Error during get on {}:{}: {}".format(self.host(), self.port(), e))
|
||||
return e.code, None
|
||||
except (OSError, http.client.BadStatusLine, ValueError) as e:
|
||||
log.debug("Error during get on {}:{}: {}".format(self.host(), self.port(), e))
|
||||
return 0, None
|
||||
|
||||
def get(self, path, callback, context={}):
|
||||
def get(self, path, callback, **kwargs):
|
||||
"""
|
||||
HTTP GET on the remote server
|
||||
|
||||
:param path: Remote path
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
|
||||
Full arg list in createHTTPQuery
|
||||
"""
|
||||
|
||||
self.createHTTPQuery("GET", path, callback, context=context)
|
||||
self.createHTTPQuery("GET", path, callback, **kwargs)
|
||||
|
||||
def put(self, path, callback, body={}, context={}):
|
||||
def put(self, path, callback, **kwargs):
|
||||
"""
|
||||
HTTP PUT on the remote server
|
||||
|
||||
:param path: Remote path
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
:param body: params to send (dictionary)
|
||||
|
||||
Full arg list in createHTTPQuery
|
||||
"""
|
||||
|
||||
self.createHTTPQuery("PUT", path, callback, context=context, body=body)
|
||||
self.createHTTPQuery("PUT", path, callback, **kwargs)
|
||||
|
||||
def post(self, path, callback, body={}, context={}):
|
||||
def post(self, path, callback, **kwargs):
|
||||
"""
|
||||
HTTP POST on the remote server
|
||||
|
||||
:param path: Remote path
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
:param body: params to send (dictionary)
|
||||
|
||||
Full arg list in createHTTPQuery
|
||||
"""
|
||||
|
||||
self.createHTTPQuery("POST", path, callback, context=context, body=body)
|
||||
self.createHTTPQuery("POST", path, callback, **kwargs)
|
||||
|
||||
def delete(self, path, callback, context={}):
|
||||
def delete(self, path, callback, **kwargs):
|
||||
"""
|
||||
HTTP DELETE on the remote server
|
||||
|
||||
:param path: Remote path
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
|
||||
Full arg list in createHTTPQuery
|
||||
"""
|
||||
|
||||
self.createHTTPQuery("DELETE", path, callback, context=context)
|
||||
self.createHTTPQuery("DELETE", path, callback, **kwargs)
|
||||
|
||||
def _request(self, url):
|
||||
"""
|
||||
@@ -241,42 +398,72 @@ class HTTPClient(QtCore.QObject):
|
||||
|
||||
return QtNetwork.QNetworkRequest(url)
|
||||
|
||||
def createHTTPQuery(self, method, path, callback, body={}, context={}):
|
||||
# FIXME: connect is a method in parent class (QObject)
|
||||
def connect(self, query, callback):
|
||||
"""
|
||||
Initialize the connection
|
||||
|
||||
:param query: The query to execute when all network stack is ready
|
||||
:param callback: User callback when connection is finish
|
||||
"""
|
||||
self.executeHTTPQuery("GET", "/version", query, {})
|
||||
|
||||
def createHTTPQuery(self, method, path, callback, body={}, context={}, downloadProgressCallback=None, showProgress=True, ignoreErrors=False, progressText=None):
|
||||
"""
|
||||
Call the remote server, if not connected, check connection before
|
||||
|
||||
:param method: HTTP method
|
||||
:param path: Remote path
|
||||
:param body: params to send (dictionary)
|
||||
:param body: params to send (dictionary or pathlib.Path)
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
:param downloadProgressCallback: Callback called when received something, it can be an incomplete response
|
||||
:param showProgress: Display progress to the user
|
||||
:params progressText: Text display to user in the progress dialog. None for auto generated
|
||||
:param ignoreErrors: Ignore connection error (usefull to not closing a connection when notification feed is broken)
|
||||
:returns: QNetworkReply
|
||||
"""
|
||||
|
||||
if self._connected:
|
||||
self.executeHTTPQuery(method, path, callback, body, context=context)
|
||||
return self.executeHTTPQuery(method, path, callback, body, context, downloadProgressCallback=downloadProgressCallback, showProgress=showProgress, ignoreErrors=ignoreErrors, progressText=progressText)
|
||||
else:
|
||||
log.info("Connection to {}:{}".format(self.host, self.port))
|
||||
self.executeHTTPQuery("GET", "/version", partial(self._callbackConnect, method, path, callback, body, context), {})
|
||||
log.info("Connection to {}".format(self.url()))
|
||||
query = partial(self._callbackConnect, method, path, callback, body, context, downloadProgressCallback=downloadProgressCallback, showProgress=showProgress, ignoreErrors=ignoreErrors, progressText=progressText)
|
||||
self.connect(query, callback)
|
||||
|
||||
def _callbackConnect(self, method, path, callback, body, original_context, params, error=False, **kwargs):
|
||||
def _connectionError(self, callback, msg=""):
|
||||
"""
|
||||
Return an error to user if connection failed
|
||||
|
||||
:param callback: User callback
|
||||
:param msg: An optional additional message for the callback
|
||||
"""
|
||||
|
||||
if len(msg) > 0:
|
||||
msg = "Can't connect to server {}: {}".format(self.url(), msg)
|
||||
else:
|
||||
msg = "Can't connect to server {}".format(self.url())
|
||||
log.error(msg)
|
||||
if callback is not None:
|
||||
callback({"message": msg}, error=True, server=self)
|
||||
|
||||
def _callbackConnect(self, method, path, callback, body, original_context, params, error=False, server=None, **kwargs):
|
||||
"""
|
||||
Callback after /version response. Continue execution of query
|
||||
|
||||
:param method: HTTP method
|
||||
:param path: Remote path
|
||||
:param body: params to send (dictionary)
|
||||
:param body: params to send (dictionary or pathlib.Path)
|
||||
:param original_context: Original context
|
||||
:param callback: callback method to call when the server replies
|
||||
"""
|
||||
|
||||
if error is not False:
|
||||
msg = "Can't connect to server {}://{}:{}".format(self.scheme, self.host, self.port)
|
||||
if callback is not None:
|
||||
callback({"message": msg}, error=True, server=self)
|
||||
self._connectionError(callback)
|
||||
return
|
||||
|
||||
if "version" not in params or "local" not in params:
|
||||
msg = "The remote server {}://{}:{} is not a GNS 3 server".format(self.scheme, self.host, self.port)
|
||||
msg = "The remote server {} is not a GNS3 server".format(self.url())
|
||||
log.error(msg)
|
||||
if callback is not None:
|
||||
callback({"message": msg}, error=True, server=self)
|
||||
@@ -298,16 +485,48 @@ class HTTPClient(QtCore.QObject):
|
||||
if self.isLocal():
|
||||
msg = "Running server is not a GNS3 local server (not started with --local)"
|
||||
else:
|
||||
msg = "Remote running server is started with --local. It's forbidden for security reasons"
|
||||
msg = "Remote running server is started with --local. It is forbidden for security reasons"
|
||||
log.error(msg)
|
||||
if callback is not None:
|
||||
callback({"message": msg}, error=True, server=self)
|
||||
return
|
||||
|
||||
self.executeHTTPQuery(method, path, callback, body, context=original_context)
|
||||
self._connected = True
|
||||
kwargs["context"] = original_context
|
||||
self.executeHTTPQuery(method, path, callback, body, **kwargs)
|
||||
self._version = params["version"]
|
||||
|
||||
def _addBodyToRequest(self, body, request):
|
||||
"""
|
||||
Add the require headers for sending the body.
|
||||
It detect the type of body for sending the corresponding headers
|
||||
and methods.
|
||||
|
||||
:param body: The body
|
||||
:returns: The body compatible with Qt
|
||||
"""
|
||||
|
||||
if body is None:
|
||||
return None
|
||||
|
||||
if isinstance(body, dict):
|
||||
body = json.dumps(body)
|
||||
request.setRawHeader("Content-Type", "application/json")
|
||||
request.setRawHeader("Content-Length", str(len(body)))
|
||||
data = QtCore.QByteArray(body)
|
||||
body = QtCore.QBuffer(self)
|
||||
body.setData(data)
|
||||
body.open(QtCore.QIODevice.ReadOnly)
|
||||
return body
|
||||
elif isinstance(body, pathlib.Path):
|
||||
body = QtCore.QFile(str(body), self)
|
||||
body.open(QtCore.QFile.ReadOnly)
|
||||
request.setRawHeader("Content-Type", "application/octet-stream")
|
||||
# QT is smart and will compute the Content-Lenght for us
|
||||
return body
|
||||
else:
|
||||
return None
|
||||
|
||||
def addAuth(self, request):
|
||||
"""
|
||||
If require add basic auth header
|
||||
@@ -319,7 +538,7 @@ class HTTPClient(QtCore.QObject):
|
||||
request.setRawHeader("Authorization", auth_string)
|
||||
return request
|
||||
|
||||
def executeHTTPQuery(self, method, path, callback, body, context={}):
|
||||
def executeHTTPQuery(self, method, path, callback, body, context={}, downloadProgressCallback=None, showProgress=True, ignoreErrors=False, progressText=None):
|
||||
"""
|
||||
Call the remote server
|
||||
|
||||
@@ -328,43 +547,81 @@ class HTTPClient(QtCore.QObject):
|
||||
:param body: params to send (dictionary)
|
||||
:param callback: callback method to call when the server replies
|
||||
:param context: Pass a context to the response callback
|
||||
:param downloadProgressCallback: Callback called when received something, it can be an incomplete response
|
||||
:param showProgress: Display progress to the user
|
||||
:param progressText: Text display to user in progress dialog. None for auto generated
|
||||
:param ignoreErrors: Ignore connection error (usefull to not closing a connection when notification feed is broken)
|
||||
:returns: QNetworkReply
|
||||
"""
|
||||
|
||||
try:
|
||||
ip = self._http_host.rsplit('%', 1)[0]
|
||||
ipaddress.IPv6Address(ip) # remove any scope ID
|
||||
# this is an IPv6 address, we must surround it with brackets to be used with QUrl.
|
||||
host = "[{}]".format(ip)
|
||||
except ipaddress.AddressValueError:
|
||||
host = self._http_host
|
||||
|
||||
log.debug("{method} {protocol}://{host}:{port}/v1{path} {body}".format(method=method, protocol=self._scheme, host=host, port=self._http_port, path=path, body=body))
|
||||
url = QtCore.QUrl("{protocol}://{host}:{port}/v1{path}".format(protocol=self._scheme, host=host, port=self._http_port, path=path))
|
||||
request = self._request(url)
|
||||
|
||||
request = self.addAuth(request)
|
||||
|
||||
request.setRawHeader("User-Agent", "GNS3 QT Client v{version}".format(version=__version__))
|
||||
|
||||
# By default QT doesn't support GET with body even if it's in the RFC that's why we need to use sendCustomRequest
|
||||
body = self._addBodyToRequest(body, request)
|
||||
|
||||
response = self._network_manager.sendCustomRequest(request, method, body)
|
||||
|
||||
import copy
|
||||
context = copy.copy(context)
|
||||
context["query_id"] = str(uuid.uuid4())
|
||||
self.notify_progress_start_query(context["query_id"])
|
||||
log.debug("{method} {scheme}://{host}:{port}/v1{path} {body}".format(method=method, scheme=self.scheme, host=self.host, port=self.port, path=path, body=body))
|
||||
url = QtCore.QUrl("{scheme}://{host}:{port}/v1{path}".format(scheme=self.scheme, host=self.host, port=self.port, path=path))
|
||||
request = self._request(url)
|
||||
request = self.addAuth(request)
|
||||
query_id = str(uuid.uuid4())
|
||||
context["query_id"] = query_id
|
||||
if showProgress:
|
||||
self.notify_progress_start_query(context["query_id"], progressText, response)
|
||||
response.uploadProgress.connect(partial(self.notify_progress_upload, query_id))
|
||||
response.downloadProgress.connect(partial(self.notify_progress_download, query_id))
|
||||
|
||||
request.setRawHeader("Content-Type", "application/json")
|
||||
request.setRawHeader("Content-Length", str(len(body)))
|
||||
request.setRawHeader("User-Agent", "GNS3 QT Client v{version}".format(version=__version__))
|
||||
response.finished.connect(partial(self._processResponse, response, callback, context, body, ignoreErrors))
|
||||
if downloadProgressCallback is not None:
|
||||
response.downloadProgress.connect(partial(self._processDownloadProgress, response, downloadProgressCallback, context))
|
||||
return response
|
||||
|
||||
if method == "GET":
|
||||
response = self._network_manager.get(request)
|
||||
def _processDownloadProgress(self, response, callback, context):
|
||||
"""
|
||||
Process a packet receive on the notification feed.
|
||||
The feed can contains partial JSON. If we found a
|
||||
part of a JSON we keep it for the next packet
|
||||
"""
|
||||
|
||||
if method == "PUT":
|
||||
body = json.dumps(body)
|
||||
request.setRawHeader("Content-Type", "application/json")
|
||||
request.setRawHeader("Content-Length", str(len(body)))
|
||||
response = self._network_manager.put(request, body)
|
||||
if response.error() == QtNetwork.QNetworkReply.NoError:
|
||||
error_code = response.error()
|
||||
|
||||
if method == "POST":
|
||||
body = json.dumps(body)
|
||||
request.setRawHeader("Content-Type", "application/json")
|
||||
request.setRawHeader("Content-Length", str(len(body)))
|
||||
response = self._network_manager.post(request, body)
|
||||
if error_code >= 300:
|
||||
return
|
||||
|
||||
if method == "DELETE":
|
||||
response = self._network_manager.deleteResource(request)
|
||||
content = bytes(response.readAll())
|
||||
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
|
||||
if content_type == "application/json":
|
||||
content = content.decode("utf-8")
|
||||
if context["query_id"] in self._buffer:
|
||||
content = self._buffer[context["query_id"]] + content
|
||||
try:
|
||||
while True:
|
||||
content = content.lstrip(" \r\n\t")
|
||||
answer, index = json.JSONDecoder().raw_decode(content)
|
||||
callback(answer, server=self, context=context)
|
||||
content = content[index:]
|
||||
except ValueError: # Partial JSON
|
||||
self._buffer[context["query_id"]] = content
|
||||
else:
|
||||
callback(content, server=self, context=context)
|
||||
|
||||
if HTTPClient._progress_callback and HTTPClient._progress_callback.progress_dialog():
|
||||
request_canceled = partial(self._requestCanceled, response, context)
|
||||
HTTPClient._progress_callback.progress_dialog().canceled.connect(request_canceled)
|
||||
response.finished.connect(partial(self._processResponse, response, callback, context))
|
||||
if HTTPClient._progress_callback and HTTPClient._progress_callback.progress_dialog():
|
||||
request_canceled = partial(self._requestCanceled, response, context)
|
||||
HTTPClient._progress_callback.progress_dialog().canceled.connect(request_canceled)
|
||||
|
||||
def _requestCanceled(self, response, context):
|
||||
|
||||
@@ -373,28 +630,38 @@ class HTTPClient(QtCore.QObject):
|
||||
if "query_id" in context:
|
||||
self.notify_progress_end_query(context["query_id"])
|
||||
|
||||
def _processResponse(self, response, callback, context):
|
||||
def _processResponse(self, response, callback, context, request_body, ignore_errors):
|
||||
|
||||
if request_body is not None:
|
||||
request_body.close()
|
||||
|
||||
status = None
|
||||
body = None
|
||||
|
||||
if "query_id" in context:
|
||||
self.notify_progress_end_query(context["query_id"])
|
||||
|
||||
if response.error() != QtNetwork.QNetworkReply.NoError:
|
||||
error_code = response.error()
|
||||
error_message = response.errorString()
|
||||
log.info("Response error: {}".format(error_message))
|
||||
|
||||
if not ignore_errors:
|
||||
log.info("Response error: %s (error: %d)", error_message, error_code)
|
||||
|
||||
if error_code < 200:
|
||||
self._connected = False
|
||||
if not ignore_errors:
|
||||
self.close()
|
||||
if callback is not None:
|
||||
callback({"message": error_message}, error=True, server=self, context=context)
|
||||
return
|
||||
else:
|
||||
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
|
||||
if status == 401:
|
||||
print(error_message)
|
||||
|
||||
try:
|
||||
body = bytes(response.readAll()).decode("utf-8")
|
||||
# Some time anti-virus intercept our query and reply with garbage content
|
||||
body = bytes(response.readAll()).decode("utf-8").strip("\0")
|
||||
# Some time antivirus intercept our query and reply with garbage content
|
||||
except UnicodeError:
|
||||
body = None
|
||||
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
|
||||
@@ -407,10 +674,14 @@ class HTTPClient(QtCore.QObject):
|
||||
else:
|
||||
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
|
||||
log.debug("Decoding response from {} response {}".format(response.url().toString(), status))
|
||||
body = bytes(response.readAll()).decode("utf-8")
|
||||
try:
|
||||
body = bytes(response.readAll()).decode("utf-8").strip("\0")
|
||||
# Some time anti-virus intercept our query and reply with garbage content
|
||||
except UnicodeDecodeError:
|
||||
body = None
|
||||
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
|
||||
log.debug(body)
|
||||
if body and content_type == "application/json":
|
||||
if body and len(body.strip(" \n\t")) > 0 and content_type == "application/json":
|
||||
params = json.loads(body)
|
||||
else:
|
||||
params = {}
|
||||
@@ -423,17 +694,64 @@ class HTTPClient(QtCore.QObject):
|
||||
if status == 400:
|
||||
raise HttpBadRequest(body)
|
||||
|
||||
def RAMLimit(self):
|
||||
"""
|
||||
Returns the RAM limit for this server (used for RAM usage load balancing).
|
||||
|
||||
:returns: RAM limit (integer)
|
||||
"""
|
||||
|
||||
return self._ram_limit
|
||||
|
||||
def allocatedRAM(self):
|
||||
"""
|
||||
Amount of allocated RAM on this server (used for RAM usage load balancing).
|
||||
|
||||
:returns: allocated RAM (integer)
|
||||
"""
|
||||
|
||||
return self._allocated_ram
|
||||
|
||||
def increaseAllocatedRAM(self, ram):
|
||||
"""
|
||||
Increase the amount of allocated RAM on this server (used for RAM usage load balancing).
|
||||
|
||||
:param ram: amount of RAM (integer)
|
||||
"""
|
||||
|
||||
log.info("RAM usage on {} has increased by {} MB (total load is now {} MB)".format(self.url(), ram, self._allocated_ram + ram))
|
||||
self._allocated_ram += ram
|
||||
|
||||
def decreaseAllocatedRAM(self, ram):
|
||||
"""
|
||||
Decrease the amount of allocated RAM on this server (used for RAM usage load balancing).
|
||||
|
||||
:param ram: amount of RAM (integer)
|
||||
"""
|
||||
|
||||
log.info("RAM usage on {} has decreased by {} MB (total load is now {} MB)".format(self.url(), ram, self._allocated_ram - ram))
|
||||
self._allocated_ram -= ram
|
||||
if self._allocated_ram < 0:
|
||||
self._allocated_ram = 0
|
||||
|
||||
def dump(self):
|
||||
"""
|
||||
Returns a representation of this server.
|
||||
:returns: dictionary
|
||||
"""
|
||||
|
||||
return {"id": self._id,
|
||||
"host": self.host,
|
||||
"port": self.port,
|
||||
"local": self._local,
|
||||
"cloud": self._cloud}
|
||||
server = self.settings()
|
||||
server["id"] = self._id
|
||||
server["local"] = self._local
|
||||
server["vm"] = self._gns3_vm
|
||||
#server["cloud"] = self._cloud
|
||||
if "user" in server and self._local:
|
||||
del server["user"]
|
||||
if "password" in server:
|
||||
del server["password"]
|
||||
if server["protocol"] == "https":
|
||||
server["accept_insecure_certificate"] = self._accept_insecure_certificate
|
||||
return server
|
||||
|
||||
def isCloud(self):
|
||||
return False
|
||||
|
||||
153
gns3/image_manager.py
Normal file
153
gns3/image_manager.py
Normal file
@@ -0,0 +1,153 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
from gns3.servers import Servers
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.utils.file_copy_worker import FileCopyWorker
|
||||
from gns3.utils.progress_dialog import ProgressDialog
|
||||
|
||||
|
||||
class ImageManager:
|
||||
|
||||
def __init__(self):
|
||||
# Remember if we already ask the user about this image for this server
|
||||
self._asked_for_this_image = {}
|
||||
|
||||
def askCopyUploadImage(self, parent, path, server, vm_type):
|
||||
"""
|
||||
Ask user for copying the image to the default directory or upload
|
||||
it to remote server.
|
||||
|
||||
:param parent: Parent window
|
||||
:param path: File path on computer
|
||||
:param server: The server where the images should be located
|
||||
:param vm_type: Remote upload endpoint
|
||||
:returns path: Final path
|
||||
"""
|
||||
|
||||
if server and not server.isLocal():
|
||||
return self._uploadImageToRemoteServer(path, server, vm_type)
|
||||
else:
|
||||
destination_directory = self.getDirectoryForType(vm_type)
|
||||
if os.path.normpath(os.path.dirname(path)) != destination_directory:
|
||||
# the IOS image is not in the default images directory
|
||||
reply = QtWidgets.QMessageBox.question(parent,
|
||||
'Image',
|
||||
'Would you like to copy {} to the default images directory'.format(os.path.basename(path)),
|
||||
QtWidgets.QMessageBox.Yes,
|
||||
QtWidgets.QMessageBox.No)
|
||||
if reply == QtWidgets.QMessageBox.Yes:
|
||||
destination_path = os.path.join(destination_directory, os.path.basename(path))
|
||||
worker = FileCopyWorker(path, destination_path)
|
||||
progress_dialog = ProgressDialog(worker, 'Image', 'Copying {}'.format(os.path.basename(path)), 'Cancel', busy=True, parent=parent)
|
||||
progress_dialog.show()
|
||||
progress_dialog.exec_()
|
||||
errors = progress_dialog.errors()
|
||||
if errors:
|
||||
QtWidgets.QMessageBox.critical(parent, 'Image', '{}'.format(''.join(errors)))
|
||||
else:
|
||||
path = destination_path
|
||||
return path
|
||||
|
||||
def _uploadImageToRemoteServer(self, path, server, vm_type):
|
||||
"""
|
||||
Upload image to remote server
|
||||
|
||||
:param path: File path on computer
|
||||
:param server: The server where the images should be located
|
||||
:param vm_type: Image vm_type
|
||||
:returns path: Final path
|
||||
"""
|
||||
|
||||
if vm_type == 'QEMU':
|
||||
upload_endpoint = '/qemu/vms'
|
||||
elif vm_type == 'IOU':
|
||||
upload_endpoint = '/iou/vms'
|
||||
elif vm_type == 'DYNAMIPS':
|
||||
upload_endpoint = '/dynamips/vms'
|
||||
else:
|
||||
raise Exception('Invalid image vm_type')
|
||||
|
||||
filename = os.path.basename(path)
|
||||
server.post('{}/{}'.format(upload_endpoint, filename), None, body=pathlib.Path(path))
|
||||
return filename
|
||||
|
||||
def addMissingImage(self, filename, server, vm_type):
|
||||
"""
|
||||
Add a missing image to the queue of images require to be upload on remote server
|
||||
:param filename: Filename of the image
|
||||
:param server: Server where image should be uploaded
|
||||
:param vm_type: Type of the image
|
||||
"""
|
||||
|
||||
if self._asked_for_this_image.setdefault(server.id(), {}).setdefault(filename, False):
|
||||
return
|
||||
self._asked_for_this_image[server.id()][filename] = True
|
||||
|
||||
if server.isLocal():
|
||||
return
|
||||
path = os.path.join(self.getDirectoryForType(vm_type), filename)
|
||||
if os.path.exists(path):
|
||||
if self._askForUploadMissingImage(filename, server):
|
||||
self._uploadImageToRemoteServer(path, server, vm_type)
|
||||
del self._asked_for_this_image[server.id()][filename]
|
||||
|
||||
def _askForUploadMissingImage(self, filename, server):
|
||||
from gns3.main_window import MainWindow
|
||||
parent = MainWindow.instance()
|
||||
reply = QtWidgets.QMessageBox.warning(parent,
|
||||
'Image',
|
||||
'{} is missing on server {} but exist on your computer. Do you want to upload it?'.format(filename, server.url()),
|
||||
QtWidgets.QMessageBox.Yes,
|
||||
QtWidgets.QMessageBox.No)
|
||||
if reply == QtWidgets.QMessageBox.Yes:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getDirectory(self):
|
||||
"""
|
||||
Returns the images directory path.
|
||||
|
||||
:returns: path to the default images directory
|
||||
"""
|
||||
|
||||
return Servers.instance().localServerSettings()['images_path']
|
||||
|
||||
def getDirectoryForType(self, vm_type):
|
||||
"""
|
||||
Return the path of local directory of the images
|
||||
of a specific vm_type
|
||||
"""
|
||||
if vm_type == 'DYNAMIPS':
|
||||
return os.path.join(self.getDirectory(), 'IOS')
|
||||
else:
|
||||
return os.path.join(self.getDirectory(), vm_type)
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
"""
|
||||
Singleton to return only on instance of ImageManager.
|
||||
|
||||
:returns: instance of ImageManager
|
||||
"""
|
||||
|
||||
if not hasattr(ImageManager, '_instance') or ImageManager._instance is None:
|
||||
ImageManager._instance = ImageManager()
|
||||
return ImageManager._instance
|
||||
@@ -19,11 +19,11 @@
|
||||
Graphical representation of an ellipse on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from .shape_item import ShapeItem
|
||||
|
||||
|
||||
class EllipseItem(ShapeItem, QtGui.QGraphicsEllipseItem):
|
||||
class EllipseItem(QtWidgets.QGraphicsEllipseItem, ShapeItem):
|
||||
|
||||
"""
|
||||
Class to draw an ellipse on the scene.
|
||||
@@ -31,8 +31,8 @@ class EllipseItem(ShapeItem, QtGui.QGraphicsEllipseItem):
|
||||
|
||||
def __init__(self, pos=None, width=200, height=200):
|
||||
|
||||
QtGui.QGraphicsEllipseItem.__init__(self, 0, 0, width, height)
|
||||
ShapeItem.__init__(self)
|
||||
super().__init__()
|
||||
self.setRect(0, 0, width, height)
|
||||
pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.DashLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
|
||||
self.setPen(pen)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255, 255)) # default color is white and not transparent
|
||||
@@ -58,7 +58,7 @@ class EllipseItem(ShapeItem, QtGui.QGraphicsEllipseItem):
|
||||
:param widget: QWidget instance
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsEllipseItem.paint(self, painter, option, widget)
|
||||
super().paint(painter, option, widget)
|
||||
self.drawLayerInfo(painter)
|
||||
|
||||
def duplicate(self):
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Graphical representation of an Ethernet link for QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from .link_item import LinkItem
|
||||
from .note_item import NoteItem
|
||||
from ..ports.port import Port
|
||||
@@ -41,7 +41,7 @@ class EthernetLinkItem(LinkItem):
|
||||
|
||||
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
|
||||
|
||||
LinkItem.__init__(self, source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
|
||||
super().__init__(source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
|
||||
self._source_collision_offset = 0.0
|
||||
self._destination_collision_offset = 0.0
|
||||
|
||||
@@ -75,7 +75,7 @@ class EthernetLinkItem(LinkItem):
|
||||
:returns: QPainterPath instance
|
||||
"""
|
||||
|
||||
path = QtGui.QGraphicsPathItem.shape(self)
|
||||
path = QtWidgets.QGraphicsPathItem.shape(self)
|
||||
offset = self._point_size / 2
|
||||
if not self._adding_flag:
|
||||
if self.length:
|
||||
@@ -106,7 +106,7 @@ class EthernetLinkItem(LinkItem):
|
||||
:param widget: QWidget instance.
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsPathItem.paint(self, painter, option, widget)
|
||||
QtWidgets.QGraphicsPathItem.paint(self, painter, option, widget)
|
||||
if not self._adding_flag and self._settings["draw_link_status_points"]:
|
||||
|
||||
# points disappears if nodes are too close to each others.
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
Graphical representation of an image on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore
|
||||
|
||||
|
||||
class ImageItem(QtGui.QGraphicsPixmapItem):
|
||||
class ImageItem():
|
||||
|
||||
"""
|
||||
Class to insert an image on the scene.
|
||||
@@ -30,11 +30,9 @@ class ImageItem(QtGui.QGraphicsPixmapItem):
|
||||
|
||||
show_layer = False
|
||||
|
||||
def __init__(self, pixmap, image_path, pos=None):
|
||||
def __init__(self, image_path, pos=None):
|
||||
|
||||
QtGui.QGraphicsPixmapItem.__init__(self, pixmap)
|
||||
self.setFlags(self.ItemIsMovable | self.ItemIsSelectable)
|
||||
self.setTransformationMode(QtCore.Qt.SmoothTransformation)
|
||||
self._image_path = image_path
|
||||
if pos:
|
||||
self.setPos(pos)
|
||||
@@ -48,17 +46,6 @@ class ImageItem(QtGui.QGraphicsPixmapItem):
|
||||
from ..topology import Topology
|
||||
Topology.instance().removeImage(self)
|
||||
|
||||
def duplicate(self):
|
||||
"""
|
||||
Duplicates this image item.
|
||||
|
||||
:return: ImageItem instance
|
||||
"""
|
||||
|
||||
image_item = ImageItem(self.pixmap(), self._image_path, QtCore.QPointF(self.x() + 20, self.y() + 20))
|
||||
image_item.setZValue(self.zValue())
|
||||
return image_item
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
"""
|
||||
Paints the contents of an item in local coordinates.
|
||||
@@ -68,7 +55,7 @@ class ImageItem(QtGui.QGraphicsPixmapItem):
|
||||
:param widget: QWidget instance
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsPixmapItem.paint(self, painter, option, widget)
|
||||
super().paint(painter, option, widget)
|
||||
|
||||
if self.show_layer is False:
|
||||
return
|
||||
@@ -93,7 +80,7 @@ class ImageItem(QtGui.QGraphicsPixmapItem):
|
||||
:param value: Z value
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsPixmapItem.setZValue(self, value)
|
||||
super().setZValue(value)
|
||||
if self.zValue() < 0:
|
||||
self.setFlag(self.ItemIsSelectable, False)
|
||||
self.setFlag(self.ItemIsMovable, False)
|
||||
|
||||
@@ -23,10 +23,10 @@ Link items are graphical representation of a link on the QGraphicsScene
|
||||
import math
|
||||
import struct
|
||||
import sys
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class LinkItem(QtGui.QGraphicsPathItem):
|
||||
class LinkItem(QtWidgets.QGraphicsPathItem):
|
||||
|
||||
"""
|
||||
Base class for link items.
|
||||
@@ -44,8 +44,8 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
|
||||
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
|
||||
|
||||
QtGui.QGraphicsPathItem.__init__(self)
|
||||
self.setAcceptsHoverEvents(True)
|
||||
super().__init__()
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setZValue(-1)
|
||||
self._link = None
|
||||
|
||||
@@ -181,33 +181,33 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
|
||||
if not self._source_port.capturing() or not self._destination_port.capturing():
|
||||
# start capture
|
||||
start_capture_action = QtGui.QAction("Start capture", menu)
|
||||
start_capture_action = QtWidgets.QAction("Start capture", menu)
|
||||
start_capture_action.setIcon(QtGui.QIcon(':/icons/capture-start.svg'))
|
||||
start_capture_action.triggered.connect(self._startCaptureActionSlot)
|
||||
menu.addAction(start_capture_action)
|
||||
|
||||
if self._source_port.capturing() or self._destination_port.capturing():
|
||||
# stop capture
|
||||
stop_capture_action = QtGui.QAction("Stop capture", menu)
|
||||
stop_capture_action = QtWidgets.QAction("Stop capture", menu)
|
||||
stop_capture_action.setIcon(QtGui.QIcon(':/icons/capture-stop.svg'))
|
||||
stop_capture_action.triggered.connect(self._stopCaptureActionSlot)
|
||||
menu.addAction(stop_capture_action)
|
||||
|
||||
# start wireshark
|
||||
start_wireshark_action = QtGui.QAction("Start Wireshark", menu)
|
||||
start_wireshark_action = QtWidgets.QAction("Start Wireshark", menu)
|
||||
start_wireshark_action.setIcon(QtGui.QIcon(":/icons/wireshark.png"))
|
||||
start_wireshark_action.triggered.connect(self._startWiresharkActionSlot)
|
||||
menu.addAction(start_wireshark_action)
|
||||
|
||||
if sys.platform.startswith("win") and struct.calcsize("P") * 8 == 64:
|
||||
# Windows 64-bit only (Solarwinds RTV limitation).
|
||||
analyze_action = QtGui.QAction("Analyze capture", menu)
|
||||
analyze_action = QtWidgets.QAction("Analyze capture", menu)
|
||||
analyze_action.setIcon(QtGui.QIcon(':/icons/rtv.png'))
|
||||
analyze_action.triggered.connect(self._analyzeCaptureActionSlot)
|
||||
menu.addAction(analyze_action)
|
||||
|
||||
# delete
|
||||
delete_action = QtGui.QAction("Delete", menu)
|
||||
delete_action = QtWidgets.QAction("Delete", menu)
|
||||
delete_action.setIcon(QtGui.QIcon(':/icons/delete.svg'))
|
||||
delete_action.triggered.connect(self._deleteActionSlot)
|
||||
menu.addAction(delete_action)
|
||||
@@ -224,15 +224,15 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
# 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)
|
||||
QtGui.QApplication.sendEvent(MainWindow.instance(), key)
|
||||
QtWidgets.QApplication.sendEvent(MainWindow.instance(), key)
|
||||
return
|
||||
|
||||
# create the contextual menu
|
||||
self.setAcceptsHoverEvents(False)
|
||||
menu = QtGui.QMenu()
|
||||
self.setAcceptHoverEvents(False)
|
||||
menu = QtWidgets.QMenu()
|
||||
self.populateLinkContextualMenu(menu)
|
||||
menu.exec_(QtGui.QCursor.pos())
|
||||
self.setAcceptsHoverEvents(True)
|
||||
self.setAcceptHoverEvents(True)
|
||||
self._hovered = False
|
||||
self.adjust()
|
||||
|
||||
@@ -243,7 +243,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
:param event: QKeyEvent
|
||||
"""
|
||||
|
||||
#On pressing backspace or delete key, the selected link gets deleted
|
||||
# On pressing backspace or delete key, the selected link gets deleted
|
||||
if event.key() == QtCore.Qt.Key_Delete or event.key() == QtCore.Qt.Key_Backspace:
|
||||
self._deleteActionSlot()
|
||||
return
|
||||
@@ -274,10 +274,10 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
ports[port] = [self._destination_item.node(), self._destination_port, dlt]
|
||||
|
||||
if not ports:
|
||||
QtGui.QMessageBox.critical(self._main_window, "Packet capture", "Packet capture is not supported on this link")
|
||||
QtWidgets.QMessageBox.critical(self._main_window, "Packet capture", "Packet capture is not supported on this link")
|
||||
return
|
||||
|
||||
selection, ok = QtGui.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", list(ports.keys()), 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", list(ports.keys()), 0, False)
|
||||
if ok:
|
||||
if selection in ports:
|
||||
node, port, dlt = ports[selection]
|
||||
@@ -295,7 +295,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
ports[source_port] = [self._source_item.node(), self._source_port]
|
||||
destination_port = "{} port {}".format(self._destination_item.node().name(), self._destination_port.name())
|
||||
ports[destination_port] = [self._destination_item.node(), self._destination_port]
|
||||
selection, ok = QtGui.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", list(ports.keys()), 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", list(ports.keys()), 0, False)
|
||||
if ok:
|
||||
if selection in ports:
|
||||
node, port = ports[selection]
|
||||
@@ -315,7 +315,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
if self._source_port.capturing() and self._destination_port.capturing():
|
||||
ports = ["{} port {}".format(self._source_item.node().name(), self._source_port.name()),
|
||||
"{} port {}".format(self._destination_item.node().name(), self._destination_port.name())]
|
||||
selection, ok = QtGui.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", ports, 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(self._main_window, "Packet capture", "Please select a port:", ports, 0, False)
|
||||
if ok:
|
||||
if selection.endswith(self._source_port.name()):
|
||||
self._source_port.startPacketCaptureReader()
|
||||
@@ -326,7 +326,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
elif self._destination_port.capturing():
|
||||
self._destination_port.startPacketCaptureReader()
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(self._main_window, "Packet capture", "Cannot start Wireshark: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self._main_window, "Packet capture", "Cannot start Wireshark: {}".format(e))
|
||||
|
||||
def _analyzeCaptureActionSlot(self):
|
||||
"""
|
||||
@@ -338,7 +338,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
if self._source_port.capturing() and self._destination_port.capturing():
|
||||
ports = ["{} port {}".format(self._source_item.node().name(), self._source_port.name()),
|
||||
"{} port {}".format(self._destination_item.node().name(), self._destination_port.name())]
|
||||
selection, ok = QtGui.QInputDialog.getItem(self._main_window, "Capture analyzer", "Please select a port:", ports, 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(self._main_window, "Capture analyzer", "Please select a port:", ports, 0, False)
|
||||
if ok:
|
||||
if selection.endswith(self._source_port.name()):
|
||||
self._source_port.startPacketCaptureAnalyzer()
|
||||
@@ -349,7 +349,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
|
||||
elif self._destination_port.capturing():
|
||||
self._destination_port.startPacketCaptureAnalyzer()
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(self._main_window, "Capture analyzer", "Cannot start the packet capture analyzer program: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self._main_window, "Capture analyzer", "Cannot start the packet capture analyzer program: {}".format(e))
|
||||
|
||||
def setHovered(self, value):
|
||||
"""
|
||||
|
||||
@@ -19,25 +19,24 @@
|
||||
Graphical representation of a node on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui, QtSvg
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from .note_item import NoteItem
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
|
||||
class NodeItem():
|
||||
|
||||
"""
|
||||
Node for the scene.
|
||||
|
||||
:param node: Node instance
|
||||
:param default_symbol: Default symbol for the node representation on the scene
|
||||
:param hover_symbol: Hover symbol when the node is hovered on the scene
|
||||
"""
|
||||
|
||||
show_layer = False
|
||||
|
||||
def __init__(self, node, default_symbol=None, hover_symbol=None):
|
||||
|
||||
QtSvg.QGraphicsSvgItem.__init__(self)
|
||||
def __init__(self, node):
|
||||
|
||||
# attached node
|
||||
self._node = node
|
||||
@@ -48,28 +47,23 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
# link items connected to this node item.
|
||||
self._links = []
|
||||
|
||||
# set graphical settings for this node
|
||||
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsMovable)
|
||||
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsSelectable)
|
||||
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsFocusable)
|
||||
self.setFlag(QtSvg.QGraphicsSvgItem.ItemSendsGeometryChanges)
|
||||
self.setAcceptsHoverEvents(True)
|
||||
self.setZValue(1)
|
||||
effect = QtWidgets.QGraphicsColorizeEffect()
|
||||
effect.setColor(QtGui.QColor("black"))
|
||||
effect.setStrength(0.8)
|
||||
#effect = QtWidgets.QGraphicsDropShadowEffect()
|
||||
#effect.setColor(QtGui.QColor("darkGray"))
|
||||
#effect.setBlurRadius(0)
|
||||
#effect.setOffset(3, 3)
|
||||
self.setGraphicsEffect(effect)
|
||||
self.graphicsEffect().setEnabled(False)
|
||||
|
||||
# create renderers using symbols paths/resources
|
||||
if default_symbol:
|
||||
self._default_renderer = QtSvg.QSvgRenderer(default_symbol)
|
||||
if default_symbol != node.defaultSymbol():
|
||||
self._default_renderer.setObjectName(default_symbol)
|
||||
else:
|
||||
self._default_renderer = QtSvg.QSvgRenderer(node.defaultSymbol())
|
||||
if hover_symbol:
|
||||
self._hover_renderer = QtSvg.QSvgRenderer(hover_symbol)
|
||||
if hover_symbol != node.hoverSymbol():
|
||||
self._hover_renderer.setObjectName(hover_symbol)
|
||||
else:
|
||||
self._hover_renderer = QtSvg.QSvgRenderer(node.hoverSymbol())
|
||||
self.setSharedRenderer(self._default_renderer)
|
||||
# set graphical settings for this node
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setZValue(1)
|
||||
|
||||
# connect signals to know about some events
|
||||
# e.g. when the node has been started, stopped or suspended etc.
|
||||
@@ -98,43 +92,6 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
self._main_window = MainWindow.instance()
|
||||
self._settings = self._main_window.uiGraphicsView.settings()
|
||||
|
||||
def defaultRenderer(self):
|
||||
"""
|
||||
Returns the default QSvgRenderer.
|
||||
|
||||
:return: QSvgRenderer instance
|
||||
"""
|
||||
|
||||
return self._default_renderer
|
||||
|
||||
def setDefaultRenderer(self, default_renderer):
|
||||
"""
|
||||
Sets new default QSvgRenderer.
|
||||
|
||||
:param default_renderer: QSvgRenderer instance
|
||||
"""
|
||||
|
||||
self._default_renderer = default_renderer
|
||||
self.setSharedRenderer(self._default_renderer)
|
||||
|
||||
def hoverRenderer(self):
|
||||
"""
|
||||
Returns the hover QSvgRenderer.
|
||||
|
||||
:return: QSvgRenderer instance
|
||||
"""
|
||||
|
||||
return self._hover_renderer
|
||||
|
||||
def setHoverRenderer(self, hover_renderer):
|
||||
"""
|
||||
Sets new hover QSvgRenderer.
|
||||
|
||||
:param hover_renderer: QSvgRenderer instance
|
||||
"""
|
||||
|
||||
self._hover_renderer = hover_renderer
|
||||
|
||||
def setUnsavedState(self):
|
||||
"""
|
||||
Indicates the project is in a unsaved state.
|
||||
@@ -348,10 +305,10 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
"""
|
||||
|
||||
self._selected_port = None
|
||||
menu = QtGui.QMenu()
|
||||
menu = QtWidgets.QMenu()
|
||||
ports = self._node.ports()
|
||||
if not ports:
|
||||
QtGui.QMessageBox.critical(self.scene().parent(), "Link", "No port available, please configure this device")
|
||||
QtWidgets.QMessageBox.critical(self.scene().parent(), "Link", "No port available, please configure this device")
|
||||
return None
|
||||
|
||||
# sort the ports
|
||||
@@ -361,7 +318,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
# make the port number unique (special case with WICs).
|
||||
port_number = port.portNumber()
|
||||
if port_number >= 16:
|
||||
port_number *= 4
|
||||
port_number *= 8
|
||||
ports_dict[(port.adapterNumber() * 16) + port_number] = port
|
||||
elif port.portNumber()is not None:
|
||||
ports_dict[port.portNumber()] = port
|
||||
@@ -376,6 +333,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
# show a contextual menu for the user to choose a port
|
||||
for port in ports:
|
||||
port_object = ports_dict[port]
|
||||
log.debug("Node '{}' Port {} Type {}".format(self.node(), port_object.name(), type(port_object.name())))
|
||||
if port in unavailable_ports:
|
||||
# this port cannot be chosen by the user (grayed out)
|
||||
action = menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port_object.name())
|
||||
@@ -414,19 +372,19 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
"""
|
||||
|
||||
# dynamically change the renderer when this node item is selected/unselected.
|
||||
if change == QtSvg.QGraphicsSvgItem.ItemSelectedChange:
|
||||
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
|
||||
if value:
|
||||
self.setSharedRenderer(self._hover_renderer)
|
||||
self.graphicsEffect().setEnabled(True)
|
||||
else:
|
||||
self.setSharedRenderer(self._default_renderer)
|
||||
self.graphicsEffect().setEnabled(False)
|
||||
|
||||
# adjust link item positions when this node is moving or has changed.
|
||||
if change == QtSvg.QGraphicsSvgItem.ItemPositionChange or change == QtSvg.QGraphicsSvgItem.ItemPositionHasChanged:
|
||||
if change == QtWidgets.QGraphicsItem.ItemPositionChange or change == QtWidgets.QGraphicsItem.ItemPositionHasChanged:
|
||||
self.setUnsavedState()
|
||||
for link in self._links:
|
||||
link.adjust()
|
||||
|
||||
return QtGui.QGraphicsItem.itemChange(self, change, value)
|
||||
return QtWidgets.QGraphicsItem.itemChange(self, change, value)
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
"""
|
||||
@@ -439,8 +397,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
|
||||
# don't show the selection rectangle
|
||||
if not self._settings["draw_rectangle_selected_item"]:
|
||||
option.state = QtGui.QStyle.State_None
|
||||
QtSvg.QGraphicsSvgItem.paint(self, painter, option, widget)
|
||||
option.state = QtWidgets.QStyle.State_None
|
||||
super().paint(painter, option, widget)
|
||||
|
||||
if not self._initialized or self.show_layer:
|
||||
brect = self.boundingRect()
|
||||
@@ -464,7 +422,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
:param value: Z value
|
||||
"""
|
||||
|
||||
QtSvg.QGraphicsSvgItem.setZValue(self, value)
|
||||
super().setZValue(value)
|
||||
if self.zValue() < 0:
|
||||
self.setFlag(self.ItemIsSelectable, False)
|
||||
self.setFlag(self.ItemIsMovable, False)
|
||||
@@ -488,13 +446,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
"""
|
||||
|
||||
self.setCustomToolTip()
|
||||
# dynamically change the renderer when this node item is hovered.
|
||||
if not self.isSelected():
|
||||
self.setSharedRenderer(self._hover_renderer)
|
||||
# effect = QtGui.QGraphicsColorizeEffect()
|
||||
# effect.setColor(QtGui.QColor("black"))
|
||||
# effect.setStrength(0.8)
|
||||
# self.setGraphicsEffect(effect)
|
||||
self.graphicsEffect().setEnabled(True)
|
||||
|
||||
def hoverLeaveEvent(self, event):
|
||||
"""
|
||||
@@ -503,7 +456,5 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
|
||||
:param event: QGraphicsSceneHoverEvent instance
|
||||
"""
|
||||
|
||||
# dynamically change the renderer back to the default when this node item is not hovered anymore.
|
||||
if not self.isSelected():
|
||||
self.setSharedRenderer(self._default_renderer)
|
||||
# self.graphicsEffect().setEnabled(False)
|
||||
self.graphicsEffect().setEnabled(False)
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
Graphical representation of a note on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtWidgets, QtGui
|
||||
|
||||
|
||||
class NoteItem(QtGui.QGraphicsTextItem):
|
||||
|
||||
class NoteItem(QtWidgets.QGraphicsTextItem):
|
||||
"""
|
||||
Text note for the QGraphicsView.
|
||||
|
||||
@@ -34,9 +33,10 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
|
||||
QtGui.QGraphicsTextItem.__init__(self, parent)
|
||||
super().__init__(parent)
|
||||
|
||||
from ..main_window import MainWindow
|
||||
|
||||
main_window = MainWindow.instance()
|
||||
view_settings = main_window.uiGraphicsView.settings()
|
||||
qt_font = QtGui.QFont()
|
||||
@@ -59,6 +59,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
|
||||
self.scene().removeItem(self)
|
||||
from ..topology import Topology
|
||||
|
||||
Topology.instance().removeNote(self)
|
||||
|
||||
def editable(self):
|
||||
@@ -101,7 +102,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
if self.rotation() < 360.0:
|
||||
self.setRotation(self.rotation() + 1)
|
||||
else:
|
||||
QtGui.QGraphicsTextItem.keyPressEvent(self, event)
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def editText(self):
|
||||
"""
|
||||
@@ -132,7 +133,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
:param event: QFocusEvent instance
|
||||
"""
|
||||
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, False)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, False)
|
||||
cursor = self.textCursor()
|
||||
if cursor.hasSelection():
|
||||
cursor.clearSelection()
|
||||
@@ -142,7 +143,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
# delete the note if empty
|
||||
self.delete()
|
||||
return
|
||||
return QtGui.QGraphicsTextItem.focusOutEvent(self, event)
|
||||
return super().focusOutEvent(event)
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
"""
|
||||
@@ -153,7 +154,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
:param widget: QWidget instance
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsTextItem.paint(self, painter, option, widget)
|
||||
super().paint(painter, option, widget)
|
||||
|
||||
if self.show_layer is False or self.parentItem():
|
||||
return
|
||||
@@ -178,7 +179,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
:param value: Z value
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsTextItem.setZValue(self, value)
|
||||
super().setZValue(value)
|
||||
if self.zValue() < 0:
|
||||
self.setFlag(self.ItemIsSelectable, False)
|
||||
self.setFlag(self.ItemIsMovable, False)
|
||||
@@ -198,7 +199,7 @@ class NoteItem(QtGui.QGraphicsTextItem):
|
||||
"y": self.y()}
|
||||
|
||||
note_info["font"] = self.font().toString()
|
||||
note_info["color"] = self.defaultTextColor().name()
|
||||
note_info["color"] = self.defaultTextColor().name(QtGui.QColor.HexArgb)
|
||||
if self.rotation() != 0:
|
||||
note_info["rotation"] = self.rotation()
|
||||
if self.zValue() != 2:
|
||||
|
||||
47
gns3/items/pixmap_image_item.py
Normal file
47
gns3/items/pixmap_image_item.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Graphical representation of a Pixmap image on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtWidgets
|
||||
from .image_item import ImageItem
|
||||
|
||||
|
||||
class PixmapImageItem(ImageItem, QtWidgets.QGraphicsPixmapItem):
|
||||
|
||||
"""
|
||||
Class to insert an pixmap image on the scene.
|
||||
"""
|
||||
|
||||
def __init__(self, pixmap, image_path, pos=None):
|
||||
|
||||
QtWidgets.QGraphicsPixmapItem.__init__(self, pixmap)
|
||||
ImageItem.__init__(self, image_path, pos)
|
||||
self.setTransformationMode(QtCore.Qt.SmoothTransformation)
|
||||
|
||||
def duplicate(self):
|
||||
"""
|
||||
Duplicates this image item.
|
||||
|
||||
:return: PixmapImageItem instance
|
||||
"""
|
||||
|
||||
image_item = PixmapImageItem(self.pixmap(), self._image_path, QtCore.QPointF(self.x() + 20, self.y() + 20))
|
||||
image_item.setZValue(self.zValue())
|
||||
return image_item
|
||||
54
gns3/items/pixmap_node_item.py
Normal file
54
gns3/items/pixmap_node_item.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Graphical representation of a pixmap node on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtGui, QtWidgets
|
||||
from .node_item import NodeItem
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PixmapNodeItem(NodeItem, QtWidgets.QGraphicsPixmapItem):
|
||||
|
||||
"""
|
||||
Pixmap node for the scene.
|
||||
|
||||
:param node: Node instance
|
||||
:param pixmap_symbol: symbol for the node representation on the scene
|
||||
"""
|
||||
|
||||
def __init__(self, node, pixmap_symbol_path):
|
||||
|
||||
QtWidgets.QGraphicsPixmapItem.__init__(self)
|
||||
NodeItem.__init__(self, node)
|
||||
|
||||
self._pixmap_symbol_path = pixmap_symbol_path
|
||||
pixmap = QtGui.QPixmap(pixmap_symbol_path)
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
def pixmapSymbolPath(self):
|
||||
"""
|
||||
Returns the pixmap path
|
||||
|
||||
:return: path to the Pixmap file.
|
||||
"""
|
||||
|
||||
return self._pixmap_symbol_path
|
||||
@@ -19,11 +19,11 @@
|
||||
Graphical representation of a rectangle on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from .shape_item import ShapeItem
|
||||
|
||||
|
||||
class RectangleItem(ShapeItem, QtGui.QGraphicsRectItem):
|
||||
class RectangleItem(QtWidgets.QGraphicsRectItem, ShapeItem):
|
||||
|
||||
"""
|
||||
Class to draw a rectangle on the scene.
|
||||
@@ -31,8 +31,8 @@ class RectangleItem(ShapeItem, QtGui.QGraphicsRectItem):
|
||||
|
||||
def __init__(self, pos=None, width=200, height=100):
|
||||
|
||||
QtGui.QGraphicsRectItem.__init__(self, 0, 0, width, height)
|
||||
ShapeItem.__init__(self)
|
||||
super().__init__()
|
||||
self.setRect(0, 0, width, height)
|
||||
pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
|
||||
self.setPen(pen)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255, 255)) # default color is white and not transparent
|
||||
@@ -58,7 +58,7 @@ class RectangleItem(ShapeItem, QtGui.QGraphicsRectItem):
|
||||
:param widget: QWidget instance
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsRectItem.paint(self, painter, option, widget)
|
||||
super().paint(painter, option, widget)
|
||||
self.drawLayerInfo(painter)
|
||||
|
||||
def duplicate(self):
|
||||
|
||||
@@ -20,7 +20,7 @@ Graphical representation of a Serial link on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
import math
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
from .link_item import LinkItem
|
||||
from .note_item import NoteItem
|
||||
from ..ports.port import Port
|
||||
@@ -42,7 +42,7 @@ class SerialLinkItem(LinkItem):
|
||||
|
||||
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
|
||||
|
||||
LinkItem.__init__(self, source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
|
||||
super().__init__(source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
|
||||
|
||||
def adjust(self):
|
||||
"""
|
||||
@@ -89,7 +89,7 @@ class SerialLinkItem(LinkItem):
|
||||
:returns: QPainterPath instance
|
||||
"""
|
||||
|
||||
path = QtGui.QGraphicsPathItem.shape(self)
|
||||
path = QtWidgets.QGraphicsPathItem.shape(self)
|
||||
offset = self._point_size / 2
|
||||
point = self.source
|
||||
path.addEllipse(point.x() - offset, point.y() - offset, self._point_size, self._point_size)
|
||||
@@ -106,7 +106,7 @@ class SerialLinkItem(LinkItem):
|
||||
:param widget: QWidget instance.
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsPathItem.paint(self, painter, option, widget)
|
||||
QtWidgets.QGraphicsPathItem.paint(self, painter, option, widget)
|
||||
|
||||
if not self._adding_flag and self._settings["draw_link_status_points"]:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Base class for shape items (Rectangle, ellipse etc.).
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtGui
|
||||
from ..qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class ShapeItem:
|
||||
@@ -30,10 +30,10 @@ class ShapeItem:
|
||||
|
||||
show_layer = False
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, **kws):
|
||||
|
||||
self.setFlags(QtGui.QGraphicsItem.ItemIsMovable | QtGui.QGraphicsItem.ItemIsFocusable | QtGui.QGraphicsItem.ItemIsSelectable)
|
||||
self.setAcceptsHoverEvents(True)
|
||||
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsFocusable | QtWidgets.QGraphicsItem.ItemIsSelectable)
|
||||
self.setAcceptHoverEvents(True)
|
||||
self._border = 5
|
||||
self._edge = None
|
||||
|
||||
@@ -58,7 +58,7 @@ class ShapeItem:
|
||||
if self.rotation() < 360.0:
|
||||
self.setRotation(self.rotation() + 1)
|
||||
else:
|
||||
QtGui.QGraphicsItem.keyPressEvent(self, event)
|
||||
QtWidgets.QGraphicsItem.keyPressEvent(self, event)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
"""
|
||||
@@ -69,22 +69,22 @@ class ShapeItem:
|
||||
|
||||
self.update()
|
||||
if event.pos().x() > (self.rect().right() - self._border):
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
|
||||
self._edge = "right"
|
||||
|
||||
elif event.pos().x() < (self.rect().left() + self._border):
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
|
||||
self._edge = "left"
|
||||
|
||||
elif event.pos().y() < (self.rect().top() + self._border):
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
|
||||
self._edge = "top"
|
||||
|
||||
elif event.pos().y() > (self.rect().bottom() - self._border):
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
|
||||
self._edge = "bottom"
|
||||
|
||||
QtGui.QGraphicsItem.mousePressEvent(self, event)
|
||||
QtWidgets.QGraphicsItem.mousePressEvent(self, event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
"""
|
||||
@@ -94,9 +94,9 @@ class ShapeItem:
|
||||
"""
|
||||
|
||||
self.update()
|
||||
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
|
||||
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
|
||||
self._edge = None
|
||||
QtGui.QGraphicsItem.mouseReleaseEvent(self, event)
|
||||
QtWidgets.QGraphicsItem.mouseReleaseEvent(self, event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""
|
||||
@@ -145,7 +145,7 @@ class ShapeItem:
|
||||
self.setPos(scenePos.x(), self.y())
|
||||
self._edge = "left"
|
||||
|
||||
QtGui.QGraphicsItem.mouseMoveEvent(self, event)
|
||||
QtWidgets.QGraphicsItem.mouseMoveEvent(self, event)
|
||||
|
||||
def hoverMoveEvent(self, event):
|
||||
"""
|
||||
@@ -208,7 +208,7 @@ class ShapeItem:
|
||||
:param value: Z value
|
||||
"""
|
||||
|
||||
QtGui.QGraphicsItem.setZValue(self, value)
|
||||
QtWidgets.QGraphicsItem.setZValue(self, value)
|
||||
if self.zValue() < 0:
|
||||
self.setFlag(self.ItemIsSelectable, False)
|
||||
self.setFlag(self.ItemIsMovable, False)
|
||||
|
||||
47
gns3/items/svg_image_item.py
Normal file
47
gns3/items/svg_image_item.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Graphical representation of a SVG image on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtCore, QtSvg
|
||||
from .image_item import ImageItem
|
||||
|
||||
|
||||
class SvgImageItem(ImageItem, QtSvg.QGraphicsSvgItem):
|
||||
|
||||
"""
|
||||
Class to insert a SVG image on the scene.
|
||||
"""
|
||||
|
||||
def __init__(self, renderer, image_path, pos=None):
|
||||
|
||||
QtSvg.QGraphicsSvgItem.__init__(self)
|
||||
ImageItem.__init__(self, image_path, pos)
|
||||
self.setSharedRenderer(renderer)
|
||||
|
||||
def duplicate(self):
|
||||
"""
|
||||
Duplicates this image item.
|
||||
|
||||
:return: SvgImageItem instance
|
||||
"""
|
||||
|
||||
image_item = SvgImageItem(self.renderer(), self._image_path, QtCore.QPointF(self.x() + 20, self.y() + 20))
|
||||
image_item.setZValue(self.zValue())
|
||||
return image_item
|
||||
50
gns3/items/svg_node_item.py
Normal file
50
gns3/items/svg_node_item.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Graphical representation of a SVG node on the QGraphicsScene.
|
||||
"""
|
||||
|
||||
from ..qt import QtSvg
|
||||
from .node_item import NodeItem
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SvgNodeItem(NodeItem, QtSvg.QGraphicsSvgItem):
|
||||
|
||||
"""
|
||||
SVG node for the scene.
|
||||
|
||||
:param node: Node instance
|
||||
:param symbol: symbol for the node representation on the scene
|
||||
"""
|
||||
|
||||
def __init__(self, node, symbol=None):
|
||||
|
||||
QtSvg.QGraphicsSvgItem.__init__(self)
|
||||
NodeItem.__init__(self, node)
|
||||
|
||||
# create renderer using symbols path/resource
|
||||
if symbol:
|
||||
renderer = QtSvg.QSvgRenderer(symbol)
|
||||
if symbol != node.defaultSymbol():
|
||||
renderer.setObjectName(symbol)
|
||||
else:
|
||||
renderer = QtSvg.QSvgRenderer(node.defaultSymbol())
|
||||
self.setSharedRenderer(renderer)
|
||||
75
gns3/licence.py
Normal file
75
gns3/licence.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import rsa
|
||||
import sys
|
||||
import os
|
||||
import base64
|
||||
|
||||
PUB_KEY = b"""-----BEGIN RSA PUBLIC KEY-----
|
||||
MIICCgKCAgEAiE4Zgzge3Cg6EUfct7vnzcmXkIvsy6g/QkfEeKSz3Cd+L7kxVZGE
|
||||
weOXySrSSrRBoF1i2JhL2KkqZTY31972deviL+fv+TgE5RueyERFey3fw7+oN/RW
|
||||
i8UIUvRqHjwocCuJq5yUiOv+AdGKG3TNeYXvx4Xvnrr4AJnJRThDfqd0nr8QAXRn
|
||||
/Ifx4MKivL8RDyqHoVlHvHeyJmtaZIzsYthsK3FU2XED6d6xwbga3t2cb4+DfJa3
|
||||
rBtWnoIXHiRdZZUtl34dGiiyxKL2yco+Dpd5pUvw6F7+n77SnSwN+F0ZzrrgUMHA
|
||||
vBHBnF4WB6mjRFxbO+B/H1OxnXcjwxgYWLCbkrhQogqyfdkmacppWLOH9OyzGUkY
|
||||
r7qITLCWSAHuIqXmQF4VAqCPYwEK7o6ndebFk1jaAAPGIw52AA1YOSXJ6jpKiO7f
|
||||
5gXT3xRfv4kW1Fp6le0hp0Laz6VGbOv44vauxk516v5MI+CUL3u5TOmGWM53u1OG
|
||||
qq6SfL+5Cu0/4L+SUaJ7nzN+PgWx6BEd0LRzEVQcmRPA4zHbhJ7ebBbYOul9RFyW
|
||||
8D7yy7mUQZwVQDcuaB6l2pu0BfZppb+Uf81h0nRQIrHt7BRBiyaGojQIHsw8CrqP
|
||||
3fsnHUvqtNLipC26FSTW4wlPIEktsWU8TABgjbuS45+zFTI141/J77ECAwEAAQ==
|
||||
-----END RSA PUBLIC KEY-----"""
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def checkLicence():
|
||||
"""
|
||||
Return true if the user as correctly installed the licence file
|
||||
"""
|
||||
appname = "GNS3"
|
||||
|
||||
filename = "licence.txt"
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
# On windows, the user specific configuration file location is %APPDATA%/GNS3/gns3_gui.conf
|
||||
appdata = os.path.expandvars("%APPDATA%")
|
||||
licence_file = os.path.join(appdata, appname, filename)
|
||||
|
||||
else:
|
||||
# On UNIX-like platforms, the user specific configuration file location is /etc/xdg/GNS3/gns3_gui.conf
|
||||
home = os.path.expanduser("~")
|
||||
licence_file = os.path.join(home, ".config", appname, filename)
|
||||
|
||||
return check_licence_file(licence_file)
|
||||
|
||||
|
||||
def check_licence_file(licence_file):
|
||||
if os.path.exists(licence_file):
|
||||
with open(licence_file) as f:
|
||||
email = f.readline().strip()
|
||||
key = f.readline().strip()
|
||||
pubkey = rsa.PublicKey.load_pkcs1(PUB_KEY)
|
||||
try:
|
||||
rsa.verify(email.encode("utf-8"), base64.b64decode(key), pubkey)
|
||||
log.info("Found a valid licence file. Thanks for your support")
|
||||
return True
|
||||
except rsa.pkcs1.VerificationError:
|
||||
log.error("Invalid licence file.")
|
||||
return False
|
||||
return False
|
||||
32
gns3/link.py
32
gns3/link.py
@@ -48,7 +48,7 @@ class Link(QtCore.QObject):
|
||||
|
||||
def __init__(self, source_node, source_port, destination_node, destination_port):
|
||||
|
||||
super(Link, self).__init__()
|
||||
super().__init__()
|
||||
|
||||
log.info("adding link from {} {} to {} {}".format(source_node.name(),
|
||||
source_port.name(),
|
||||
@@ -206,7 +206,7 @@ class Link(QtCore.QObject):
|
||||
|
||||
# check that the node is connected to this link as a source
|
||||
if node_id == self._source_node.id() and port_id == self._source_port.id():
|
||||
laddr = self._source_node.server().host
|
||||
laddr = self._source_node.server().host()
|
||||
self._source_udp = (lport, laddr)
|
||||
# disconnect the signal has we don't expect new source UDP info for this link.
|
||||
self._source_node.allocate_udp_nio_signal.disconnect(self.UDPPortAllocatedSlot)
|
||||
@@ -217,7 +217,7 @@ class Link(QtCore.QObject):
|
||||
|
||||
# check that the node is connected to this link as a destination
|
||||
elif node_id == self._destination_node.id() and port_id == self._destination_port.id():
|
||||
laddr = self._destination_node.server().host
|
||||
laddr = self._destination_node.server().host()
|
||||
self._destination_udp = (lport, laddr)
|
||||
# disconnect the signal has we don't expect new source UDP info for this link.
|
||||
self._destination_node.allocate_udp_nio_signal.disconnect(self.UDPPortAllocatedSlot)
|
||||
@@ -338,21 +338,19 @@ class Link(QtCore.QObject):
|
||||
"""
|
||||
|
||||
if not self._stub:
|
||||
if self._source_node.id() != node_id:
|
||||
try:
|
||||
# the destination node has canceled its NIO allocation
|
||||
self._destination_node.nio_signal.disconnect(self.newNIOSlot)
|
||||
except TypeError:
|
||||
# ignore TypeError: 'method' object is not connected
|
||||
pass
|
||||
try:
|
||||
# the destination node has canceled its NIO allocation
|
||||
self._destination_node.nio_signal.disconnect(self.newNIOSlot)
|
||||
except TypeError:
|
||||
# ignore TypeError: 'method' object is not connected
|
||||
pass
|
||||
|
||||
elif self._destination_node.id() != node_id:
|
||||
try:
|
||||
# the source node has canceled its NIO allocation
|
||||
self._source_node.nio_signal.disconnect(self.newNIOSlot)
|
||||
except TypeError:
|
||||
# ignore TypeError: 'method' object is not connected
|
||||
pass
|
||||
try:
|
||||
# the source node has canceled its NIO allocation
|
||||
self._source_node.nio_signal.disconnect(self.newNIOSlot)
|
||||
except TypeError:
|
||||
# ignore TypeError: 'method' object is not connected
|
||||
pass
|
||||
|
||||
self._source_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
|
||||
self._destination_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
|
||||
|
||||
@@ -18,56 +18,77 @@
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
import copy
|
||||
from pkg_resources import parse_version
|
||||
|
||||
|
||||
from .qt import QtCore
|
||||
from .version import __version__
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LocalConfig:
|
||||
class PeriodicCheckConfig(QtCore.QThread):
|
||||
|
||||
"""
|
||||
Timer for checking if the configuration file change
|
||||
on disk.
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self._parent = parent
|
||||
|
||||
def run(self):
|
||||
self._timer = QtCore.QTimer()
|
||||
self._timer.timeout.connect(self._parent._checkConfigChanged)
|
||||
self._timer.setInterval(1000) # milliseconds
|
||||
self._timer.start()
|
||||
self.exec_()
|
||||
|
||||
|
||||
class LocalConfig(QtCore.QObject):
|
||||
|
||||
"""
|
||||
Handles the local GUI settings.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
config_changed_signal = QtCore.Signal()
|
||||
|
||||
def __init__(self, config_file=None):
|
||||
|
||||
super().__init__()
|
||||
self._settings = {}
|
||||
self._last_config_changed = None
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
filename = "gns3_gui.ini"
|
||||
else:
|
||||
filename = "gns3_gui.conf"
|
||||
|
||||
if sys.platform.startswith("darwin"):
|
||||
appname = "gns3.net"
|
||||
else:
|
||||
appname = "GNS3"
|
||||
self._migrateOldConfigPath()
|
||||
|
||||
appname = "GNS3"
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
|
||||
# On windows, the system wide configuration file location is %COMMON_APPDATA%/GNS3/gns3_gui.conf
|
||||
common_appdata = os.path.expandvars("%COMMON_APPDATA%")
|
||||
system_wide_config_file = os.path.join(common_appdata, appname, filename)
|
||||
|
||||
# On windows, the user specific configuration file location is %APPDATA%/GNS3/gns3_gui.conf
|
||||
appdata = os.path.expandvars("%APPDATA%")
|
||||
self._config_file = os.path.join(appdata, appname, filename)
|
||||
|
||||
else:
|
||||
|
||||
# On UNIX-like platforms, the system wide configuration file location is /etc/xdg/GNS3/gns3_gui.conf
|
||||
system_wide_config_file = os.path.join("/etc/xdg", appname, filename)
|
||||
|
||||
# On UNIX-like platforms, the user specific configuration file location is /etc/xdg/GNS3/gns3_gui.conf
|
||||
home = os.path.expanduser("~")
|
||||
self._config_file = os.path.join(home, ".config", appname, filename)
|
||||
if config_file:
|
||||
self._config_file = config_file
|
||||
else:
|
||||
self._config_file = os.path.join(LocalConfig.configDirectory(), filename)
|
||||
|
||||
# First load system wide settings
|
||||
if os.path.exists(system_wide_config_file):
|
||||
self._settings = self._readConfig(system_wide_config_file)
|
||||
if not self._settings:
|
||||
log.warning("No system wide settings loaded from {}".format(system_wide_config_file))
|
||||
self._readConfig(system_wide_config_file)
|
||||
|
||||
config_file_in_cwd = os.path.join(os.getcwd(), filename)
|
||||
if os.path.exists(config_file_in_cwd):
|
||||
@@ -85,19 +106,86 @@ class LocalConfig:
|
||||
user_settings = self._readConfig(self._config_file)
|
||||
# overwrite system wide settings with user specific ones
|
||||
self._settings.update(user_settings)
|
||||
self._migrateOldConfig()
|
||||
self._writeConfig()
|
||||
|
||||
self._check_thread = PeriodicCheckConfig(self)
|
||||
self._check_thread.start()
|
||||
|
||||
@staticmethod
|
||||
def configDirectory():
|
||||
"""
|
||||
Get the configuration directory
|
||||
"""
|
||||
if sys.platform.startswith("win"):
|
||||
appdata = os.path.expandvars("%APPDATA%")
|
||||
path = os.path.join(appdata, "GNS3")
|
||||
else:
|
||||
home = os.path.expanduser("~")
|
||||
path = os.path.join(home, ".config", "GNS3")
|
||||
return os.path.normpath(path)
|
||||
|
||||
def _migrateOldConfigPath(self):
|
||||
"""
|
||||
Migrate pre 1.4 config path
|
||||
"""
|
||||
|
||||
# In < 1.4 on Mac the config was in a gns3.net directory
|
||||
# We have move to same location as Linux
|
||||
if sys.platform.startswith("darwin"):
|
||||
old_path = os.path.join(os.path.expanduser("~"), ".config", "gns3.net")
|
||||
new_path = os.path.join(os.path.expanduser("~"), ".config", "GNS3")
|
||||
if os.path.exists(old_path) and not os.path.exists(new_path):
|
||||
try:
|
||||
shutil.copytree(old_path, new_path)
|
||||
except OSError as e:
|
||||
print("Can't copy the old config: %s", str(e))
|
||||
|
||||
def _migrateOldConfig(self):
|
||||
"""
|
||||
Migrate pre 1.4 config
|
||||
"""
|
||||
|
||||
if "version" not in self._settings or parse_version(self._settings["version"]) < parse_version("1.4.0"):
|
||||
|
||||
servers = self._settings.get("Servers", {})
|
||||
|
||||
if "LocalServer" in self._settings:
|
||||
servers["local_server"] = copy.copy(self._settings["LocalServer"])
|
||||
|
||||
# We migrate the server binary for OSX due to the change from py2app to CX freeze
|
||||
if servers["local_server"]["path"] == "/Applications/GNS3.app/Contents/Resources/server/Contents/MacOS/gns3server":
|
||||
servers["local_server"]["path"] = "/Applications/GNS3.app/Contents/MacOS/gns3server"
|
||||
|
||||
if "RemoteServers" in self._settings:
|
||||
servers["remote_servers"] = copy.copy(self._settings["RemoteServers"])
|
||||
|
||||
self._settings["Servers"] = servers
|
||||
|
||||
if "GUI" in self._settings:
|
||||
main_window = self._settings.get("MainWindow", {})
|
||||
main_window["hide_getting_started_dialog"] = self._settings["GUI"].get("hide_getting_started_dialog", False)
|
||||
self._settings["MainWindow"] = main_window
|
||||
|
||||
def _readConfig(self, config_path):
|
||||
"""
|
||||
Read the configuration file.
|
||||
"""
|
||||
|
||||
log.info("Load config from %s", config_path)
|
||||
try:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
self._last_config_changed = os.stat(config_path).st_mtime
|
||||
config = json.load(f)
|
||||
self._settings.update(config)
|
||||
except (ValueError, OSError) as e:
|
||||
log.error("Could not read the config file {}: {}".format(self._config_file, e))
|
||||
|
||||
# Update already loaded section
|
||||
for section in self._settings.keys():
|
||||
if isinstance(self._settings[section], dict):
|
||||
self.loadSectionSettings(section, self._settings[section])
|
||||
|
||||
return dict()
|
||||
|
||||
def _writeConfig(self):
|
||||
@@ -107,11 +195,21 @@ class LocalConfig:
|
||||
|
||||
self._settings["version"] = __version__
|
||||
try:
|
||||
with open(self._config_file, "w", encoding="utf-8") as f:
|
||||
temporary = os.path.join(os.path.dirname(self._config_file), "gns3_gui.tmp")
|
||||
with open(temporary, "w", encoding="utf-8") as f:
|
||||
json.dump(self._settings, f, sort_keys=True, indent=4)
|
||||
shutil.move(temporary, self._config_file)
|
||||
log.info("Configuration save to %s", self._config_file)
|
||||
self._last_config_changed = os.stat(self._config_file).st_mtime
|
||||
except (ValueError, OSError) as e:
|
||||
log.error("Could not write the config file {}: {}".format(self._config_file, e))
|
||||
|
||||
def _checkConfigChanged(self):
|
||||
if self._last_config_changed and self._last_config_changed < os.stat(self._config_file).st_mtime:
|
||||
log.info("Client config has changed, reloading it...")
|
||||
self._readConfig(self._config_file)
|
||||
self.config_changed_signal.emit()
|
||||
|
||||
def configFilePath(self):
|
||||
"""
|
||||
Returns the config file path.
|
||||
@@ -128,8 +226,8 @@ class LocalConfig:
|
||||
:returns: path to the config file.
|
||||
"""
|
||||
|
||||
self._settings = self._readConfig(self._config_file)
|
||||
self._config_file = config_file
|
||||
self._readConfig(self._config_file)
|
||||
|
||||
def settings(self):
|
||||
"""
|
||||
@@ -138,7 +236,7 @@ class LocalConfig:
|
||||
:returns: settings (dict)
|
||||
"""
|
||||
|
||||
return self._readConfig(self._config_file)
|
||||
return copy.deepcopy(self._settings)
|
||||
|
||||
def setSettings(self, settings):
|
||||
"""
|
||||
@@ -147,8 +245,9 @@ class LocalConfig:
|
||||
:param settings: settings to save (dict)
|
||||
"""
|
||||
|
||||
self._settings.update(settings)
|
||||
self._writeConfig()
|
||||
if self._settings != settings:
|
||||
self._settings.update(settings)
|
||||
self._writeConfig()
|
||||
|
||||
def loadSectionSettings(self, section, default_settings):
|
||||
"""
|
||||
@@ -161,15 +260,24 @@ class LocalConfig:
|
||||
|
||||
settings = self.settings().get(section, dict())
|
||||
|
||||
# use default values for missing settings
|
||||
for name, value in default_settings.items():
|
||||
if name not in settings:
|
||||
settings[name] = value
|
||||
def _copySettings(local, default):
|
||||
"""
|
||||
Copy only existing settings, ignore the other.
|
||||
Add default values if require.
|
||||
"""
|
||||
|
||||
if section not in self._settings:
|
||||
self._settings[section] = {}
|
||||
self._settings[section].update(settings)
|
||||
return settings
|
||||
# use default values for missing settings
|
||||
for name, value in default.items():
|
||||
if name not in local:
|
||||
local[name] = value
|
||||
elif isinstance(value, dict):
|
||||
local[name] = _copySettings(local[name], default[name])
|
||||
return local
|
||||
|
||||
settings = _copySettings(settings, default_settings)
|
||||
|
||||
self._settings[section] = settings
|
||||
return copy.deepcopy(settings)
|
||||
|
||||
def saveSectionSettings(self, section, settings):
|
||||
"""
|
||||
@@ -181,17 +289,22 @@ class LocalConfig:
|
||||
|
||||
if section not in self._settings:
|
||||
self._settings[section] = {}
|
||||
self._settings[section].update(settings)
|
||||
self._writeConfig()
|
||||
|
||||
if self._settings[section] != settings:
|
||||
self._settings[section].update(settings)
|
||||
log.info("Section %s has changed. Saving configuration", section)
|
||||
self._writeConfig()
|
||||
else:
|
||||
log.debug("Section %s has not changed. Skip saving configuration", section)
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
def instance(config_file=None):
|
||||
"""
|
||||
Singleton to return only on instance of LocalConfig.
|
||||
|
||||
:returns: instance of LocalConfig
|
||||
"""
|
||||
|
||||
if not hasattr(LocalConfig, "_instance"):
|
||||
LocalConfig._instance = LocalConfig()
|
||||
if not hasattr(LocalConfig, "_instance") or LocalConfig._instance is None:
|
||||
LocalConfig._instance = LocalConfig(config_file=config_file)
|
||||
return LocalConfig._instance
|
||||
|
||||
@@ -33,12 +33,21 @@ class LocalServerConfig:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
appname = "GNS3"
|
||||
|
||||
self._config = configparser.RawConfigParser()
|
||||
if sys.platform.startswith("win"):
|
||||
filename = "gns3_server.ini"
|
||||
else:
|
||||
filename = "gns3_server.conf"
|
||||
self._config_file = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), filename)
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
appdata = os.path.expandvars("%APPDATA%")
|
||||
self._config_file = os.path.join(appdata, appname, filename)
|
||||
else:
|
||||
home = os.path.expanduser("~")
|
||||
self._config_file = os.path.join(home, ".config", appname, filename)
|
||||
|
||||
try:
|
||||
# create the config file if it doesn't exist
|
||||
open(self._config_file, "a").close()
|
||||
@@ -52,7 +61,7 @@ class LocalServerConfig:
|
||||
"""
|
||||
|
||||
try:
|
||||
self._config.read(self._config_file)
|
||||
self._config.read(self._config_file, encoding="utf-8")
|
||||
except (OSError, configparser.Error) as e:
|
||||
log.error("Could not read the local server configuration {}: {}".format(self._config_file, e))
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
class ColouredFormatter(logging.Formatter):
|
||||
@@ -81,7 +82,7 @@ class ColouredStreamHandler(logging.StreamHandler):
|
||||
self.handleError(record)
|
||||
|
||||
|
||||
def init_logger(level, quiet=False):
|
||||
def init_logger(level, logfile, quiet=False):
|
||||
if sys.platform.startswith("win"):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
stream_handler.formatter = ColouredFormatter("{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{")
|
||||
@@ -89,5 +90,20 @@ def init_logger(level, quiet=False):
|
||||
stream_handler = ColouredStreamHandler(sys.stdout)
|
||||
stream_handler.formatter = ColouredFormatter("{asctime} {levelname} {filename}:{lineno}#RESET# {message}", "%Y-%m-%d %H:%M:%S", "{")
|
||||
logging.basicConfig(level=level, handlers=[stream_handler])
|
||||
logging.getLogger().addHandler(stream_handler)
|
||||
log = logging.getLogger()
|
||||
log.addHandler(stream_handler)
|
||||
|
||||
try:
|
||||
try:
|
||||
os.makedirs(os.path.dirname(logfile))
|
||||
except FileExistsError:
|
||||
pass
|
||||
handler = logging.FileHandler(logfile, "w")
|
||||
handler.formatter = logging.Formatter("{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{")
|
||||
log.addHandler(handler)
|
||||
except OSError as e:
|
||||
log.warn("could not log to {}: {}".format(logfile, e))
|
||||
|
||||
log.info('Log level: {}'.format(logging.getLevelName(level)))
|
||||
|
||||
return logging.getLogger()
|
||||
|
||||
123
gns3/main.py
123
gns3/main.py
@@ -16,6 +16,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Try to install updates & restart application if an update is installed
|
||||
try:
|
||||
import gns3.update_manager
|
||||
if gns3.update_manager.UpdateManager().installDownloadedUpdates():
|
||||
print("Update installed restart the application")
|
||||
python = sys.executable
|
||||
os.execl(python, python, * sys.argv)
|
||||
except Exception as e:
|
||||
print("Fail update installation: {}".format(str(e)))
|
||||
|
||||
|
||||
# WARNING
|
||||
# Due to buggy user machines we choose to put this as the first loading modules
|
||||
@@ -27,28 +40,26 @@ from gns3.utils.get_resource import get_resource
|
||||
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
import os
|
||||
import traceback
|
||||
import time
|
||||
import locale
|
||||
import argparse
|
||||
import signal
|
||||
|
||||
try:
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets, DEFAULT_BINDING
|
||||
except ImportError:
|
||||
raise SystemExit("Can't import Qt modules: Qt and/or PyQt is probably not installed correctly...")
|
||||
from gns3.main_window import MainWindow
|
||||
|
||||
from gns3.logger import init_logger
|
||||
from gns3.crash_report import CrashReport
|
||||
|
||||
from gns3.local_config import LocalConfig
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
try:
|
||||
from gns3.qt import QtCore, QtGui, DEFAULT_BINDING
|
||||
except ImportError:
|
||||
raise RuntimeError("Can't import Qt modules: Qt and/or PyQt is probably not installed correctly...")
|
||||
|
||||
from gns3.main_window import MainWindow
|
||||
from gns3.version import __version__
|
||||
|
||||
|
||||
@@ -96,15 +107,44 @@ def main():
|
||||
Entry point for GNS3 GUI.
|
||||
"""
|
||||
|
||||
# Sometimes (for example at first launch) the OSX app service launcher add
|
||||
# an extra argument starting with -psn_. We filter it
|
||||
if sys.platform.startswith("darwin"):
|
||||
sys.argv = [a for a in sys.argv if not a.startswith("-psn_")]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?")
|
||||
parser.add_argument("--version", help="show the version", action="version", version=__version__)
|
||||
parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False)
|
||||
parser.add_argument("--config", help="Configuration file")
|
||||
options = parser.parse_args()
|
||||
exception_file_path = "exceptions.log"
|
||||
|
||||
if options.project and hasattr(sys, "frozen"):
|
||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||
if options.config:
|
||||
LocalConfig.instance(config_file=options.config)
|
||||
else:
|
||||
LocalConfig.instance()
|
||||
|
||||
if hasattr(sys, "frozen"):
|
||||
# We add to the path where the OS search executable our binary location starting by GNS3
|
||||
# packaged binary
|
||||
frozen_dir = os.path.dirname(os.path.abspath(sys.executable))
|
||||
if sys.platform.startswith("darwin"):
|
||||
frozen_dirs = [
|
||||
frozen_dir,
|
||||
os.path.normpath(os.path.join(frozen_dir, '..', 'Resources'))
|
||||
]
|
||||
elif sys.platform.startswith("win"):
|
||||
frozen_dirs = [
|
||||
frozen_dir,
|
||||
os.path.normpath(os.path.join(frozen_dir, 'dynamips')),
|
||||
os.path.normpath(os.path.join(frozen_dir, 'vpcs'))
|
||||
]
|
||||
|
||||
os.environ["PATH"] = os.pathsep.join(frozen_dirs) + os.pathsep + os.environ.get("PATH", "")
|
||||
|
||||
if options.project:
|
||||
os.chdir(frozen_dir)
|
||||
|
||||
def exceptionHook(exception, value, tb):
|
||||
|
||||
@@ -141,24 +181,22 @@ def main():
|
||||
print("GNS3 GUI version {}".format(__version__))
|
||||
print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
|
||||
|
||||
# we only support Python 2 version >= 2.7 and Python 3 version >= 3.3
|
||||
if sys.version_info < (2, 7):
|
||||
raise RuntimeError("Python 2.7 or higher is required")
|
||||
elif sys.version_info[0] == 3 and sys.version_info < (3, 3):
|
||||
raise RuntimeError("Python 3.3 or higher is required")
|
||||
# we only support Python 3 version >= 3.4
|
||||
if sys.version_info < (3, 4):
|
||||
raise SystemExit("Python 3.4 or higher is required")
|
||||
|
||||
def version(version_string):
|
||||
return [int(i) for i in version_string.split('.')]
|
||||
|
||||
if version(QtCore.QT_VERSION_STR) < version("4.6"):
|
||||
raise RuntimeError("Requirement is Qt version 4.6 or higher, got version {}".format(QtCore.QT_VERSION_STR))
|
||||
raise SystemExit("Requirement is Qt version 4.6 or higher, got version {}".format(QtCore.QT_VERSION_STR))
|
||||
|
||||
# 4.8.3 because of QSettings (http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html)
|
||||
if DEFAULT_BINDING == "PyQt" and version(QtCore.BINDING_VERSION_STR) < version("4.8.3"):
|
||||
raise RuntimeError("Requirement is PyQt version 4.8.3 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
|
||||
if DEFAULT_BINDING == "PyQt4" and version(QtCore.BINDING_VERSION_STR) < version("4.8.3"):
|
||||
raise SystemExit("Requirement is PyQt version 4.8.3 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
|
||||
|
||||
if DEFAULT_BINDING == "PySide" and version(QtCore.BINDING_VERSION_STR) < version("1.0"):
|
||||
raise RuntimeError("Requirement is PySide version 1.0 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
|
||||
if DEFAULT_BINDING == "PyQt5" and version(QtCore.BINDING_VERSION_STR) < version("5.0.0"):
|
||||
raise SystemExit("Requirement is PyQt5 version 5.0.0 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
|
||||
|
||||
# check for the correct locale
|
||||
# (UNIX/Linux only)
|
||||
@@ -180,7 +218,7 @@ def main():
|
||||
import win32con
|
||||
import win32gui
|
||||
except ImportError:
|
||||
raise RuntimeError("Python for Windows extensions must be installed.")
|
||||
raise SystemExit("Python for Windows extensions must be installed.")
|
||||
|
||||
if not options.debug:
|
||||
try:
|
||||
@@ -190,7 +228,7 @@ def main():
|
||||
except win32console.error as e:
|
||||
print("warning: could not allocate console: {}".format(e))
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# this info is necessary for QSettings
|
||||
app.setOrganizationName("GNS3")
|
||||
@@ -198,38 +236,39 @@ def main():
|
||||
app.setApplicationName("GNS3")
|
||||
app.setApplicationVersion(__version__)
|
||||
|
||||
formatter = logging.Formatter("[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s",
|
||||
datefmt="%y%m%d %H:%M:%S")
|
||||
# save client logging info to a file
|
||||
logfile = os.path.join(LocalConfig.configDirectory(), "gns3_gui.log")
|
||||
|
||||
# on debug enable logging to stdout
|
||||
if options.debug:
|
||||
root_logger = init_logger(logging.DEBUG)
|
||||
root_logger = init_logger(logging.DEBUG, logfile)
|
||||
else:
|
||||
root_logger = init_logger(logging.INFO)
|
||||
|
||||
# save client logging info to a file
|
||||
logfile = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), "gns3_gui.log")
|
||||
try:
|
||||
try:
|
||||
os.makedirs(os.path.dirname(QtCore.QSettings().fileName()))
|
||||
except FileExistsError:
|
||||
pass
|
||||
handler = logging.FileHandler(logfile, "w")
|
||||
root_logger.addHandler(handler)
|
||||
except OSError as e:
|
||||
log.warn("could not log to {}: {}".format(logfile, e))
|
||||
|
||||
log.info('Log level: {}'.format(logging.getLevelName(log.getEffectiveLevel())))
|
||||
root_logger = init_logger(logging.INFO, logfile)
|
||||
|
||||
# update the exception file path to have it in the same directory as the settings file.
|
||||
exception_file_path = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), exception_file_path)
|
||||
exception_file_path = os.path.join(LocalConfig.configDirectory(), exception_file_path)
|
||||
|
||||
mainwindow = MainWindow(options.project)
|
||||
|
||||
# Manage Ctrl + C or kill command
|
||||
def sigint_handler(*args):
|
||||
log.info("Signal received exiting the application")
|
||||
mainwindow.setSoftExit(False)
|
||||
app.closeAllWindows()
|
||||
signal.signal(signal.SIGINT, sigint_handler)
|
||||
signal.signal(signal.SIGTERM, sigint_handler)
|
||||
|
||||
mainwindow.show()
|
||||
exit_code = app.exec_()
|
||||
delattr(MainWindow, "_instance")
|
||||
app.deleteLater()
|
||||
|
||||
# We force a full garbage collect before exit
|
||||
# for unknow reason otherwise Qt Segfault on OSX in some
|
||||
# conditions
|
||||
import gc
|
||||
gc.collect()
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,5 +21,6 @@ from gns3.modules.iou import IOU
|
||||
from gns3.modules.vpcs import VPCS
|
||||
from gns3.modules.virtualbox import VirtualBox
|
||||
from gns3.modules.qemu import Qemu
|
||||
from gns3.modules.vmware import VMware
|
||||
|
||||
MODULES = [VPCS, Dynamips, IOU, VirtualBox, Qemu, Builtin]
|
||||
MODULES = [VPCS, Dynamips, IOU, Qemu, VirtualBox, VMware, Builtin]
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Built-in module implementation.
|
||||
"""
|
||||
|
||||
from gns3.qt import QtGui
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.servers import Servers
|
||||
from ..module import Module
|
||||
from ..module_error import ModuleError
|
||||
@@ -38,10 +38,13 @@ class Builtin(Module):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Module.__init__(self)
|
||||
super().__init__()
|
||||
|
||||
self._nodes = []
|
||||
|
||||
def configChangedSlot(self):
|
||||
pass
|
||||
|
||||
def addNode(self, node):
|
||||
"""
|
||||
Adds a node to this module.
|
||||
@@ -93,27 +96,31 @@ class Builtin(Module):
|
||||
servers = Servers.instance()
|
||||
local_server = servers.localServer()
|
||||
remote_servers = servers.remoteServers()
|
||||
gns3_vm = Servers.instance().vmServer()
|
||||
|
||||
if not all(using_local_server) and len(remote_servers):
|
||||
if not all(using_local_server) and (gns3_vm or len(remote_servers)):
|
||||
# a module is not using a local server
|
||||
|
||||
if True not in using_local_server and len(remote_servers) == 1:
|
||||
# no module is using a local server and there is only one
|
||||
# remote server available, so no need to ask the user.
|
||||
return next(iter(servers))
|
||||
|
||||
server_list = []
|
||||
server_list.append("Local server ({}:{})".format(local_server.host, local_server.port))
|
||||
for remote_server in remote_servers:
|
||||
server_list.append("{}".format(remote_server))
|
||||
server_list = ["Local server ({})".format(local_server.url())]
|
||||
if gns3_vm:
|
||||
server_list.append("GNS3 VM ({})".format(gns3_vm.url()))
|
||||
if len(remote_servers):
|
||||
if True not in using_local_server and len(remote_servers) == 1:
|
||||
# no module is using a local server and there is only one
|
||||
# remote server available, so no need to ask the user.
|
||||
return next(iter(servers))
|
||||
for remote_server in remote_servers:
|
||||
server_list.append("{}".format(remote_server))
|
||||
|
||||
# TODO: move this to graphics_view
|
||||
from gns3.main_window import MainWindow
|
||||
mainwindow = MainWindow.instance()
|
||||
(selection, ok) = QtGui.QInputDialog.getItem(mainwindow, "Server", "Please choose a server", server_list, 0, False)
|
||||
(selection, ok) = QtWidgets.QInputDialog.getItem(mainwindow, "Server", "Please choose a server", server_list, 0, False)
|
||||
if ok:
|
||||
if selection.startswith("Local server"):
|
||||
return local_server
|
||||
elif selection.startswith("GNS3 VM"):
|
||||
return gns3_vm
|
||||
else:
|
||||
return remote_servers[selection]
|
||||
else:
|
||||
@@ -156,15 +163,15 @@ class Builtin(Module):
|
||||
available_interfaces.append(interface["name"])
|
||||
|
||||
if available_interfaces:
|
||||
selection, ok = QtGui.QInputDialog.getItem(mainwindow,
|
||||
"Cloud interfaces", "Interface {} could not be found\nPlease select an alternative from your existing interfaces:".format(missing_interface),
|
||||
available_interfaces, 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(mainwindow,
|
||||
"Cloud interfaces", "Interface {} could not be found\nPlease select an alternative from your existing interfaces:".format(missing_interface),
|
||||
available_interfaces, 0, False)
|
||||
if ok:
|
||||
return selection
|
||||
QtGui.QMessageBox.warning(mainwindow, "Cloud interface", "No alternative interface chosen to replace {} on this host, this may lead to issues".format(missing_interface))
|
||||
QtWidgets.QMessageBox.warning(mainwindow, "Cloud interface", "No alternative interface chosen to replace {} on this host, this may lead to issues".format(missing_interface))
|
||||
return None
|
||||
else:
|
||||
QtGui.QMessageBox.critical(mainwindow, "Cloud interface", "Could not find interface {} on this host".format(missing_interface))
|
||||
QtWidgets.QMessageBox.critical(mainwindow, "Cloud interface", "Could not find interface {} on this host".format(missing_interface))
|
||||
return missing_interface
|
||||
|
||||
@staticmethod
|
||||
@@ -201,8 +208,7 @@ class Builtin(Module):
|
||||
{"class": node_class.__name__,
|
||||
"name": node_class.symbolName(),
|
||||
"categories": node_class.categories(),
|
||||
"default_symbol": node_class.defaultSymbol(),
|
||||
"hover_symbol": node_class.hoverSymbol()}
|
||||
"symbol": node_class.defaultSymbol()}
|
||||
)
|
||||
return nodes
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ class Cloud(Node):
|
||||
_name_instance_count = 1
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
Node.__init__(self, module, server, project)
|
||||
|
||||
super().__init__(module, server, project)
|
||||
|
||||
log.info("cloud is being created")
|
||||
# create an unique id and name
|
||||
@@ -58,8 +59,6 @@ class Cloud(Node):
|
||||
|
||||
name = "Cloud {}".format(self._name_id)
|
||||
self.setStatus(Node.started) # this is an always-on node
|
||||
self._defaults = {}
|
||||
self._ports = []
|
||||
self._initial_settings = None
|
||||
self._settings = {"name": name,
|
||||
"interfaces": {},
|
||||
@@ -347,11 +346,11 @@ This is a pseudo-device for external connections
|
||||
:param node_info: representation of the node (dictionary)
|
||||
"""
|
||||
|
||||
self.node_info = node_info
|
||||
settings = node_info["properties"]
|
||||
name = settings.pop("name")
|
||||
self.updated_signal.connect(self._updatePortSettings)
|
||||
log.info("cloud {} is loading".format(name))
|
||||
self._node_info = node_info
|
||||
self.setup(name, settings)
|
||||
|
||||
def _updatePortSettings(self):
|
||||
@@ -361,8 +360,8 @@ This is a pseudo-device for external connections
|
||||
|
||||
self.updated_signal.disconnect(self._updatePortSettings)
|
||||
# update the port with the correct IDs
|
||||
if "ports" in self.node_info:
|
||||
ports = self.node_info["ports"]
|
||||
if "ports" in self._node_info:
|
||||
ports = self._node_info["ports"]
|
||||
for topology_port in ports:
|
||||
for port in self._ports:
|
||||
if topology_port["name"] == port.name():
|
||||
@@ -417,7 +416,7 @@ This is a pseudo-device for external connections
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -433,17 +432,7 @@ This is a pseudo-device for external connections
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/cloud.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when the cloud is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/cloud.selected.svg"
|
||||
return ":/symbols/cloud.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -36,7 +36,7 @@ class Host(Cloud):
|
||||
_name_instance_count = 1
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
Cloud.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
|
||||
log.info("host is being created")
|
||||
# create an unique id and name
|
||||
@@ -87,17 +87,7 @@ class Host(Cloud):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/computer.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when the host is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/computer.selected.svg"
|
||||
return ":/symbols/computer.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -20,11 +20,11 @@ Configuration page for clouds.
|
||||
"""
|
||||
|
||||
import re
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.cloud_configuration_page_ui import Ui_cloudConfigPageWidget
|
||||
|
||||
|
||||
class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
class CloudConfigurationPage(QtWidgets.QWidget, Ui_cloudConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for clouds.
|
||||
@@ -32,7 +32,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self._nios = []
|
||||
|
||||
@@ -128,7 +128,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiGenericEthernetListWidget.takeItem(self.uiGenericEthernetListWidget.currentRow())
|
||||
@@ -177,7 +177,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiLinuxEthernetListWidget.takeItem(self.uiLinuxEthernetListWidget.currentRow())
|
||||
@@ -231,7 +231,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIONATListWidget.takeItem(self.uiNIONATListWidget.currentRow())
|
||||
@@ -293,7 +293,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIOUDPListWidget.takeItem(self.uiNIOUDPListWidget.currentRow())
|
||||
@@ -347,7 +347,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIOTAPListWidget.takeItem(self.uiNIOTAPListWidget.currentRow())
|
||||
@@ -404,7 +404,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIOUNIXListWidget.takeItem(self.uiNIOUNIXListWidget.currentRow())
|
||||
@@ -460,7 +460,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIOVDEListWidget.takeItem(self.uiNIOVDEListWidget.currentRow())
|
||||
@@ -514,7 +514,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.name() == nio and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to NIO {}, please remove it first".format(nio))
|
||||
return
|
||||
self._nios.remove(nio)
|
||||
self.uiNIONullListWidget.takeItem(self.uiNIONullListWidget.currentRow())
|
||||
@@ -545,7 +545,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
self.uiGenericEthernetComboBox.addItem(interface["name"])
|
||||
self.uiGenericEthernetComboBox.setItemData(index, interface["id"], QtCore.Qt.ToolTipRole)
|
||||
index += 1
|
||||
self.uiGenericEthernetComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
self.uiGenericEthernetComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
|
||||
|
||||
# load all network interfaces
|
||||
self.uiLinuxEthernetComboBox.clear()
|
||||
@@ -555,7 +555,7 @@ class CloudConfigurationPage(QtGui.QWidget, Ui_cloudConfigPageWidget):
|
||||
self.uiLinuxEthernetComboBox.addItem(interface["name"])
|
||||
self.uiLinuxEthernetComboBox.setItemData(index, interface["id"], QtCore.Qt.ToolTipRole)
|
||||
index += 1
|
||||
self.uiLinuxEthernetComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
self.uiLinuxEthernetComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
|
||||
|
||||
# populate the NIO lists
|
||||
self.nios = []
|
||||
|
||||
@@ -1,418 +1,404 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/builtin/ui/cloud_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/builtin/ui/cloud_configuration_page.ui'
|
||||
#
|
||||
# Created: Tue May 5 21:08:19 2015
|
||||
# by: PyQt4 UI code generator 4.10.4
|
||||
# Created: Wed Jul 15 12:22:31 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_cloudConfigPageWidget(object):
|
||||
def setupUi(self, cloudConfigPageWidget):
|
||||
cloudConfigPageWidget.setObjectName(_fromUtf8("cloudConfigPageWidget"))
|
||||
cloudConfigPageWidget.setObjectName("cloudConfigPageWidget")
|
||||
cloudConfigPageWidget.resize(653, 478)
|
||||
self.vboxlayout = QtGui.QVBoxLayout(cloudConfigPageWidget)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiNIOsTabWidget = QtGui.QTabWidget(cloudConfigPageWidget)
|
||||
self.uiNIOsTabWidget.setObjectName(_fromUtf8("uiNIOsTabWidget"))
|
||||
self.NIOEthernetTab = QtGui.QWidget()
|
||||
self.NIOEthernetTab.setObjectName(_fromUtf8("NIOEthernetTab"))
|
||||
self.vboxlayout1 = QtGui.QVBoxLayout(self.NIOEthernetTab)
|
||||
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
|
||||
self.uiGenericEthernetGroupBox = QtGui.QGroupBox(self.NIOEthernetTab)
|
||||
self.uiGenericEthernetGroupBox.setObjectName(_fromUtf8("uiGenericEthernetGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiGenericEthernetGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiGenericEthernetComboBox = QtGui.QComboBox(self.uiGenericEthernetGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(cloudConfigPageWidget)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiNIOsTabWidget = QtWidgets.QTabWidget(cloudConfigPageWidget)
|
||||
self.uiNIOsTabWidget.setObjectName("uiNIOsTabWidget")
|
||||
self.NIOEthernetTab = QtWidgets.QWidget()
|
||||
self.NIOEthernetTab.setObjectName("NIOEthernetTab")
|
||||
self.vboxlayout1 = QtWidgets.QVBoxLayout(self.NIOEthernetTab)
|
||||
self.vboxlayout1.setObjectName("vboxlayout1")
|
||||
self.uiGenericEthernetGroupBox = QtWidgets.QGroupBox(self.NIOEthernetTab)
|
||||
self.uiGenericEthernetGroupBox.setObjectName("uiGenericEthernetGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiGenericEthernetGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiGenericEthernetComboBox = QtWidgets.QComboBox(self.uiGenericEthernetGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiGenericEthernetComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiGenericEthernetComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiGenericEthernetComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
self.uiGenericEthernetComboBox.setObjectName(_fromUtf8("uiGenericEthernetComboBox"))
|
||||
self.uiGenericEthernetComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
|
||||
self.uiGenericEthernetComboBox.setObjectName("uiGenericEthernetComboBox")
|
||||
self.gridlayout.addWidget(self.uiGenericEthernetComboBox, 0, 0, 1, 3)
|
||||
self.uiGenericEthernetLineEdit = QtGui.QLineEdit(self.uiGenericEthernetGroupBox)
|
||||
self.uiGenericEthernetLineEdit.setObjectName(_fromUtf8("uiGenericEthernetLineEdit"))
|
||||
self.uiGenericEthernetLineEdit = QtWidgets.QLineEdit(self.uiGenericEthernetGroupBox)
|
||||
self.uiGenericEthernetLineEdit.setObjectName("uiGenericEthernetLineEdit")
|
||||
self.gridlayout.addWidget(self.uiGenericEthernetLineEdit, 1, 0, 1, 1)
|
||||
self.uiAddGenericEthernetPushButton = QtGui.QPushButton(self.uiGenericEthernetGroupBox)
|
||||
self.uiAddGenericEthernetPushButton.setObjectName(_fromUtf8("uiAddGenericEthernetPushButton"))
|
||||
self.uiAddGenericEthernetPushButton = QtWidgets.QPushButton(self.uiGenericEthernetGroupBox)
|
||||
self.uiAddGenericEthernetPushButton.setObjectName("uiAddGenericEthernetPushButton")
|
||||
self.gridlayout.addWidget(self.uiAddGenericEthernetPushButton, 1, 1, 1, 1)
|
||||
self.uiDeleteGenericEthernetPushButton = QtGui.QPushButton(self.uiGenericEthernetGroupBox)
|
||||
self.uiDeleteGenericEthernetPushButton = QtWidgets.QPushButton(self.uiGenericEthernetGroupBox)
|
||||
self.uiDeleteGenericEthernetPushButton.setEnabled(False)
|
||||
self.uiDeleteGenericEthernetPushButton.setObjectName(_fromUtf8("uiDeleteGenericEthernetPushButton"))
|
||||
self.uiDeleteGenericEthernetPushButton.setObjectName("uiDeleteGenericEthernetPushButton")
|
||||
self.gridlayout.addWidget(self.uiDeleteGenericEthernetPushButton, 1, 2, 1, 1)
|
||||
self.uiGenericEthernetListWidget = QtGui.QListWidget(self.uiGenericEthernetGroupBox)
|
||||
self.uiGenericEthernetListWidget.setObjectName(_fromUtf8("uiGenericEthernetListWidget"))
|
||||
self.uiGenericEthernetListWidget = QtWidgets.QListWidget(self.uiGenericEthernetGroupBox)
|
||||
self.uiGenericEthernetListWidget.setObjectName("uiGenericEthernetListWidget")
|
||||
self.gridlayout.addWidget(self.uiGenericEthernetListWidget, 2, 0, 1, 3)
|
||||
self.vboxlayout1.addWidget(self.uiGenericEthernetGroupBox)
|
||||
self.uiLinuxEthernetGroupBox = QtGui.QGroupBox(self.NIOEthernetTab)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
|
||||
self.uiLinuxEthernetGroupBox = QtWidgets.QGroupBox(self.NIOEthernetTab)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiLinuxEthernetGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiLinuxEthernetGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiLinuxEthernetGroupBox.setObjectName(_fromUtf8("uiLinuxEthernetGroupBox"))
|
||||
self.gridlayout1 = QtGui.QGridLayout(self.uiLinuxEthernetGroupBox)
|
||||
self.gridlayout1.setObjectName(_fromUtf8("gridlayout1"))
|
||||
self.uiLinuxEthernetComboBox = QtGui.QComboBox(self.uiLinuxEthernetGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiLinuxEthernetGroupBox.setObjectName("uiLinuxEthernetGroupBox")
|
||||
self.gridlayout1 = QtWidgets.QGridLayout(self.uiLinuxEthernetGroupBox)
|
||||
self.gridlayout1.setObjectName("gridlayout1")
|
||||
self.uiLinuxEthernetComboBox = QtWidgets.QComboBox(self.uiLinuxEthernetGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiLinuxEthernetComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiLinuxEthernetComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiLinuxEthernetComboBox.setObjectName(_fromUtf8("uiLinuxEthernetComboBox"))
|
||||
self.uiLinuxEthernetComboBox.setObjectName("uiLinuxEthernetComboBox")
|
||||
self.gridlayout1.addWidget(self.uiLinuxEthernetComboBox, 0, 0, 1, 3)
|
||||
self.uiLinuxEthernetLineEdit = QtGui.QLineEdit(self.uiLinuxEthernetGroupBox)
|
||||
self.uiLinuxEthernetLineEdit.setObjectName(_fromUtf8("uiLinuxEthernetLineEdit"))
|
||||
self.uiLinuxEthernetLineEdit = QtWidgets.QLineEdit(self.uiLinuxEthernetGroupBox)
|
||||
self.uiLinuxEthernetLineEdit.setObjectName("uiLinuxEthernetLineEdit")
|
||||
self.gridlayout1.addWidget(self.uiLinuxEthernetLineEdit, 1, 0, 1, 1)
|
||||
self.uiAddLinuxEthernetPushButton = QtGui.QPushButton(self.uiLinuxEthernetGroupBox)
|
||||
self.uiAddLinuxEthernetPushButton.setObjectName(_fromUtf8("uiAddLinuxEthernetPushButton"))
|
||||
self.uiAddLinuxEthernetPushButton = QtWidgets.QPushButton(self.uiLinuxEthernetGroupBox)
|
||||
self.uiAddLinuxEthernetPushButton.setObjectName("uiAddLinuxEthernetPushButton")
|
||||
self.gridlayout1.addWidget(self.uiAddLinuxEthernetPushButton, 1, 1, 1, 1)
|
||||
self.uiDeleteLinuxEthernetPushButton = QtGui.QPushButton(self.uiLinuxEthernetGroupBox)
|
||||
self.uiDeleteLinuxEthernetPushButton = QtWidgets.QPushButton(self.uiLinuxEthernetGroupBox)
|
||||
self.uiDeleteLinuxEthernetPushButton.setEnabled(False)
|
||||
self.uiDeleteLinuxEthernetPushButton.setObjectName(_fromUtf8("uiDeleteLinuxEthernetPushButton"))
|
||||
self.uiDeleteLinuxEthernetPushButton.setObjectName("uiDeleteLinuxEthernetPushButton")
|
||||
self.gridlayout1.addWidget(self.uiDeleteLinuxEthernetPushButton, 1, 2, 1, 1)
|
||||
self.uiLinuxEthernetListWidget = QtGui.QListWidget(self.uiLinuxEthernetGroupBox)
|
||||
self.uiLinuxEthernetListWidget.setObjectName(_fromUtf8("uiLinuxEthernetListWidget"))
|
||||
self.uiLinuxEthernetListWidget = QtWidgets.QListWidget(self.uiLinuxEthernetGroupBox)
|
||||
self.uiLinuxEthernetListWidget.setObjectName("uiLinuxEthernetListWidget")
|
||||
self.gridlayout1.addWidget(self.uiLinuxEthernetListWidget, 2, 0, 1, 3)
|
||||
self.vboxlayout1.addWidget(self.uiLinuxEthernetGroupBox)
|
||||
spacerItem = QtGui.QSpacerItem(21, 16, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
spacerItem = QtWidgets.QSpacerItem(21, 16, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||
self.vboxlayout1.addItem(spacerItem)
|
||||
self.uiNIOsTabWidget.addTab(self.NIOEthernetTab, _fromUtf8(""))
|
||||
self.NIONATTab = QtGui.QWidget()
|
||||
self.NIONATTab.setObjectName(_fromUtf8("NIONATTab"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.NIONATTab)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiNIONATSettingsGroupBox = QtGui.QGroupBox(self.NIONATTab)
|
||||
self.uiNIONATSettingsGroupBox.setObjectName(_fromUtf8("uiNIONATSettingsGroupBox"))
|
||||
self._2 = QtGui.QGridLayout(self.uiNIONATSettingsGroupBox)
|
||||
self._2.setObjectName(_fromUtf8("_2"))
|
||||
self.uiNIONATIdentifierLabel = QtGui.QLabel(self.uiNIONATSettingsGroupBox)
|
||||
self.uiNIONATIdentifierLabel.setObjectName(_fromUtf8("uiNIONATIdentifierLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIOEthernetTab, "")
|
||||
self.NIONATTab = QtWidgets.QWidget()
|
||||
self.NIONATTab.setObjectName("NIONATTab")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.NIONATTab)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiNIONATSettingsGroupBox = QtWidgets.QGroupBox(self.NIONATTab)
|
||||
self.uiNIONATSettingsGroupBox.setObjectName("uiNIONATSettingsGroupBox")
|
||||
self._2 = QtWidgets.QGridLayout(self.uiNIONATSettingsGroupBox)
|
||||
self._2.setObjectName("_2")
|
||||
self.uiNIONATIdentifierLabel = QtWidgets.QLabel(self.uiNIONATSettingsGroupBox)
|
||||
self.uiNIONATIdentifierLabel.setObjectName("uiNIONATIdentifierLabel")
|
||||
self._2.addWidget(self.uiNIONATIdentifierLabel, 0, 0, 1, 1)
|
||||
self.uiNIONATIdentiferLineEdit = QtGui.QLineEdit(self.uiNIONATSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiNIONATIdentiferLineEdit = QtWidgets.QLineEdit(self.uiNIONATSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIONATIdentiferLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIONATIdentiferLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiNIONATIdentiferLineEdit.setObjectName(_fromUtf8("uiNIONATIdentiferLineEdit"))
|
||||
self.uiNIONATIdentiferLineEdit.setObjectName("uiNIONATIdentiferLineEdit")
|
||||
self._2.addWidget(self.uiNIONATIdentiferLineEdit, 1, 0, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiNIONATSettingsGroupBox, 0, 0, 1, 2)
|
||||
self.uiNIONATListGroupBox = QtGui.QGroupBox(self.NIONATTab)
|
||||
self.uiNIONATListGroupBox.setObjectName(_fromUtf8("uiNIONATListGroupBox"))
|
||||
self._3 = QtGui.QVBoxLayout(self.uiNIONATListGroupBox)
|
||||
self._3.setObjectName(_fromUtf8("_3"))
|
||||
self.uiNIONATListWidget = QtGui.QListWidget(self.uiNIONATListGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.uiNIONATListGroupBox = QtWidgets.QGroupBox(self.NIONATTab)
|
||||
self.uiNIONATListGroupBox.setObjectName("uiNIONATListGroupBox")
|
||||
self._3 = QtWidgets.QVBoxLayout(self.uiNIONATListGroupBox)
|
||||
self._3.setObjectName("_3")
|
||||
self.uiNIONATListWidget = QtWidgets.QListWidget(self.uiNIONATListGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIONATListWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIONATListWidget.setSizePolicy(sizePolicy)
|
||||
self.uiNIONATListWidget.setObjectName(_fromUtf8("uiNIONATListWidget"))
|
||||
self.uiNIONATListWidget.setObjectName("uiNIONATListWidget")
|
||||
self._3.addWidget(self.uiNIONATListWidget)
|
||||
self.gridLayout_2.addWidget(self.uiNIONATListGroupBox, 0, 2, 3, 1)
|
||||
self.uiAddNIONATPushButton = QtGui.QPushButton(self.NIONATTab)
|
||||
self.uiAddNIONATPushButton.setObjectName(_fromUtf8("uiAddNIONATPushButton"))
|
||||
self.uiAddNIONATPushButton = QtWidgets.QPushButton(self.NIONATTab)
|
||||
self.uiAddNIONATPushButton.setObjectName("uiAddNIONATPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiAddNIONATPushButton, 1, 0, 1, 1)
|
||||
self.uiDeleteNIONATPushButton = QtGui.QPushButton(self.NIONATTab)
|
||||
self.uiDeleteNIONATPushButton = QtWidgets.QPushButton(self.NIONATTab)
|
||||
self.uiDeleteNIONATPushButton.setEnabled(False)
|
||||
self.uiDeleteNIONATPushButton.setObjectName(_fromUtf8("uiDeleteNIONATPushButton"))
|
||||
self.uiDeleteNIONATPushButton.setObjectName("uiDeleteNIONATPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiDeleteNIONATPushButton, 1, 1, 1, 1)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 294, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 294, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem1, 2, 0, 2, 1)
|
||||
spacerItem2 = QtGui.QSpacerItem(20, 194, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 194, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem2, 3, 2, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.NIONATTab, _fromUtf8(""))
|
||||
self.NIOUDPTab = QtGui.QWidget()
|
||||
self.NIOUDPTab.setObjectName(_fromUtf8("NIOUDPTab"))
|
||||
self.gridlayout2 = QtGui.QGridLayout(self.NIOUDPTab)
|
||||
self.gridlayout2.setObjectName(_fromUtf8("gridlayout2"))
|
||||
self.uiNIOUDPSettingsGroupBox = QtGui.QGroupBox(self.NIOUDPTab)
|
||||
self.uiNIOUDPSettingsGroupBox.setObjectName(_fromUtf8("uiNIOUDPSettingsGroupBox"))
|
||||
self.gridlayout3 = QtGui.QGridLayout(self.uiNIOUDPSettingsGroupBox)
|
||||
self.gridlayout3.setObjectName(_fromUtf8("gridlayout3"))
|
||||
self.uiLocalPortLabel = QtGui.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiLocalPortLabel.setObjectName(_fromUtf8("uiLocalPortLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIONATTab, "")
|
||||
self.NIOUDPTab = QtWidgets.QWidget()
|
||||
self.NIOUDPTab.setObjectName("NIOUDPTab")
|
||||
self.gridlayout2 = QtWidgets.QGridLayout(self.NIOUDPTab)
|
||||
self.gridlayout2.setObjectName("gridlayout2")
|
||||
self.uiNIOUDPSettingsGroupBox = QtWidgets.QGroupBox(self.NIOUDPTab)
|
||||
self.uiNIOUDPSettingsGroupBox.setObjectName("uiNIOUDPSettingsGroupBox")
|
||||
self.gridlayout3 = QtWidgets.QGridLayout(self.uiNIOUDPSettingsGroupBox)
|
||||
self.gridlayout3.setObjectName("gridlayout3")
|
||||
self.uiLocalPortLabel = QtWidgets.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiLocalPortLabel.setObjectName("uiLocalPortLabel")
|
||||
self.gridlayout3.addWidget(self.uiLocalPortLabel, 0, 0, 1, 1)
|
||||
self.uiLocalPortSpinBox = QtGui.QSpinBox(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiLocalPortSpinBox = QtWidgets.QSpinBox(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiLocalPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiLocalPortSpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiLocalPortSpinBox.setMaximum(65535)
|
||||
self.uiLocalPortSpinBox.setProperty("value", 30000)
|
||||
self.uiLocalPortSpinBox.setObjectName(_fromUtf8("uiLocalPortSpinBox"))
|
||||
self.uiLocalPortSpinBox.setObjectName("uiLocalPortSpinBox")
|
||||
self.gridlayout3.addWidget(self.uiLocalPortSpinBox, 0, 1, 1, 1)
|
||||
self.uiRemoteHostLabel = QtGui.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiRemoteHostLabel.setObjectName(_fromUtf8("uiRemoteHostLabel"))
|
||||
self.uiRemoteHostLabel = QtWidgets.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiRemoteHostLabel.setObjectName("uiRemoteHostLabel")
|
||||
self.gridlayout3.addWidget(self.uiRemoteHostLabel, 1, 0, 1, 1)
|
||||
self.uiRemoteHostLineEdit = QtGui.QLineEdit(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiRemoteHostLineEdit = QtWidgets.QLineEdit(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiRemoteHostLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiRemoteHostLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiRemoteHostLineEdit.setMinimumSize(QtCore.QSize(80, 0))
|
||||
self.uiRemoteHostLineEdit.setObjectName(_fromUtf8("uiRemoteHostLineEdit"))
|
||||
self.uiRemoteHostLineEdit.setObjectName("uiRemoteHostLineEdit")
|
||||
self.gridlayout3.addWidget(self.uiRemoteHostLineEdit, 1, 1, 1, 1)
|
||||
self.uiRemotePortLabel = QtGui.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiRemotePortLabel.setObjectName(_fromUtf8("uiRemotePortLabel"))
|
||||
self.uiRemotePortLabel = QtWidgets.QLabel(self.uiNIOUDPSettingsGroupBox)
|
||||
self.uiRemotePortLabel.setObjectName("uiRemotePortLabel")
|
||||
self.gridlayout3.addWidget(self.uiRemotePortLabel, 2, 0, 1, 1)
|
||||
self.uiRemotePortSpinBox = QtGui.QSpinBox(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiRemotePortSpinBox = QtWidgets.QSpinBox(self.uiNIOUDPSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiRemotePortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiRemotePortSpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiRemotePortSpinBox.setMaximum(65535)
|
||||
self.uiRemotePortSpinBox.setProperty("value", 20000)
|
||||
self.uiRemotePortSpinBox.setObjectName(_fromUtf8("uiRemotePortSpinBox"))
|
||||
self.uiRemotePortSpinBox.setObjectName("uiRemotePortSpinBox")
|
||||
self.gridlayout3.addWidget(self.uiRemotePortSpinBox, 2, 1, 1, 1)
|
||||
self.gridlayout2.addWidget(self.uiNIOUDPSettingsGroupBox, 0, 0, 1, 2)
|
||||
self.uiNIOUDPListGroupBox = QtGui.QGroupBox(self.NIOUDPTab)
|
||||
self.uiNIOUDPListGroupBox.setObjectName(_fromUtf8("uiNIOUDPListGroupBox"))
|
||||
self.vboxlayout2 = QtGui.QVBoxLayout(self.uiNIOUDPListGroupBox)
|
||||
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
|
||||
self.uiNIOUDPListWidget = QtGui.QListWidget(self.uiNIOUDPListGroupBox)
|
||||
self.uiNIOUDPListWidget.setObjectName(_fromUtf8("uiNIOUDPListWidget"))
|
||||
self.uiNIOUDPListGroupBox = QtWidgets.QGroupBox(self.NIOUDPTab)
|
||||
self.uiNIOUDPListGroupBox.setObjectName("uiNIOUDPListGroupBox")
|
||||
self.vboxlayout2 = QtWidgets.QVBoxLayout(self.uiNIOUDPListGroupBox)
|
||||
self.vboxlayout2.setObjectName("vboxlayout2")
|
||||
self.uiNIOUDPListWidget = QtWidgets.QListWidget(self.uiNIOUDPListGroupBox)
|
||||
self.uiNIOUDPListWidget.setObjectName("uiNIOUDPListWidget")
|
||||
self.vboxlayout2.addWidget(self.uiNIOUDPListWidget)
|
||||
self.gridlayout2.addWidget(self.uiNIOUDPListGroupBox, 0, 2, 2, 1)
|
||||
self.uiAddNIOUDPPushButton = QtGui.QPushButton(self.NIOUDPTab)
|
||||
self.uiAddNIOUDPPushButton.setObjectName(_fromUtf8("uiAddNIOUDPPushButton"))
|
||||
self.uiAddNIOUDPPushButton = QtWidgets.QPushButton(self.NIOUDPTab)
|
||||
self.uiAddNIOUDPPushButton.setObjectName("uiAddNIOUDPPushButton")
|
||||
self.gridlayout2.addWidget(self.uiAddNIOUDPPushButton, 1, 0, 1, 1)
|
||||
self.uiDeleteNIOUDPPushButton = QtGui.QPushButton(self.NIOUDPTab)
|
||||
self.uiDeleteNIOUDPPushButton = QtWidgets.QPushButton(self.NIOUDPTab)
|
||||
self.uiDeleteNIOUDPPushButton.setEnabled(False)
|
||||
self.uiDeleteNIOUDPPushButton.setObjectName(_fromUtf8("uiDeleteNIOUDPPushButton"))
|
||||
self.uiDeleteNIOUDPPushButton.setObjectName("uiDeleteNIOUDPPushButton")
|
||||
self.gridlayout2.addWidget(self.uiDeleteNIOUDPPushButton, 1, 1, 1, 1)
|
||||
spacerItem3 = QtGui.QSpacerItem(20, 211, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem3 = QtWidgets.QSpacerItem(20, 211, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridlayout2.addItem(spacerItem3, 2, 1, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.NIOUDPTab, _fromUtf8(""))
|
||||
self.NIOTAPTab = QtGui.QWidget()
|
||||
self.NIOTAPTab.setObjectName(_fromUtf8("NIOTAPTab"))
|
||||
self.vboxlayout3 = QtGui.QVBoxLayout(self.NIOTAPTab)
|
||||
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
|
||||
self.uiNIOTAPGroupBox = QtGui.QGroupBox(self.NIOTAPTab)
|
||||
self.uiNIOTAPGroupBox.setObjectName(_fromUtf8("uiNIOTAPGroupBox"))
|
||||
self.gridlayout4 = QtGui.QGridLayout(self.uiNIOTAPGroupBox)
|
||||
self.gridlayout4.setObjectName(_fromUtf8("gridlayout4"))
|
||||
self.uiNIOTAPLineEdit = QtGui.QLineEdit(self.uiNIOTAPGroupBox)
|
||||
self.uiNIOTAPLineEdit.setObjectName(_fromUtf8("uiNIOTAPLineEdit"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIOUDPTab, "")
|
||||
self.NIOTAPTab = QtWidgets.QWidget()
|
||||
self.NIOTAPTab.setObjectName("NIOTAPTab")
|
||||
self.vboxlayout3 = QtWidgets.QVBoxLayout(self.NIOTAPTab)
|
||||
self.vboxlayout3.setObjectName("vboxlayout3")
|
||||
self.uiNIOTAPGroupBox = QtWidgets.QGroupBox(self.NIOTAPTab)
|
||||
self.uiNIOTAPGroupBox.setObjectName("uiNIOTAPGroupBox")
|
||||
self.gridlayout4 = QtWidgets.QGridLayout(self.uiNIOTAPGroupBox)
|
||||
self.gridlayout4.setObjectName("gridlayout4")
|
||||
self.uiNIOTAPLineEdit = QtWidgets.QLineEdit(self.uiNIOTAPGroupBox)
|
||||
self.uiNIOTAPLineEdit.setObjectName("uiNIOTAPLineEdit")
|
||||
self.gridlayout4.addWidget(self.uiNIOTAPLineEdit, 0, 0, 1, 1)
|
||||
self.uiAddNIOTAPPushButton = QtGui.QPushButton(self.uiNIOTAPGroupBox)
|
||||
self.uiAddNIOTAPPushButton.setObjectName(_fromUtf8("uiAddNIOTAPPushButton"))
|
||||
self.uiAddNIOTAPPushButton = QtWidgets.QPushButton(self.uiNIOTAPGroupBox)
|
||||
self.uiAddNIOTAPPushButton.setObjectName("uiAddNIOTAPPushButton")
|
||||
self.gridlayout4.addWidget(self.uiAddNIOTAPPushButton, 0, 1, 1, 1)
|
||||
self.uiDeleteNIOTAPPushButton = QtGui.QPushButton(self.uiNIOTAPGroupBox)
|
||||
self.uiDeleteNIOTAPPushButton = QtWidgets.QPushButton(self.uiNIOTAPGroupBox)
|
||||
self.uiDeleteNIOTAPPushButton.setEnabled(False)
|
||||
self.uiDeleteNIOTAPPushButton.setObjectName(_fromUtf8("uiDeleteNIOTAPPushButton"))
|
||||
self.uiDeleteNIOTAPPushButton.setObjectName("uiDeleteNIOTAPPushButton")
|
||||
self.gridlayout4.addWidget(self.uiDeleteNIOTAPPushButton, 0, 2, 1, 1)
|
||||
self.uiNIOTAPListWidget = QtGui.QListWidget(self.uiNIOTAPGroupBox)
|
||||
self.uiNIOTAPListWidget.setObjectName(_fromUtf8("uiNIOTAPListWidget"))
|
||||
self.uiNIOTAPListWidget = QtWidgets.QListWidget(self.uiNIOTAPGroupBox)
|
||||
self.uiNIOTAPListWidget.setObjectName("uiNIOTAPListWidget")
|
||||
self.gridlayout4.addWidget(self.uiNIOTAPListWidget, 1, 0, 1, 3)
|
||||
self.vboxlayout3.addWidget(self.uiNIOTAPGroupBox)
|
||||
spacerItem4 = QtGui.QSpacerItem(20, 191, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem4 = QtWidgets.QSpacerItem(20, 191, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.vboxlayout3.addItem(spacerItem4)
|
||||
self.uiNIOsTabWidget.addTab(self.NIOTAPTab, _fromUtf8(""))
|
||||
self.NIOUnixTab = QtGui.QWidget()
|
||||
self.NIOUnixTab.setObjectName(_fromUtf8("NIOUnixTab"))
|
||||
self.gridlayout5 = QtGui.QGridLayout(self.NIOUnixTab)
|
||||
self.gridlayout5.setObjectName(_fromUtf8("gridlayout5"))
|
||||
self.uiNIOUNIXSettingsGroupBox = QtGui.QGroupBox(self.NIOUnixTab)
|
||||
self.uiNIOUNIXSettingsGroupBox.setObjectName(_fromUtf8("uiNIOUNIXSettingsGroupBox"))
|
||||
self.gridlayout6 = QtGui.QGridLayout(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.gridlayout6.setObjectName(_fromUtf8("gridlayout6"))
|
||||
self.gridlayout7 = QtGui.QGridLayout()
|
||||
self.gridlayout7.setObjectName(_fromUtf8("gridlayout7"))
|
||||
self.uiLocalFileLabel = QtGui.QLabel(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.uiLocalFileLabel.setObjectName(_fromUtf8("uiLocalFileLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIOTAPTab, "")
|
||||
self.NIOUnixTab = QtWidgets.QWidget()
|
||||
self.NIOUnixTab.setObjectName("NIOUnixTab")
|
||||
self.gridlayout5 = QtWidgets.QGridLayout(self.NIOUnixTab)
|
||||
self.gridlayout5.setObjectName("gridlayout5")
|
||||
self.uiNIOUNIXSettingsGroupBox = QtWidgets.QGroupBox(self.NIOUnixTab)
|
||||
self.uiNIOUNIXSettingsGroupBox.setObjectName("uiNIOUNIXSettingsGroupBox")
|
||||
self.gridlayout6 = QtWidgets.QGridLayout(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.gridlayout6.setObjectName("gridlayout6")
|
||||
self.gridlayout7 = QtWidgets.QGridLayout()
|
||||
self.gridlayout7.setObjectName("gridlayout7")
|
||||
self.uiLocalFileLabel = QtWidgets.QLabel(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.uiLocalFileLabel.setObjectName("uiLocalFileLabel")
|
||||
self.gridlayout7.addWidget(self.uiLocalFileLabel, 0, 0, 1, 1)
|
||||
self.uiLocalFileLineEdit = QtGui.QLineEdit(self.uiNIOUNIXSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiLocalFileLineEdit = QtWidgets.QLineEdit(self.uiNIOUNIXSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiLocalFileLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiLocalFileLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiLocalFileLineEdit.setObjectName(_fromUtf8("uiLocalFileLineEdit"))
|
||||
self.uiLocalFileLineEdit.setObjectName("uiLocalFileLineEdit")
|
||||
self.gridlayout7.addWidget(self.uiLocalFileLineEdit, 1, 0, 1, 1)
|
||||
self.gridlayout6.addLayout(self.gridlayout7, 0, 0, 1, 1)
|
||||
self.gridlayout8 = QtGui.QGridLayout()
|
||||
self.gridlayout8.setObjectName(_fromUtf8("gridlayout8"))
|
||||
self.uiRemoteFileLabel = QtGui.QLabel(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.uiRemoteFileLabel.setObjectName(_fromUtf8("uiRemoteFileLabel"))
|
||||
self.gridlayout8 = QtWidgets.QGridLayout()
|
||||
self.gridlayout8.setObjectName("gridlayout8")
|
||||
self.uiRemoteFileLabel = QtWidgets.QLabel(self.uiNIOUNIXSettingsGroupBox)
|
||||
self.uiRemoteFileLabel.setObjectName("uiRemoteFileLabel")
|
||||
self.gridlayout8.addWidget(self.uiRemoteFileLabel, 0, 0, 1, 1)
|
||||
self.uiRemoteFileLineEdit = QtGui.QLineEdit(self.uiNIOUNIXSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiRemoteFileLineEdit = QtWidgets.QLineEdit(self.uiNIOUNIXSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiRemoteFileLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiRemoteFileLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiRemoteFileLineEdit.setObjectName(_fromUtf8("uiRemoteFileLineEdit"))
|
||||
self.uiRemoteFileLineEdit.setObjectName("uiRemoteFileLineEdit")
|
||||
self.gridlayout8.addWidget(self.uiRemoteFileLineEdit, 1, 0, 1, 1)
|
||||
self.gridlayout6.addLayout(self.gridlayout8, 1, 0, 1, 1)
|
||||
self.gridlayout5.addWidget(self.uiNIOUNIXSettingsGroupBox, 0, 0, 1, 2)
|
||||
self.uiNIOUNIXListGroupBox = QtGui.QGroupBox(self.NIOUnixTab)
|
||||
self.uiNIOUNIXListGroupBox.setObjectName(_fromUtf8("uiNIOUNIXListGroupBox"))
|
||||
self.vboxlayout4 = QtGui.QVBoxLayout(self.uiNIOUNIXListGroupBox)
|
||||
self.vboxlayout4.setObjectName(_fromUtf8("vboxlayout4"))
|
||||
self.uiNIOUNIXListWidget = QtGui.QListWidget(self.uiNIOUNIXListGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.uiNIOUNIXListGroupBox = QtWidgets.QGroupBox(self.NIOUnixTab)
|
||||
self.uiNIOUNIXListGroupBox.setObjectName("uiNIOUNIXListGroupBox")
|
||||
self.vboxlayout4 = QtWidgets.QVBoxLayout(self.uiNIOUNIXListGroupBox)
|
||||
self.vboxlayout4.setObjectName("vboxlayout4")
|
||||
self.uiNIOUNIXListWidget = QtWidgets.QListWidget(self.uiNIOUNIXListGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIOUNIXListWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIOUNIXListWidget.setSizePolicy(sizePolicy)
|
||||
self.uiNIOUNIXListWidget.setObjectName(_fromUtf8("uiNIOUNIXListWidget"))
|
||||
self.uiNIOUNIXListWidget.setObjectName("uiNIOUNIXListWidget")
|
||||
self.vboxlayout4.addWidget(self.uiNIOUNIXListWidget)
|
||||
self.gridlayout5.addWidget(self.uiNIOUNIXListGroupBox, 0, 2, 3, 1)
|
||||
self.uiAddNIOUNIXPushButton = QtGui.QPushButton(self.NIOUnixTab)
|
||||
self.uiAddNIOUNIXPushButton.setObjectName(_fromUtf8("uiAddNIOUNIXPushButton"))
|
||||
self.uiAddNIOUNIXPushButton = QtWidgets.QPushButton(self.NIOUnixTab)
|
||||
self.uiAddNIOUNIXPushButton.setObjectName("uiAddNIOUNIXPushButton")
|
||||
self.gridlayout5.addWidget(self.uiAddNIOUNIXPushButton, 1, 0, 1, 1)
|
||||
self.uiDeleteNIOUNIXPushButton = QtGui.QPushButton(self.NIOUnixTab)
|
||||
self.uiDeleteNIOUNIXPushButton = QtWidgets.QPushButton(self.NIOUnixTab)
|
||||
self.uiDeleteNIOUNIXPushButton.setEnabled(False)
|
||||
self.uiDeleteNIOUNIXPushButton.setObjectName(_fromUtf8("uiDeleteNIOUNIXPushButton"))
|
||||
self.uiDeleteNIOUNIXPushButton.setObjectName("uiDeleteNIOUNIXPushButton")
|
||||
self.gridlayout5.addWidget(self.uiDeleteNIOUNIXPushButton, 1, 1, 1, 1)
|
||||
spacerItem5 = QtGui.QSpacerItem(160, 190, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
spacerItem5 = QtWidgets.QSpacerItem(160, 190, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||
self.gridlayout5.addItem(spacerItem5, 2, 0, 2, 2)
|
||||
spacerItem6 = QtGui.QSpacerItem(196, 132, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem6 = QtWidgets.QSpacerItem(196, 132, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridlayout5.addItem(spacerItem6, 3, 2, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.NIOUnixTab, _fromUtf8(""))
|
||||
self.NIOVDETab = QtGui.QWidget()
|
||||
self.NIOVDETab.setObjectName(_fromUtf8("NIOVDETab"))
|
||||
self.gridlayout9 = QtGui.QGridLayout(self.NIOVDETab)
|
||||
self.gridlayout9.setObjectName(_fromUtf8("gridlayout9"))
|
||||
self.uiNIOVDESettingsGroupBox = QtGui.QGroupBox(self.NIOVDETab)
|
||||
self.uiNIOVDESettingsGroupBox.setObjectName(_fromUtf8("uiNIOVDESettingsGroupBox"))
|
||||
self.gridlayout10 = QtGui.QGridLayout(self.uiNIOVDESettingsGroupBox)
|
||||
self.gridlayout10.setObjectName(_fromUtf8("gridlayout10"))
|
||||
self.gridlayout11 = QtGui.QGridLayout()
|
||||
self.gridlayout11.setObjectName(_fromUtf8("gridlayout11"))
|
||||
self.uiVDEControlFileLabel = QtGui.QLabel(self.uiNIOVDESettingsGroupBox)
|
||||
self.uiVDEControlFileLabel.setObjectName(_fromUtf8("uiVDEControlFileLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIOUnixTab, "")
|
||||
self.NIOVDETab = QtWidgets.QWidget()
|
||||
self.NIOVDETab.setObjectName("NIOVDETab")
|
||||
self.gridlayout9 = QtWidgets.QGridLayout(self.NIOVDETab)
|
||||
self.gridlayout9.setObjectName("gridlayout9")
|
||||
self.uiNIOVDESettingsGroupBox = QtWidgets.QGroupBox(self.NIOVDETab)
|
||||
self.uiNIOVDESettingsGroupBox.setObjectName("uiNIOVDESettingsGroupBox")
|
||||
self.gridlayout10 = QtWidgets.QGridLayout(self.uiNIOVDESettingsGroupBox)
|
||||
self.gridlayout10.setObjectName("gridlayout10")
|
||||
self.gridlayout11 = QtWidgets.QGridLayout()
|
||||
self.gridlayout11.setObjectName("gridlayout11")
|
||||
self.uiVDEControlFileLabel = QtWidgets.QLabel(self.uiNIOVDESettingsGroupBox)
|
||||
self.uiVDEControlFileLabel.setObjectName("uiVDEControlFileLabel")
|
||||
self.gridlayout11.addWidget(self.uiVDEControlFileLabel, 0, 0, 1, 1)
|
||||
self.uiVDEControlFileLineEdit = QtGui.QLineEdit(self.uiNIOVDESettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiVDEControlFileLineEdit = QtWidgets.QLineEdit(self.uiNIOVDESettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiVDEControlFileLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiVDEControlFileLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiVDEControlFileLineEdit.setObjectName(_fromUtf8("uiVDEControlFileLineEdit"))
|
||||
self.uiVDEControlFileLineEdit.setObjectName("uiVDEControlFileLineEdit")
|
||||
self.gridlayout11.addWidget(self.uiVDEControlFileLineEdit, 1, 0, 1, 1)
|
||||
self.gridlayout10.addLayout(self.gridlayout11, 0, 0, 1, 1)
|
||||
self.gridlayout12 = QtGui.QGridLayout()
|
||||
self.gridlayout12.setObjectName(_fromUtf8("gridlayout12"))
|
||||
self.uiVDELocalFileLabel = QtGui.QLabel(self.uiNIOVDESettingsGroupBox)
|
||||
self.uiVDELocalFileLabel.setObjectName(_fromUtf8("uiVDELocalFileLabel"))
|
||||
self.gridlayout12 = QtWidgets.QGridLayout()
|
||||
self.gridlayout12.setObjectName("gridlayout12")
|
||||
self.uiVDELocalFileLabel = QtWidgets.QLabel(self.uiNIOVDESettingsGroupBox)
|
||||
self.uiVDELocalFileLabel.setObjectName("uiVDELocalFileLabel")
|
||||
self.gridlayout12.addWidget(self.uiVDELocalFileLabel, 0, 0, 1, 1)
|
||||
self.uiVDELocalFileLineEdit = QtGui.QLineEdit(self.uiNIOVDESettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiVDELocalFileLineEdit = QtWidgets.QLineEdit(self.uiNIOVDESettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiVDELocalFileLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiVDELocalFileLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiVDELocalFileLineEdit.setObjectName(_fromUtf8("uiVDELocalFileLineEdit"))
|
||||
self.uiVDELocalFileLineEdit.setObjectName("uiVDELocalFileLineEdit")
|
||||
self.gridlayout12.addWidget(self.uiVDELocalFileLineEdit, 1, 0, 1, 1)
|
||||
self.gridlayout10.addLayout(self.gridlayout12, 1, 0, 1, 1)
|
||||
self.gridlayout9.addWidget(self.uiNIOVDESettingsGroupBox, 0, 0, 1, 2)
|
||||
self.uiNIOVDEListGroupBox = QtGui.QGroupBox(self.NIOVDETab)
|
||||
self.uiNIOVDEListGroupBox.setObjectName(_fromUtf8("uiNIOVDEListGroupBox"))
|
||||
self.vboxlayout5 = QtGui.QVBoxLayout(self.uiNIOVDEListGroupBox)
|
||||
self.vboxlayout5.setObjectName(_fromUtf8("vboxlayout5"))
|
||||
self.uiNIOVDEListWidget = QtGui.QListWidget(self.uiNIOVDEListGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.uiNIOVDEListGroupBox = QtWidgets.QGroupBox(self.NIOVDETab)
|
||||
self.uiNIOVDEListGroupBox.setObjectName("uiNIOVDEListGroupBox")
|
||||
self.vboxlayout5 = QtWidgets.QVBoxLayout(self.uiNIOVDEListGroupBox)
|
||||
self.vboxlayout5.setObjectName("vboxlayout5")
|
||||
self.uiNIOVDEListWidget = QtWidgets.QListWidget(self.uiNIOVDEListGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIOVDEListWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIOVDEListWidget.setSizePolicy(sizePolicy)
|
||||
self.uiNIOVDEListWidget.setObjectName(_fromUtf8("uiNIOVDEListWidget"))
|
||||
self.uiNIOVDEListWidget.setObjectName("uiNIOVDEListWidget")
|
||||
self.vboxlayout5.addWidget(self.uiNIOVDEListWidget)
|
||||
self.gridlayout9.addWidget(self.uiNIOVDEListGroupBox, 0, 2, 3, 1)
|
||||
self.uiAddNIOVDEPushButton = QtGui.QPushButton(self.NIOVDETab)
|
||||
self.uiAddNIOVDEPushButton.setObjectName(_fromUtf8("uiAddNIOVDEPushButton"))
|
||||
self.uiAddNIOVDEPushButton = QtWidgets.QPushButton(self.NIOVDETab)
|
||||
self.uiAddNIOVDEPushButton.setObjectName("uiAddNIOVDEPushButton")
|
||||
self.gridlayout9.addWidget(self.uiAddNIOVDEPushButton, 1, 0, 1, 1)
|
||||
self.uiDeleteNIOVDEPushButton = QtGui.QPushButton(self.NIOVDETab)
|
||||
self.uiDeleteNIOVDEPushButton = QtWidgets.QPushButton(self.NIOVDETab)
|
||||
self.uiDeleteNIOVDEPushButton.setEnabled(False)
|
||||
self.uiDeleteNIOVDEPushButton.setObjectName(_fromUtf8("uiDeleteNIOVDEPushButton"))
|
||||
self.uiDeleteNIOVDEPushButton.setObjectName("uiDeleteNIOVDEPushButton")
|
||||
self.gridlayout9.addWidget(self.uiDeleteNIOVDEPushButton, 1, 1, 1, 1)
|
||||
spacerItem7 = QtGui.QSpacerItem(161, 201, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
spacerItem7 = QtWidgets.QSpacerItem(161, 201, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||
self.gridlayout9.addItem(spacerItem7, 2, 0, 2, 2)
|
||||
spacerItem8 = QtGui.QSpacerItem(196, 132, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem8 = QtWidgets.QSpacerItem(196, 132, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridlayout9.addItem(spacerItem8, 3, 2, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.NIOVDETab, _fromUtf8(""))
|
||||
self.NIONullTab = QtGui.QWidget()
|
||||
self.NIONullTab.setObjectName(_fromUtf8("NIONullTab"))
|
||||
self.gridlayout13 = QtGui.QGridLayout(self.NIONullTab)
|
||||
self.gridlayout13.setObjectName(_fromUtf8("gridlayout13"))
|
||||
self.uiNIONullSettingsGroupBox = QtGui.QGroupBox(self.NIONullTab)
|
||||
self.uiNIONullSettingsGroupBox.setObjectName(_fromUtf8("uiNIONullSettingsGroupBox"))
|
||||
self.gridlayout14 = QtGui.QGridLayout(self.uiNIONullSettingsGroupBox)
|
||||
self.gridlayout14.setObjectName(_fromUtf8("gridlayout14"))
|
||||
self.uiNIONullIdentifierLabel = QtGui.QLabel(self.uiNIONullSettingsGroupBox)
|
||||
self.uiNIONullIdentifierLabel.setObjectName(_fromUtf8("uiNIONullIdentifierLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIOVDETab, "")
|
||||
self.NIONullTab = QtWidgets.QWidget()
|
||||
self.NIONullTab.setObjectName("NIONullTab")
|
||||
self.gridlayout13 = QtWidgets.QGridLayout(self.NIONullTab)
|
||||
self.gridlayout13.setObjectName("gridlayout13")
|
||||
self.uiNIONullSettingsGroupBox = QtWidgets.QGroupBox(self.NIONullTab)
|
||||
self.uiNIONullSettingsGroupBox.setObjectName("uiNIONullSettingsGroupBox")
|
||||
self.gridlayout14 = QtWidgets.QGridLayout(self.uiNIONullSettingsGroupBox)
|
||||
self.gridlayout14.setObjectName("gridlayout14")
|
||||
self.uiNIONullIdentifierLabel = QtWidgets.QLabel(self.uiNIONullSettingsGroupBox)
|
||||
self.uiNIONullIdentifierLabel.setObjectName("uiNIONullIdentifierLabel")
|
||||
self.gridlayout14.addWidget(self.uiNIONullIdentifierLabel, 0, 0, 1, 1)
|
||||
self.uiNIONullIdentiferLineEdit = QtGui.QLineEdit(self.uiNIONullSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiNIONullIdentiferLineEdit = QtWidgets.QLineEdit(self.uiNIONullSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIONullIdentiferLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIONullIdentiferLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiNIONullIdentiferLineEdit.setObjectName(_fromUtf8("uiNIONullIdentiferLineEdit"))
|
||||
self.uiNIONullIdentiferLineEdit.setObjectName("uiNIONullIdentiferLineEdit")
|
||||
self.gridlayout14.addWidget(self.uiNIONullIdentiferLineEdit, 1, 0, 1, 1)
|
||||
self.gridlayout13.addWidget(self.uiNIONullSettingsGroupBox, 0, 0, 1, 2)
|
||||
self.uiNIONullListGroupBox = QtGui.QGroupBox(self.NIONullTab)
|
||||
self.uiNIONullListGroupBox.setObjectName(_fromUtf8("uiNIONullListGroupBox"))
|
||||
self.vboxlayout6 = QtGui.QVBoxLayout(self.uiNIONullListGroupBox)
|
||||
self.vboxlayout6.setObjectName(_fromUtf8("vboxlayout6"))
|
||||
self.uiNIONullListWidget = QtGui.QListWidget(self.uiNIONullListGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.uiNIONullListGroupBox = QtWidgets.QGroupBox(self.NIONullTab)
|
||||
self.uiNIONullListGroupBox.setObjectName("uiNIONullListGroupBox")
|
||||
self.vboxlayout6 = QtWidgets.QVBoxLayout(self.uiNIONullListGroupBox)
|
||||
self.vboxlayout6.setObjectName("vboxlayout6")
|
||||
self.uiNIONullListWidget = QtWidgets.QListWidget(self.uiNIONullListGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNIONullListWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiNIONullListWidget.setSizePolicy(sizePolicy)
|
||||
self.uiNIONullListWidget.setObjectName(_fromUtf8("uiNIONullListWidget"))
|
||||
self.uiNIONullListWidget.setObjectName("uiNIONullListWidget")
|
||||
self.vboxlayout6.addWidget(self.uiNIONullListWidget)
|
||||
self.gridlayout13.addWidget(self.uiNIONullListGroupBox, 0, 2, 3, 1)
|
||||
self.uiAddNIONullPushButton = QtGui.QPushButton(self.NIONullTab)
|
||||
self.uiAddNIONullPushButton.setObjectName(_fromUtf8("uiAddNIONullPushButton"))
|
||||
self.uiAddNIONullPushButton = QtWidgets.QPushButton(self.NIONullTab)
|
||||
self.uiAddNIONullPushButton.setObjectName("uiAddNIONullPushButton")
|
||||
self.gridlayout13.addWidget(self.uiAddNIONullPushButton, 1, 0, 1, 1)
|
||||
self.uiDeleteNIONullPushButton = QtGui.QPushButton(self.NIONullTab)
|
||||
self.uiDeleteNIONullPushButton = QtWidgets.QPushButton(self.NIONullTab)
|
||||
self.uiDeleteNIONullPushButton.setEnabled(False)
|
||||
self.uiDeleteNIONullPushButton.setObjectName(_fromUtf8("uiDeleteNIONullPushButton"))
|
||||
self.uiDeleteNIONullPushButton.setObjectName("uiDeleteNIONullPushButton")
|
||||
self.gridlayout13.addWidget(self.uiDeleteNIONullPushButton, 1, 1, 1, 1)
|
||||
spacerItem9 = QtGui.QSpacerItem(20, 261, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem9 = QtWidgets.QSpacerItem(20, 261, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridlayout13.addItem(spacerItem9, 2, 0, 2, 2)
|
||||
spacerItem10 = QtGui.QSpacerItem(20, 181, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem10 = QtWidgets.QSpacerItem(20, 181, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridlayout13.addItem(spacerItem10, 3, 2, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.NIONullTab, _fromUtf8(""))
|
||||
self.MiscTab = QtGui.QWidget()
|
||||
self.MiscTab.setObjectName(_fromUtf8("MiscTab"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.MiscTab)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.MiscTab)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.uiNIOsTabWidget.addTab(self.NIONullTab, "")
|
||||
self.MiscTab = QtWidgets.QWidget()
|
||||
self.MiscTab.setObjectName("MiscTab")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.MiscTab)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.MiscTab)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.MiscTab)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.MiscTab)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
spacerItem11 = QtGui.QSpacerItem(20, 399, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem11 = QtWidgets.QSpacerItem(20, 399, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem11, 1, 1, 1, 1)
|
||||
self.uiNIOsTabWidget.addTab(self.MiscTab, _fromUtf8(""))
|
||||
self.uiNIOsTabWidget.addTab(self.MiscTab, "")
|
||||
self.vboxlayout.addWidget(self.uiNIOsTabWidget)
|
||||
|
||||
self.retranslateUi(cloudConfigPageWidget)
|
||||
@@ -420,53 +406,54 @@ class Ui_cloudConfigPageWidget(object):
|
||||
QtCore.QMetaObject.connectSlotsByName(cloudConfigPageWidget)
|
||||
|
||||
def retranslateUi(self, cloudConfigPageWidget):
|
||||
cloudConfigPageWidget.setWindowTitle(_translate("cloudConfigPageWidget", "Cloud configuration", None))
|
||||
self.uiGenericEthernetGroupBox.setTitle(_translate("cloudConfigPageWidget", "Generic Ethernet NIO (Administrator or root access required)", None))
|
||||
self.uiAddGenericEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteGenericEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiLinuxEthernetGroupBox.setTitle(_translate("cloudConfigPageWidget", "Linux Ethernet NIO (Linux only, root access required)", None))
|
||||
self.uiAddLinuxEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteLinuxEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOEthernetTab), _translate("cloudConfigPageWidget", "Ethernet", None))
|
||||
self.uiNIONATSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings", None))
|
||||
self.uiNIONATIdentifierLabel.setText(_translate("cloudConfigPageWidget", "Identifier:", None))
|
||||
self.uiNIONATListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs", None))
|
||||
self.uiAddNIONATPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIONATPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIONATTab), _translate("cloudConfigPageWidget", "NAT", None))
|
||||
self.uiNIOUDPSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings", None))
|
||||
self.uiLocalPortLabel.setText(_translate("cloudConfigPageWidget", "Local port:", None))
|
||||
self.uiRemoteHostLabel.setText(_translate("cloudConfigPageWidget", "Remote host:", None))
|
||||
self.uiRemoteHostLineEdit.setText(_translate("cloudConfigPageWidget", "127.0.0.1", None))
|
||||
self.uiRemotePortLabel.setText(_translate("cloudConfigPageWidget", "Remote port:", None))
|
||||
self.uiNIOUDPListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs", None))
|
||||
self.uiAddNIOUDPPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIOUDPPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOUDPTab), _translate("cloudConfigPageWidget", "UDP", None))
|
||||
self.uiNIOTAPGroupBox.setTitle(_translate("cloudConfigPageWidget", "TAP interface (require root access)", None))
|
||||
self.uiAddNIOTAPPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIOTAPPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOTAPTab), _translate("cloudConfigPageWidget", "TAP", None))
|
||||
self.uiNIOUNIXSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings", None))
|
||||
self.uiLocalFileLabel.setText(_translate("cloudConfigPageWidget", "Local file:", None))
|
||||
self.uiRemoteFileLabel.setText(_translate("cloudConfigPageWidget", "Remote file:", None))
|
||||
self.uiNIOUNIXListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs", None))
|
||||
self.uiAddNIOUNIXPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIOUNIXPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOUnixTab), _translate("cloudConfigPageWidget", "UNIX", None))
|
||||
self.uiNIOVDESettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings", None))
|
||||
self.uiVDEControlFileLabel.setText(_translate("cloudConfigPageWidget", "Control file:", None))
|
||||
self.uiVDELocalFileLabel.setText(_translate("cloudConfigPageWidget", "Local file:", None))
|
||||
self.uiNIOVDEListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs", None))
|
||||
self.uiAddNIOVDEPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIOVDEPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOVDETab), _translate("cloudConfigPageWidget", "VDE", None))
|
||||
self.uiNIONullSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings", None))
|
||||
self.uiNIONullIdentifierLabel.setText(_translate("cloudConfigPageWidget", "Identifier:", None))
|
||||
self.uiNIONullListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs", None))
|
||||
self.uiAddNIONullPushButton.setText(_translate("cloudConfigPageWidget", "&Add", None))
|
||||
self.uiDeleteNIONullPushButton.setText(_translate("cloudConfigPageWidget", "&Delete", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIONullTab), _translate("cloudConfigPageWidget", "NULL", None))
|
||||
self.uiNameLabel.setText(_translate("cloudConfigPageWidget", "Name:", None))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.MiscTab), _translate("cloudConfigPageWidget", "Misc.", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
cloudConfigPageWidget.setWindowTitle(_translate("cloudConfigPageWidget", "Cloud configuration"))
|
||||
self.uiGenericEthernetGroupBox.setTitle(_translate("cloudConfigPageWidget", "Generic Ethernet NIO (Administrator or root access required)"))
|
||||
self.uiAddGenericEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteGenericEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiLinuxEthernetGroupBox.setTitle(_translate("cloudConfigPageWidget", "Linux Ethernet NIO (Linux only, root access required)"))
|
||||
self.uiAddLinuxEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteLinuxEthernetPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOEthernetTab), _translate("cloudConfigPageWidget", "Ethernet"))
|
||||
self.uiNIONATSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings"))
|
||||
self.uiNIONATIdentifierLabel.setText(_translate("cloudConfigPageWidget", "Local identifier:"))
|
||||
self.uiNIONATListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs"))
|
||||
self.uiAddNIONATPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIONATPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIONATTab), _translate("cloudConfigPageWidget", "NAT"))
|
||||
self.uiNIOUDPSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings"))
|
||||
self.uiLocalPortLabel.setText(_translate("cloudConfigPageWidget", "Local port:"))
|
||||
self.uiRemoteHostLabel.setText(_translate("cloudConfigPageWidget", "Remote host:"))
|
||||
self.uiRemoteHostLineEdit.setText(_translate("cloudConfigPageWidget", "127.0.0.1"))
|
||||
self.uiRemotePortLabel.setText(_translate("cloudConfigPageWidget", "Remote port:"))
|
||||
self.uiNIOUDPListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs"))
|
||||
self.uiAddNIOUDPPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIOUDPPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOUDPTab), _translate("cloudConfigPageWidget", "UDP"))
|
||||
self.uiNIOTAPGroupBox.setTitle(_translate("cloudConfigPageWidget", "TAP interface (require root access)"))
|
||||
self.uiAddNIOTAPPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIOTAPPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOTAPTab), _translate("cloudConfigPageWidget", "TAP"))
|
||||
self.uiNIOUNIXSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings"))
|
||||
self.uiLocalFileLabel.setText(_translate("cloudConfigPageWidget", "Local file:"))
|
||||
self.uiRemoteFileLabel.setText(_translate("cloudConfigPageWidget", "Remote file:"))
|
||||
self.uiNIOUNIXListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs"))
|
||||
self.uiAddNIOUNIXPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIOUNIXPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOUnixTab), _translate("cloudConfigPageWidget", "UNIX"))
|
||||
self.uiNIOVDESettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings"))
|
||||
self.uiVDEControlFileLabel.setText(_translate("cloudConfigPageWidget", "Control file:"))
|
||||
self.uiVDELocalFileLabel.setText(_translate("cloudConfigPageWidget", "Local file:"))
|
||||
self.uiNIOVDEListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs"))
|
||||
self.uiAddNIOVDEPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIOVDEPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIOVDETab), _translate("cloudConfigPageWidget", "VDE"))
|
||||
self.uiNIONullSettingsGroupBox.setTitle(_translate("cloudConfigPageWidget", "Settings"))
|
||||
self.uiNIONullIdentifierLabel.setText(_translate("cloudConfigPageWidget", "Local identifier:"))
|
||||
self.uiNIONullListGroupBox.setTitle(_translate("cloudConfigPageWidget", "NIOs"))
|
||||
self.uiAddNIONullPushButton.setText(_translate("cloudConfigPageWidget", "&Add"))
|
||||
self.uiDeleteNIONullPushButton.setText(_translate("cloudConfigPageWidget", "&Delete"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.NIONullTab), _translate("cloudConfigPageWidget", "NULL"))
|
||||
self.uiNameLabel.setText(_translate("cloudConfigPageWidget", "Name:"))
|
||||
self.uiNIOsTabWidget.setTabText(self.uiNIOsTabWidget.indexOf(self.MiscTab), _translate("cloudConfigPageWidget", "Misc."))
|
||||
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
Dynamips module implementation.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import hashlib
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.servers import Servers
|
||||
from gns3.local_config import LocalConfig
|
||||
from gns3.image_manager import ImageManager
|
||||
from gns3.local_server_config import LocalServerConfig
|
||||
from gns3.gns3_vm import GNS3VM
|
||||
|
||||
from ..module import Module
|
||||
from ..module_error import ModuleError
|
||||
@@ -43,9 +45,10 @@ from .nodes.ethernet_switch import EthernetSwitch
|
||||
from .nodes.ethernet_hub import EthernetHub
|
||||
from .nodes.frame_relay_switch import FrameRelaySwitch
|
||||
from .nodes.atm_switch import ATMSwitch
|
||||
from .settings import DYNAMIPS_SETTINGS, DYNAMIPS_SETTING_TYPES
|
||||
from .settings import IOS_ROUTER_SETTINGS, IOS_ROUTER_SETTING_TYPES
|
||||
from .settings import DYNAMIPS_SETTINGS
|
||||
from .settings import IOS_ROUTER_SETTINGS
|
||||
from .settings import PLATFORMS_DEFAULT_RAM
|
||||
from .settings import DEFAULT_IDLEPC
|
||||
|
||||
PLATFORM_TO_CLASS = {
|
||||
"c1700": C1700,
|
||||
@@ -68,61 +71,63 @@ class Dynamips(Module):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Module.__init__(self)
|
||||
super().__init__()
|
||||
|
||||
self._settings = {}
|
||||
self._ios_routers = {}
|
||||
self._nodes = []
|
||||
self._ios_images_cache = {}
|
||||
|
||||
self.configChangedSlot()
|
||||
|
||||
def configChangedSlot(self):
|
||||
# load the settings and IOS images.
|
||||
self._loadSettings()
|
||||
self._loadIOSRouters()
|
||||
|
||||
@staticmethod
|
||||
def _findDynamips():
|
||||
def getDefaultIdlePC(path):
|
||||
"""
|
||||
Finds the Dynamips path.
|
||||
|
||||
:return: path to Dynamips
|
||||
Return the default IDLE PC for an image if the image
|
||||
exists or None otherwise
|
||||
"""
|
||||
if not os.path.isfile(path):
|
||||
path = os.path.join(ImageManager.instance().getDirectoryForType("DYNAMIPS"), path)
|
||||
if not os.path.isfile(path):
|
||||
return None
|
||||
try:
|
||||
md5sum = Dynamips._md5sum(path)
|
||||
log.debug("Get idlePC for %s. md5sum %s", path, md5sum)
|
||||
if md5sum in DEFAULT_IDLEPC:
|
||||
log.debug("IDLEPC found for %s", path)
|
||||
return DEFAULT_IDLEPC[md5sum]
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
if sys.platform.startswith("win") and hasattr(sys, "frozen"):
|
||||
dynamips_path = os.path.join(os.getcwd(), "dynamips", "dynamips.exe")
|
||||
elif sys.platform.startswith("darwin") and hasattr(sys, "frozen"):
|
||||
dynamips_path = os.path.join(os.getcwd(), "dynamips")
|
||||
else:
|
||||
dynamips_path = shutil.which("dynamips")
|
||||
|
||||
if dynamips_path is None:
|
||||
return ""
|
||||
return dynamips_path
|
||||
@staticmethod
|
||||
def _md5sum(path):
|
||||
with open(path, "rb") as fd:
|
||||
m = hashlib.md5()
|
||||
while True:
|
||||
data = fd.read(8192)
|
||||
if not data:
|
||||
break
|
||||
m.update(data)
|
||||
return m.hexdigest()
|
||||
|
||||
def _loadSettings(self):
|
||||
"""
|
||||
Loads the settings from the persistent settings file.
|
||||
"""
|
||||
|
||||
local_config = LocalConfig.instance()
|
||||
# restore the Dynamips settings from QSettings (for backward compatibility)
|
||||
legacy_settings = {}
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.__class__.__name__)
|
||||
for name in DYNAMIPS_SETTINGS.keys():
|
||||
if settings.contains(name):
|
||||
legacy_settings[name] = settings.value(name, type=DYNAMIPS_SETTING_TYPES[name])
|
||||
settings.remove("")
|
||||
settings.endGroup()
|
||||
|
||||
if legacy_settings:
|
||||
local_config.saveSectionSettings(self.__class__.__name__, legacy_settings)
|
||||
self._settings = local_config.loadSectionSettings(self.__class__.__name__, DYNAMIPS_SETTINGS)
|
||||
|
||||
self._settings = LocalConfig.instance().loadSectionSettings(self.__class__.__name__, DYNAMIPS_SETTINGS)
|
||||
if not os.path.exists(self._settings["dynamips_path"]):
|
||||
self._settings["dynamips_path"] = self._findDynamips()
|
||||
dynamips_path = shutil.which("dynamips")
|
||||
if dynamips_path:
|
||||
self._settings["dynamips_path"] = os.path.abspath(dynamips_path)
|
||||
else:
|
||||
self._settings["dynamips_path"] = ""
|
||||
|
||||
# keep the config file sync
|
||||
self._saveSettings()
|
||||
self._loadIOSRouters()
|
||||
|
||||
def _saveSettings(self):
|
||||
"""
|
||||
@@ -150,90 +155,30 @@ class Dynamips(Module):
|
||||
Load the IOS routers from the persistent settings file.
|
||||
"""
|
||||
|
||||
local_config = LocalConfig.instance()
|
||||
|
||||
# restore the Dynamips VM settings from QSettings (for backward compatibility)
|
||||
ios_routers = []
|
||||
# load the settings
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup("IOSRouters")
|
||||
# load the VMs
|
||||
size = settings.beginReadArray("ios_router")
|
||||
for index in range(0, size):
|
||||
settings.setArrayIndex(index)
|
||||
router = {}
|
||||
for setting_name, default_value in IOS_ROUTER_SETTINGS.items():
|
||||
router[setting_name] = settings.value(setting_name, default_value, IOS_ROUTER_SETTING_TYPES[setting_name])
|
||||
|
||||
for slot_id in range(0, 7):
|
||||
slot = "slot{}".format(slot_id)
|
||||
if settings.contains(slot):
|
||||
router[slot] = settings.value(slot, "")
|
||||
|
||||
for wic_id in range(0, 3):
|
||||
wic = "wic{}".format(wic_id)
|
||||
if settings.contains(wic):
|
||||
router[wic] = settings.value(wic, "")
|
||||
|
||||
platform = router["platform"]
|
||||
chassis = router["chassis"]
|
||||
|
||||
if platform == "c7200":
|
||||
router["midplane"] = settings.value("midplane", "vxr")
|
||||
router["npe"] = settings.value("npe", "npe-400")
|
||||
router["slot0"] = settings.value("slot0", "C7200-IO-FE")
|
||||
else:
|
||||
router["iomem"] = 5
|
||||
|
||||
if platform in ("c3725", "c3725", "c2691"):
|
||||
router["slot0"] = settings.value("slot0", "GT96100-FE")
|
||||
elif platform == "c3600" and chassis == "3660":
|
||||
router["slot0"] = settings.value("slot0", "Leopard-2FE")
|
||||
elif platform == "c2600" and chassis == "2610":
|
||||
router["slot0"] = settings.value("slot0", "C2600-MB-1E")
|
||||
elif platform == "c2600" and chassis == "2611":
|
||||
router["slot0"] = settings.value("slot0", "C2600-MB-2E")
|
||||
elif platform == "c2600" and chassis in ("2620", "2610XM", "2620XM", "2650XM"):
|
||||
router["slot0"] = settings.value("slot0", "C2600-MB-1FE")
|
||||
elif platform == "c2600" and chassis in ("2621", "2611XM", "2621XM", "2651XM"):
|
||||
router["slot0"] = settings.value("slot0", "C2600-MB-2FE")
|
||||
elif platform == "c1700" and chassis in ("1720", "1721", "1750", "1751", "1760"):
|
||||
router["slot0"] = settings.value("slot0", "C1700-MB-1FE")
|
||||
elif platform == "c1700" and chassis in ("1751", "1760"):
|
||||
router["slot0"] = settings.value("slot0", "C1700-MB-WIC1")
|
||||
|
||||
ios_routers.append(router)
|
||||
|
||||
settings.endArray()
|
||||
settings.remove("")
|
||||
settings.endGroup()
|
||||
|
||||
if ios_routers:
|
||||
local_config.saveSectionSettings(self.__class__.__name__, {"routers": ios_routers})
|
||||
|
||||
settings = local_config.settings()
|
||||
settings = LocalConfig.instance().settings()
|
||||
if "routers" in settings.get(self.__class__.__name__, {}):
|
||||
for router in settings[self.__class__.__name__]["routers"]:
|
||||
name = router.get("name")
|
||||
server = router.get("server")
|
||||
router["image"] = router.get("path", router["image"]) # for compatibility before version 1.3
|
||||
router["image"] = router.get("path", router["image"]) # for backward compatibility before version 1.3
|
||||
key = "{server}:{name}".format(server=server, name=name)
|
||||
if key in self._ios_routers or not name or not server:
|
||||
continue
|
||||
router_settings = IOS_ROUTER_SETTINGS.copy()
|
||||
router_settings.update(router)
|
||||
# for backward compatibility before version 1.4
|
||||
if "symbol" not in router_settings:
|
||||
router_settings["symbol"] = router_settings["default_symbol"]
|
||||
router_settings["symbol"] = router_settings["symbol"][:-11] + ".svg" if router_settings["symbol"].endswith("normal.svg") else router_settings["symbol"]
|
||||
self._ios_routers[key] = router_settings
|
||||
|
||||
# keep things sync
|
||||
self._saveIOSRouters()
|
||||
|
||||
def _saveIOSRouters(self):
|
||||
"""
|
||||
Saves the IOS routers to the persistent settings file.
|
||||
"""
|
||||
|
||||
# save the settings
|
||||
LocalConfig.instance().saveSectionSettings(self.__class__.__name__, {"routers": list(self._ios_routers.values())})
|
||||
self._settings["routers"] = list(self._ios_routers.values())
|
||||
self._saveSettings()
|
||||
|
||||
def addNode(self, node):
|
||||
"""
|
||||
@@ -252,6 +197,8 @@ class Dynamips(Module):
|
||||
"""
|
||||
|
||||
if node in self._nodes:
|
||||
if "ram" in node.settings():
|
||||
node.server().decreaseAllocatedRAM(node.settings()["ram"])
|
||||
self._nodes.remove(node)
|
||||
|
||||
def iosRouters(self):
|
||||
@@ -292,34 +239,6 @@ class Dynamips(Module):
|
||||
self._settings.update(settings)
|
||||
self._saveSettings()
|
||||
|
||||
def allocateServer(self, node_class, use_cloud=False):
|
||||
"""
|
||||
Allocates a server.
|
||||
|
||||
:param node_class: Node object
|
||||
|
||||
:returns: allocated server (HTTPClient instance)
|
||||
"""
|
||||
|
||||
# allocate a server for the node
|
||||
servers = Servers.instance()
|
||||
|
||||
if use_cloud:
|
||||
from ...topology import Topology
|
||||
topology = Topology.instance()
|
||||
top_instance = topology.anyInstance()
|
||||
server = servers.getCloudServer(top_instance.host, top_instance.port, top_instance.ssl_ca_file)
|
||||
else:
|
||||
if self._settings["use_local_server"]:
|
||||
# use the local server
|
||||
server = servers.localServer()
|
||||
else:
|
||||
# pick up a remote server (round-robin method)
|
||||
server = next(iter(servers))
|
||||
if not server:
|
||||
raise ModuleError("No remote server is configured")
|
||||
return server
|
||||
|
||||
def createNode(self, node_class, server, project):
|
||||
"""
|
||||
Creates a new node.
|
||||
@@ -453,9 +372,9 @@ class Dynamips(Module):
|
||||
candidate_ios_images[ios_router["image"]] = ios_router
|
||||
|
||||
if candidate_ios_images:
|
||||
selection, ok = QtGui.QInputDialog.getItem(mainwindow,
|
||||
"IOS image", "IOS image {} could not be found\nPlease select an alternative from your existing images:".format(image),
|
||||
list(candidate_ios_images.keys()), 0, False)
|
||||
selection, ok = QtWidgets.QInputDialog.getItem(mainwindow,
|
||||
"IOS image", "IOS image {} could not be found\nPlease select an alternative from your existing images:".format(image),
|
||||
list(candidate_ios_images.keys()), 0, False)
|
||||
if ok:
|
||||
ios_image = candidate_ios_images[selection] # FIXME
|
||||
alternative_image["image"] = ios_router["image"]
|
||||
@@ -465,9 +384,11 @@ class Dynamips(Module):
|
||||
return alternative_image
|
||||
|
||||
# no registered IOS image is used, let's just ask for an IOS image path
|
||||
QtGui.QMessageBox.critical(mainwindow, "IOS image", "Could not find the {} IOS image \nPlease select a similar IOS image!".format(image))
|
||||
msg = "Could not find the {} IOS image \nPlease select a similar IOS image!".format(image)
|
||||
log.error(msg)
|
||||
QtWidgets.QMessageBox.critical(mainwindow, "IOS image", msg)
|
||||
from .pages.ios_router_preferences_page import IOSRouterPreferencesPage
|
||||
image_path = IOSRouterPreferencesPage.getIOSImage(mainwindow)
|
||||
image_path = IOSRouterPreferencesPage.getIOSImage(mainwindow, None)
|
||||
if image_path:
|
||||
alternative_image["image"] = image_path
|
||||
self._ios_images_cache[image] = alternative_image
|
||||
@@ -503,10 +424,13 @@ class Dynamips(Module):
|
||||
|
||||
server = "local"
|
||||
if not self._settings["use_local_server"]:
|
||||
# pick up a remote server (round-robin method)
|
||||
remote_server = next(iter(Servers.instance()))
|
||||
if remote_server:
|
||||
server = "{}:{}".format(remote_server.host, remote_server.port)
|
||||
if GNS3VM.instance().isRunning():
|
||||
server = "vm"
|
||||
else:
|
||||
# pick up a remote server (round-robin method) #FIXME: review this
|
||||
remote_server = next(iter(Servers.instance()))
|
||||
if remote_server:
|
||||
server = remote_server.url()
|
||||
|
||||
nodes = []
|
||||
for node_class in [EthernetSwitch, EthernetHub, FrameRelaySwitch, ATMSwitch]:
|
||||
@@ -515,8 +439,7 @@ class Dynamips(Module):
|
||||
"name": node_class.symbolName(),
|
||||
"server": server,
|
||||
"categories": node_class.categories(),
|
||||
"default_symbol": node_class.defaultSymbol(),
|
||||
"hover_symbol": node_class.hoverSymbol()}
|
||||
"symbol": node_class.defaultSymbol()}
|
||||
)
|
||||
|
||||
for ios_router in self._ios_routers.values():
|
||||
@@ -524,9 +447,9 @@ class Dynamips(Module):
|
||||
nodes.append(
|
||||
{"class": node_class.__name__,
|
||||
"name": ios_router["name"],
|
||||
"ram": ios_router["ram"],
|
||||
"server": ios_router["server"],
|
||||
"default_symbol": ios_router["default_symbol"],
|
||||
"hover_symbol": ios_router["hover_symbol"],
|
||||
"symbol": ios_router["symbol"],
|
||||
"categories": [ios_router["category"]]}
|
||||
)
|
||||
|
||||
|
||||
@@ -19,21 +19,20 @@
|
||||
Wizard for IOS routers.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import hashlib
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from gns3.servers import Servers
|
||||
from gns3.node import Node
|
||||
from gns3.gns3_vm import GNS3VM
|
||||
from gns3.utils.run_in_terminal import RunInTerminal
|
||||
from gns3.utils.get_resource import get_resource
|
||||
from gns3.utils.get_default_base_config import get_default_base_config
|
||||
from gns3.dialogs.vm_wizard import VMWizard
|
||||
|
||||
from ....settings import ENABLE_CLOUD
|
||||
from ..ui.ios_router_wizard_ui import Ui_IOSRouterWizard
|
||||
from ..settings import PLATFORMS_DEFAULT_RAM, PLATFORMS_DEFAULT_NVRAM, DEFAULT_IDLEPC, CHASSIS, ADAPTER_MATRIX, WIC_MATRIX
|
||||
from ..settings import PLATFORMS_DEFAULT_RAM, PLATFORMS_DEFAULT_NVRAM, CHASSIS, ADAPTER_MATRIX, WIC_MATRIX
|
||||
from .. import Dynamips
|
||||
from ..nodes.c1700 import C1700
|
||||
from ..nodes.c2600 import C2600
|
||||
@@ -57,7 +56,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
class IOSRouterWizard(VMWizard, Ui_IOSRouterWizard):
|
||||
|
||||
"""
|
||||
Wizard to create an IOS router.
|
||||
@@ -68,17 +67,9 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
|
||||
def __init__(self, ios_routers, parent):
|
||||
|
||||
QtGui.QWizard.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/symbols/router.normal.svg"))
|
||||
self.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
if sys.platform.startswith("darwin"):
|
||||
# we want to see the cancel button on OSX
|
||||
self.setOptions(QtGui.QWizard.NoDefaultButton)
|
||||
super().__init__(parent)
|
||||
self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap(":/symbols/router.svg"))
|
||||
|
||||
self.uiRemoteRadioButton.toggled.connect(self._remoteServerToggledSlot)
|
||||
self.uiLoadBalanceCheckBox.toggled.connect(self._loadBalanceToggledSlot)
|
||||
self.uiIOSImageToolButton.clicked.connect(self._iosImageBrowserSlot)
|
||||
self.uiTestIOSImagePushButton.clicked.connect(self._testIOSImageSlot)
|
||||
self.uiIdlePCFinderPushButton.clicked.connect(self._idlePCFinderSlot)
|
||||
self.uiEtherSwitchCheckBox.stateChanged.connect(self._etherSwitchSlot)
|
||||
@@ -124,32 +115,43 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
# skip the server page if we use the local server
|
||||
self.setStartId(1)
|
||||
|
||||
if not ENABLE_CLOUD:
|
||||
self.uiCloudRadioButton.hide()
|
||||
from ..pages.ios_router_preferences_page import IOSRouterPreferencesPage
|
||||
self.addImageSelector(self.uiIOSExistingImageRadioButton, self.uiIOSImageListComboBox, self.uiIOSImageLineEdit, self.uiIOSImageToolButton, IOSRouterPreferencesPage.getIOSImage)
|
||||
|
||||
def _remoteServerToggledSlot(self, checked):
|
||||
def _prefillPlatform(self):
|
||||
"""
|
||||
Slot for when the remote server radio button is toggled.
|
||||
|
||||
:param checked: either the button is checked or not
|
||||
Try to guess the platform based on image name
|
||||
"""
|
||||
# try to guess the platform
|
||||
image = os.path.basename(self.uiIOSImageLineEdit.text())
|
||||
match = re.match("^(c[0-9]+)p?\\-\w+", image.lower())
|
||||
if not match:
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
|
||||
return
|
||||
|
||||
if checked:
|
||||
self.uiRemoteServersGroupBox.setEnabled(True)
|
||||
else:
|
||||
self.uiRemoteServersGroupBox.setEnabled(False)
|
||||
detected_platform = match.group(1)
|
||||
detected_chassis = ""
|
||||
# IOS images for the 3600 platform start with the chassis name (c3620 etc.)
|
||||
for platform, chassis in CHASSIS.items():
|
||||
if detected_platform[1:] in chassis:
|
||||
detected_chassis = detected_platform[1:]
|
||||
detected_platform = platform
|
||||
break
|
||||
|
||||
def _loadBalanceToggledSlot(self, checked):
|
||||
"""
|
||||
Slot for when the load balance checkbox is toggled.
|
||||
if detected_platform not in PLATFORMS_DEFAULT_RAM:
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "This IOS image is for the {} platform/chassis and is not supported by this application!".format(detected_platform))
|
||||
return
|
||||
|
||||
:param checked: either the box is checked or not
|
||||
"""
|
||||
if image.lower().startswith("c7200p"):
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "This IOS image is for c7200 PowerPC routers and is not recommended. Please use an IOS image that do not start with c7200p.")
|
||||
|
||||
if checked:
|
||||
self.uiRemoteServersComboBox.setEnabled(False)
|
||||
else:
|
||||
self.uiRemoteServersComboBox.setEnabled(True)
|
||||
index = self.uiPlatformComboBox.findText(detected_platform)
|
||||
if index != -1:
|
||||
self.uiPlatformComboBox.setCurrentIndex(index)
|
||||
|
||||
index = self.uiChassisComboBox.findText(detected_chassis)
|
||||
if index != -1:
|
||||
self.uiChassisComboBox.setCurrentIndex(index)
|
||||
|
||||
def _platformChangedSlot(self, platform):
|
||||
"""
|
||||
@@ -177,7 +179,7 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
ios_image = self.uiIOSImageLineEdit.text()
|
||||
dynamips = os.path.realpath(Dynamips.instance().settings()["image"])
|
||||
if not os.path.exists(dynamips):
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "Could not find Dynamips executable: {}".format(dynamips))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "Could not find Dynamips executable: {}".format(dynamips))
|
||||
return
|
||||
command = '"{path}" -P {platform} -r {ram} "{ios_image}"'.format(path=dynamips,
|
||||
platform=platform[1:],
|
||||
@@ -186,7 +188,7 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
try:
|
||||
RunInTerminal(command)
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "Could not test the IOS image: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "Could not test the IOS image: {}".format(e))
|
||||
|
||||
def _idlePCValidateSlot(self):
|
||||
"""
|
||||
@@ -257,7 +259,7 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
:param message: error message from the server.
|
||||
"""
|
||||
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC finder", "Could not create IOS router: {}".format(message))
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC finder", "Could not create IOS router: {}".format(message))
|
||||
|
||||
def _computeAutoIdlepcCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
@@ -271,11 +273,11 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
self._router.delete()
|
||||
self._router = None
|
||||
if error:
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC finder", "Error: {}".format(result["message"]))
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC finder", "Error: {}".format(result["message"]))
|
||||
else:
|
||||
idlepc = result["idlepc"]
|
||||
self.uiIdlepcLineEdit.setText(idlepc)
|
||||
QtGui.QMessageBox.information(self, "Idle-PC finder", "Idle-PC value {} has been found suitable for your IOS image".format(idlepc))
|
||||
QtWidgets.QMessageBox.information(self, "Idle-PC finder", "Idle-PC value {} has been found suitable for your IOS image".format(idlepc))
|
||||
|
||||
def _iosImageBrowserSlot(self):
|
||||
"""
|
||||
@@ -283,7 +285,8 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
"""
|
||||
|
||||
from ..pages.ios_router_preferences_page import IOSRouterPreferencesPage
|
||||
path = IOSRouterPreferencesPage.getIOSImage(self)
|
||||
server = Servers.instance().getServerFromString(self.getSettings()["server"])
|
||||
path = IOSRouterPreferencesPage.getIOSImage(self, server)
|
||||
if not path:
|
||||
return
|
||||
self.uiIOSImageLineEdit.clear()
|
||||
@@ -293,7 +296,7 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
image = os.path.basename(path)
|
||||
match = re.match("^(c[0-9]+)p?\\-\w+", image.lower())
|
||||
if not match:
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
|
||||
return
|
||||
|
||||
detected_platform = match.group(1)
|
||||
@@ -306,11 +309,11 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
break
|
||||
|
||||
if detected_platform not in PLATFORMS_DEFAULT_RAM:
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "This IOS image is for the {} platform/chassis and is not supported by this application!".format(detected_platform))
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "This IOS image is for the {} platform/chassis and is not supported by this application!".format(detected_platform))
|
||||
return
|
||||
|
||||
if image.lower().startswith("c7200p"):
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "This IOS image is for c7200 PowerPC routers and is not recommended. Please use an IOS image that do not start with c7200p.")
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "This IOS image is for c7200 PowerPC routers and is not recommended. Please use an IOS image that do not start with c7200p.")
|
||||
|
||||
index = self.uiPlatformComboBox.findText(detected_platform)
|
||||
if index != -1:
|
||||
@@ -324,7 +327,7 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
|
||||
if self._router:
|
||||
self._router.delete()
|
||||
QtGui.QWizard.done(self, result)
|
||||
super().done(result)
|
||||
|
||||
def _populateAdapters(self, platform, chassis):
|
||||
"""
|
||||
@@ -363,25 +366,16 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
wic_list = list(wics)
|
||||
self._widget_wics[wic_number].addItems([""] + wic_list)
|
||||
|
||||
def _md5sum(self, filename):
|
||||
|
||||
with open(filename, "rb") as fd:
|
||||
m = hashlib.md5()
|
||||
while True:
|
||||
data = fd.read(8192)
|
||||
if not data:
|
||||
break
|
||||
m.update(data)
|
||||
return m.hexdigest()
|
||||
|
||||
def initializePage(self, page_id):
|
||||
|
||||
if self.page(page_id) == self.uiServerWizardPage:
|
||||
self.uiRemoteServersComboBox.clear()
|
||||
for server in Servers.instance().remoteServers().values():
|
||||
self.uiRemoteServersComboBox.addItem("{}:{}".format(server.host, server.port), server)
|
||||
super().initializePage(page_id)
|
||||
|
||||
if self.page(page_id) == self.uiServerWizardPage and GNS3VM.instance().isRunning():
|
||||
self.uiVMRadioButton.setChecked(True)
|
||||
elif self.page(page_id) == self.uiIOSImageWizardPage:
|
||||
self.loadImagesList("/dynamips/vms")
|
||||
elif self.page(page_id) == self.uiNamePlatformWizardPage:
|
||||
self._prefillPlatform()
|
||||
self.uiNameLineEdit.setText(self.uiPlatformComboBox.currentText())
|
||||
ios_image = self.uiIOSImageLineEdit.text()
|
||||
self.setWindowTitle("New IOS router - {}".format(os.path.basename(ios_image)))
|
||||
@@ -412,37 +406,32 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
|
||||
elif self.page(page_id) == self.uiIdlePCWizardPage:
|
||||
path = self.uiIOSImageLineEdit.text()
|
||||
if os.path.isfile(path):
|
||||
try:
|
||||
md5sum = self._md5sum(path)
|
||||
if md5sum in DEFAULT_IDLEPC:
|
||||
self.uiIdlepcLineEdit.setText(DEFAULT_IDLEPC[md5sum])
|
||||
except OSError:
|
||||
pass
|
||||
idle_pc = Dynamips.getDefaultIdlePC(path)
|
||||
if idle_pc is not None:
|
||||
self.uiIdlepcLineEdit.setText(idle_pc)
|
||||
|
||||
def validateCurrentPage(self):
|
||||
"""
|
||||
Validates the IOS name and checks validation state for Idle-PC value
|
||||
"""
|
||||
|
||||
if super().validateCurrentPage() is False:
|
||||
return False
|
||||
|
||||
if self.currentPage() == self.uiNamePlatformWizardPage:
|
||||
name = self.uiNameLineEdit.text()
|
||||
for ios_router in self._ios_routers.values():
|
||||
if ios_router["name"] == name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "{} is already used, please choose another name".format(name))
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "{} is already used, please choose another name".format(name))
|
||||
return False
|
||||
if self.currentPage() == self.uiMemoryWizardPage and self.uiPlatformComboBox.currentText() == "c7200":
|
||||
if self.uiRamSpinBox.value() > 512:
|
||||
QtGui.QMessageBox.critical(self, "c7200 RAM requirement", "c7200 routers with NPE-400 are limited to 512MB of RAM")
|
||||
QtWidgets.QMessageBox.critical(self, "c7200 RAM requirement", "c7200 routers with NPE-400 are limited to 512MB of RAM")
|
||||
return False
|
||||
if self.currentPage() == self.uiIdlePCWizardPage:
|
||||
if not self._idle_valid:
|
||||
idle_pc = self.uiIdlepcLineEdit.text()
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "{} is not a valid Idle-PC value ".format(idle_pc))
|
||||
return False
|
||||
if self.currentPage() == self.uiServerWizardPage and self.uiRemoteRadioButton.isChecked():
|
||||
if not Servers.instance().remoteServers():
|
||||
QtGui.QMessageBox.critical(self, "Remote server", "There is no remote server registered in Dynamips preferences")
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "{} is not a valid Idle-PC value ".format(idle_pc))
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -458,12 +447,11 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
server = "local"
|
||||
elif self.uiRemoteRadioButton.isChecked():
|
||||
if self.uiLoadBalanceCheckBox.isChecked():
|
||||
server = next(iter(Servers.instance()))
|
||||
server = "{}:{}".format(server.host, server.port)
|
||||
server = "load-balance"
|
||||
else:
|
||||
server = self.uiRemoteServersComboBox.currentText()
|
||||
else: # Cloud is selected
|
||||
server = "cloud"
|
||||
elif self.uiVMRadioButton.isChecked():
|
||||
server = "vm"
|
||||
|
||||
platform = self.uiPlatformComboBox.currentText()
|
||||
settings = {
|
||||
@@ -480,10 +468,11 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
|
||||
if self.uiEtherSwitchCheckBox.isChecked():
|
||||
settings["startup_config"] = get_default_base_config(self._base_etherswitch_startup_config_template)
|
||||
settings["default_symbol"] = ":/symbols/multilayer_switch.normal.svg"
|
||||
settings["hover_symbol"] = ":/symbols/multilayer_switch.selected.svg"
|
||||
settings["symbol"] = ":/symbols/multilayer_switch.svg"
|
||||
settings["disk0"] = 1 # adds 1MB disk to store vlan.dat
|
||||
settings["category"] = Node.switches
|
||||
else:
|
||||
settings["auto_delete_disks"] = True
|
||||
|
||||
image_file = os.path.basename(image)
|
||||
if image_file.lower().startswith("c7200p"):
|
||||
@@ -510,4 +499,4 @@ class IOSRouterWizard(QtGui.QWizard, Ui_IOSRouterWizard):
|
||||
if platform not in WIC_MATRIX:
|
||||
# skip the WIC modules page if the platform doesn't support any.
|
||||
return self.uiNetworkAdaptersWizardPage.nextId() + 1
|
||||
return QtGui.QWizard.nextId(self)
|
||||
return QtWidgets.QWizard.nextId(self)
|
||||
|
||||
@@ -41,7 +41,7 @@ class ATMSwitch(Device):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Device.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
self.setStatus(Node.started) # this is an always-on node
|
||||
self._ports = []
|
||||
self._settings = {"name": "",
|
||||
@@ -199,8 +199,8 @@ class ATMSwitch(Device):
|
||||
""".format(name=self.name(),
|
||||
id=self.id(),
|
||||
device_id=self._device_id,
|
||||
host=self._server.host,
|
||||
port=self._server.port)
|
||||
host=self._server.host(),
|
||||
port=self._server.port())
|
||||
|
||||
port_info = ""
|
||||
mapping = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
|
||||
@@ -333,7 +333,7 @@ class ATMSwitch(Device):
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -349,17 +349,7 @@ class ATMSwitch(Device):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/atm_switch.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when this node is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/atm_switch.selected.svg"
|
||||
return ":/symbols/atm_switch.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -34,7 +34,7 @@ class C1700(Router):
|
||||
|
||||
def __init__(self, module, server, project, chassis="1720"):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c1700")
|
||||
super().__init__(module, server, project, platform="c1700")
|
||||
c1700_settings = {"ram": 128,
|
||||
"nvram": 32,
|
||||
"disk0": 0,
|
||||
|
||||
@@ -46,7 +46,7 @@ class C2600(Router):
|
||||
|
||||
def __init__(self, module, server, project, chassis="2610"):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c2600")
|
||||
super().__init__(module, server, project, platform="c2600")
|
||||
c2600_settings = {"ram": 128,
|
||||
"nvram": 128,
|
||||
"disk0": 0,
|
||||
|
||||
@@ -34,7 +34,7 @@ class C2691(Router):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c2691")
|
||||
super().__init__(module, server, project, platform="c2691")
|
||||
c2691_settings = {"ram": 192,
|
||||
"nvram": 112,
|
||||
"disk0": 16,
|
||||
|
||||
@@ -34,7 +34,7 @@ class C3600(Router):
|
||||
|
||||
def __init__(self, module, server, project, chassis="3640"):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c3600")
|
||||
super().__init__(module, server, project, platform="c3600")
|
||||
c3600_settings = {"ram": 192,
|
||||
"nvram": 128,
|
||||
"disk0": 0,
|
||||
|
||||
@@ -34,7 +34,7 @@ class C3725(Router):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c3725")
|
||||
super().__init__(module, server, project, platform="c3725")
|
||||
c3725_settings = {"ram": 128,
|
||||
"nvram": 112,
|
||||
"disk0": 16,
|
||||
|
||||
@@ -34,7 +34,7 @@ class C3745(Router):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c3745")
|
||||
super().__init__(module, server, project, platform="c3745")
|
||||
c3745_settings = {"ram": 256,
|
||||
"nvram": 304,
|
||||
"disk0": 16,
|
||||
|
||||
@@ -34,7 +34,7 @@ class C7200(Router):
|
||||
|
||||
def __init__(self, module, server, project, npe="npe-400"):
|
||||
|
||||
Router.__init__(self, module, server, project, platform="c7200")
|
||||
super().__init__(module, server, project, platform="c7200")
|
||||
c7200_settings = {"ram": 512,
|
||||
"nvram": 128,
|
||||
"disk0": 64,
|
||||
|
||||
@@ -21,6 +21,7 @@ Base class for Device classes.
|
||||
|
||||
|
||||
from gns3.node import Node
|
||||
from gns3.packet_capture import PacketCapture
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -103,7 +104,7 @@ class Device(Node):
|
||||
"""
|
||||
|
||||
if error:
|
||||
log.error("error while adding an UDP NIO for {}: {}".format(self.name(), result["message"]))
|
||||
log.error("error while adding a NIO for {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
self.nio_cancel_signal.emit(self.id())
|
||||
else:
|
||||
@@ -170,13 +171,7 @@ class Device(Node):
|
||||
log.error("error while starting capture {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
else:
|
||||
port = context["port"]
|
||||
log.info("{} has successfully started capturing packets on {}".format(self.name(), port.name()))
|
||||
try:
|
||||
port.startPacketCapture(result["pcap_file_path"])
|
||||
except OSError as e:
|
||||
self.error_signal.emit(self.id(), "could not start the packet capture reader: {}: {}".format(e, e.filename))
|
||||
self.updated_signal.emit()
|
||||
PacketCapture.instance().startCapture(self, context["port"], result["pcap_file_path"])
|
||||
|
||||
def stopPacketCapture(self, port):
|
||||
"""
|
||||
@@ -205,7 +200,4 @@ class Device(Node):
|
||||
log.error("error while stopping capture {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
else:
|
||||
port = context["port"]
|
||||
log.info("{} has successfully stopped capturing packets on {}".format(self.name(), port.name()))
|
||||
port.stopPacketCapture()
|
||||
self.updated_signal.emit()
|
||||
PacketCapture.instance().stopCapture(self, context["port"])
|
||||
|
||||
@@ -40,7 +40,7 @@ class EthernetHub(Device):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Device.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
self.setStatus(Node.started) # this is an always-on node
|
||||
self._ports = []
|
||||
self._settings = {"name": "",
|
||||
@@ -101,7 +101,7 @@ class EthernetHub(Device):
|
||||
ports = new_settings["ports"]
|
||||
for port_number in ports:
|
||||
if port_number not in ports_to_create:
|
||||
ports_to_create.append(port_number)
|
||||
ports_to_create.append(str(port_number))
|
||||
|
||||
for port in self._ports.copy():
|
||||
if port.isFree():
|
||||
@@ -190,8 +190,8 @@ class EthernetHub(Device):
|
||||
""".format(name=self.name(),
|
||||
id=self.id(),
|
||||
device_id=self._device_id,
|
||||
host=self._server.host,
|
||||
port=self._server.port)
|
||||
host=self._server.host(),
|
||||
port=self._server.port())
|
||||
|
||||
port_info = ""
|
||||
for port in self._ports:
|
||||
@@ -279,7 +279,7 @@ class EthernetHub(Device):
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -295,17 +295,7 @@ class EthernetHub(Device):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/hub.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when this node is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/hub.selected.svg"
|
||||
return ":/symbols/hub.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -40,7 +40,7 @@ class EthernetSwitch(Device):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Device.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
self.setStatus(Node.started) # this is an always-on node
|
||||
self._ports = []
|
||||
self._settings = {"name": "",
|
||||
@@ -208,8 +208,8 @@ class EthernetSwitch(Device):
|
||||
""".format(name=self.name(),
|
||||
id=self.id(),
|
||||
device_id=self._device_id,
|
||||
host=self._server.host,
|
||||
port=self._server.port)
|
||||
host=self._server.host(),
|
||||
port=self._server.port())
|
||||
|
||||
port_info = ""
|
||||
for port in self._ports:
|
||||
@@ -311,7 +311,7 @@ class EthernetSwitch(Device):
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -327,17 +327,7 @@ class EthernetSwitch(Device):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/ethernet_switch.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when this node is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/ethernet_switch.selected.svg"
|
||||
return ":/symbols/ethernet_switch.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -35,7 +35,7 @@ class EtherSwitchRouter(Router):
|
||||
"""
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
Router.__init__(self, module, server, project, platform="c3725")
|
||||
super().__init__(module, server, project, platform="c3725")
|
||||
|
||||
self._etherswitch_settings = {"ram": 128,
|
||||
"nvram": 304,
|
||||
@@ -56,17 +56,7 @@ class EtherSwitchRouter(Router):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/multilayer_switch.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when this node is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/multilayer_switch.selected.svg"
|
||||
return ":/symbols/multilayer_switch.svg"
|
||||
|
||||
@staticmethod
|
||||
def categories():
|
||||
|
||||
@@ -40,7 +40,7 @@ class FrameRelaySwitch(Device):
|
||||
|
||||
def __init__(self, module, server, project):
|
||||
|
||||
Device.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
self.setStatus(Node.started) # this is an always-on node
|
||||
self._ports = []
|
||||
self._settings = {"name": "",
|
||||
@@ -201,8 +201,8 @@ class FrameRelaySwitch(Device):
|
||||
""".format(name=self.name(),
|
||||
id=self.id(),
|
||||
device_id=self._device_id,
|
||||
host=self._server.host,
|
||||
port=self._server.port)
|
||||
host=self._server.host(),
|
||||
port=self._server.port())
|
||||
|
||||
port_info = ""
|
||||
for port in self._ports:
|
||||
@@ -315,7 +315,7 @@ class FrameRelaySwitch(Device):
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -331,17 +331,7 @@ class FrameRelaySwitch(Device):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/frame_relay_switch.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when this node is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/frame_relay_switch.selected.svg"
|
||||
return ":/symbols/frame_relay_switch.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
@@ -26,7 +26,9 @@ from gns3.vm import VM
|
||||
from gns3.node import Node
|
||||
from gns3.ports.port import Port
|
||||
from gns3.servers import Servers
|
||||
from gns3.packet_capture import PacketCapture
|
||||
from gns3.utils.normalize_filename import normalize_filename
|
||||
from gns3.image_manager import ImageManager
|
||||
|
||||
from ..settings import PLATFORMS_DEFAULT_RAM
|
||||
from ..adapters import ADAPTER_MATRIX
|
||||
@@ -51,13 +53,13 @@ class Router(VM):
|
||||
|
||||
def __init__(self, module, server, project, platform="c7200"):
|
||||
|
||||
VM.__init__(self, module, server, project)
|
||||
super().__init__(module, server, project)
|
||||
log.info("Router {} is being created".format(platform))
|
||||
self._ports = []
|
||||
self._dynamips_id = None
|
||||
self._settings = {"name": "",
|
||||
"platform": platform,
|
||||
"image": "",
|
||||
"image_md5sum": "",
|
||||
"startup_config": "",
|
||||
"private_config": "",
|
||||
"ram": 128,
|
||||
@@ -71,6 +73,7 @@ class Router(VM):
|
||||
"exec_area": 64,
|
||||
"disk0": 0,
|
||||
"disk1": 0,
|
||||
"auto_delete_disks": False,
|
||||
"console": None,
|
||||
"aux": None,
|
||||
"mac_addr": None,
|
||||
@@ -281,23 +284,11 @@ class Router(VM):
|
||||
:param error: indicates an error (boolean)
|
||||
"""
|
||||
|
||||
if error:
|
||||
log.error("error while setting up {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
if not super()._setupCallback(result, error=error, **kwargs):
|
||||
return
|
||||
|
||||
self._vm_id = result["vm_id"]
|
||||
self._dynamips_id = result["dynamips_id"]
|
||||
|
||||
# update the settings using the defaults sent by the server
|
||||
for name, value in result.items():
|
||||
if name in self._settings and self._settings[name] != value:
|
||||
log.info("Router {} setting up and updating {} from '{}' to '{}'".format(self.name(),
|
||||
name,
|
||||
self._settings[name],
|
||||
value))
|
||||
self._settings[name] = value
|
||||
|
||||
# create the ports on the client side
|
||||
self._insertAdapters(self._settings)
|
||||
|
||||
@@ -309,6 +300,10 @@ class Router(VM):
|
||||
self.created_signal.emit(self.id())
|
||||
self._module.addNode(self)
|
||||
|
||||
# The image is missing on remote server
|
||||
if "image_md5sum" not in result or result["image_md5sum"] is None or len(result["image_md5sum"]) == 0:
|
||||
ImageManager.instance().addMissingImage(result["image"], self._server, "DYNAMIPS")
|
||||
|
||||
def update(self, new_settings):
|
||||
"""
|
||||
Updates the settings for this router.
|
||||
@@ -453,13 +448,7 @@ class Router(VM):
|
||||
log.error("error while starting capture {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
else:
|
||||
port = context["port"]
|
||||
log.info("{} has successfully started capturing packets on {}".format(self.name(), port.name()))
|
||||
try:
|
||||
port.startPacketCapture(result["pcap_file_path"])
|
||||
except OSError as e:
|
||||
self.error_signal.emit(self.id(), "could not start the packet capture reader: {}: {}".format(e, e.filename))
|
||||
self.updated_signal.emit()
|
||||
PacketCapture.instance().startCapture(self, context["port"], result["pcap_file_path"])
|
||||
|
||||
def stopPacketCapture(self, port):
|
||||
"""
|
||||
@@ -488,10 +477,7 @@ class Router(VM):
|
||||
log.error("error while stopping capture {}: {}".format(self.name(), result["message"]))
|
||||
self.server_error_signal.emit(self.id(), result["message"])
|
||||
else:
|
||||
port = context["port"]
|
||||
log.info("{} has successfully stopped capturing packets on {}".format(self.name(), port.name()))
|
||||
port.stopPacketCapture()
|
||||
self.updated_signal.emit()
|
||||
PacketCapture.instance().stopCapture(self, context["port"])
|
||||
|
||||
def computeIdlepcs(self, callback):
|
||||
"""
|
||||
@@ -658,8 +644,8 @@ class Router(VM):
|
||||
specific_info=router_specific_info,
|
||||
ram=self._settings["ram"],
|
||||
nvram=self._settings["nvram"],
|
||||
host=self._server.host,
|
||||
port=self._server.port,
|
||||
host=self._server.host(),
|
||||
port=self._server.port(),
|
||||
console=self._settings["console"],
|
||||
aux=self._settings["aux"],
|
||||
image_name=os.path.basename(self._settings["image"]),
|
||||
@@ -700,15 +686,6 @@ class Router(VM):
|
||||
|
||||
return router
|
||||
|
||||
def _imageFilesDir(self):
|
||||
"""
|
||||
Returns the location of IOS images.
|
||||
"""
|
||||
|
||||
servers = Servers.instance()
|
||||
local_server = servers.localServerSettings()
|
||||
return os.path.join(local_server["images_path"], "IOS")
|
||||
|
||||
def load(self, node_info):
|
||||
"""
|
||||
Loads a router representation
|
||||
@@ -733,7 +710,7 @@ class Router(VM):
|
||||
|
||||
if self.server().isLocal():
|
||||
# check and update the path to use the image in the images directory
|
||||
updated_image_path = os.path.join(self._imageFilesDir(), image)
|
||||
updated_image_path = os.path.join(ImageManager.instance().getDirectoryForType("DYNAMIPS"), image)
|
||||
if os.path.isfile(updated_image_path):
|
||||
image = updated_image_path
|
||||
elif not os.path.isfile(image):
|
||||
@@ -967,7 +944,7 @@ class Router(VM):
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node configurator.
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
:returns: QWidget object
|
||||
"""
|
||||
@@ -1000,17 +977,7 @@ class Router(VM):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/router.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
"""
|
||||
Returns the symbol to use when the router is hovered.
|
||||
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/router.selected.svg"
|
||||
return ":/symbols/router.svg"
|
||||
|
||||
@staticmethod
|
||||
def categories():
|
||||
|
||||
@@ -20,11 +20,11 @@ Configuration page for Dynamips ATM bridges.
|
||||
"""
|
||||
|
||||
import re
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.atm_bridge_configuration_page_ui import Ui_atmBridgeConfigPageWidget
|
||||
|
||||
|
||||
class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
class ATMBridgeConfigurationPage(QtWidgets.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for ATM bridges.
|
||||
@@ -32,7 +32,7 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self._mapping = {}
|
||||
|
||||
@@ -91,7 +91,7 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
atm_vci = self.uiATMVCISpinBox.value()
|
||||
|
||||
if ethernet_port == atm_port:
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "Same source and destination ports")
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "Same source and destination ports")
|
||||
return
|
||||
|
||||
destination = "{port}:{vpi}:{vci}".format(port=atm_port,
|
||||
@@ -99,10 +99,10 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
vci=atm_vci)
|
||||
|
||||
if destination in self._mapping:
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
return
|
||||
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, str(ethernet_port))
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -125,7 +125,7 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if (node_port.portNumber() == ethernet_port or node_port.portNumber() == atm_port) and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
return
|
||||
|
||||
del self.mapping[ethernet_port]
|
||||
@@ -150,7 +150,7 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
self._node = node
|
||||
|
||||
for ethernet_port, destination in settings["mappings"].items():
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, ethernet_port)
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -172,7 +172,7 @@ class ATMBridgeConfigurationPage(QtGui.QWidget, Ui_atmBridgeConfigPageWidget):
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "ATM bridge name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "ATM bridge name cannot be empty!")
|
||||
else:
|
||||
settings["name"] = name
|
||||
else:
|
||||
|
||||
@@ -20,11 +20,11 @@ Configuration page for Dynamips ATM switches.
|
||||
"""
|
||||
|
||||
import re
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.atm_switch_configuration_page_ui import Ui_atmSwitchConfigPageWidget
|
||||
|
||||
|
||||
class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
class ATMSwitchConfigurationPage(QtWidgets.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for ATM switches.
|
||||
@@ -32,7 +32,7 @@ class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self._mapping = {}
|
||||
|
||||
@@ -116,10 +116,10 @@ class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
destination = "{port}:{vpi}".format(port=destination_port, vpi=destination_vpi)
|
||||
|
||||
if source in self._mapping or destination in self._mapping:
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
return
|
||||
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, source)
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -145,7 +145,7 @@ class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if (node_port.portNumber() == source_port or node_port.portNumber() == destination_port) and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
return
|
||||
|
||||
del self._mapping[source]
|
||||
@@ -170,7 +170,7 @@ class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
self._node = node
|
||||
|
||||
for source, destination in settings["mappings"].items():
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, source)
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -192,7 +192,7 @@ class ATMSwitchConfigurationPage(QtGui.QWidget, Ui_atmSwitchConfigPageWidget):
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "ATM switch name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "ATM switch name cannot be empty!")
|
||||
else:
|
||||
settings["name"] = name
|
||||
else:
|
||||
|
||||
@@ -21,14 +21,14 @@ Configuration page for Dynamips preferences.
|
||||
|
||||
import os
|
||||
import sys
|
||||
from gns3.qt import QtGui
|
||||
from gns3.servers import Servers
|
||||
import shutil
|
||||
from gns3.qt import QtWidgets
|
||||
from .. import Dynamips
|
||||
from ..ui.dynamips_preferences_page_ui import Ui_DynamipsPreferencesPageWidget
|
||||
from ..settings import DYNAMIPS_SETTINGS
|
||||
|
||||
|
||||
class DynamipsPreferencesPage(QtGui.QWidget, Ui_DynamipsPreferencesPageWidget):
|
||||
class DynamipsPreferencesPage(QtWidgets.QWidget, Ui_DynamipsPreferencesPageWidget):
|
||||
|
||||
"""
|
||||
QWidget preference page for Dynamips.
|
||||
@@ -36,7 +36,7 @@ class DynamipsPreferencesPage(QtGui.QWidget, Ui_DynamipsPreferencesPageWidget):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
# connect signals
|
||||
@@ -53,15 +53,32 @@ class DynamipsPreferencesPage(QtGui.QWidget, Ui_DynamipsPreferencesPageWidget):
|
||||
file_filter = ""
|
||||
if sys.platform.startswith("win"):
|
||||
file_filter = "Executable (*.exe);;All files (*.*)"
|
||||
path = QtGui.QFileDialog.getOpenFileName(self, "Select Dynamips", ".", file_filter)
|
||||
|
||||
dynamips_path = shutil.which("dynamips")
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select Dynamips", dynamips_path, file_filter)
|
||||
if not path:
|
||||
return
|
||||
|
||||
if not os.access(path, os.X_OK):
|
||||
QtGui.QMessageBox.critical(self, "Dynamips", "{} is not an executable".format(os.path.basename(path)))
|
||||
return
|
||||
if self._checkDynamipsPath(path):
|
||||
self.uiDynamipsPathLineEdit.setText(path)
|
||||
|
||||
self.uiDynamipsPathLineEdit.setText(path)
|
||||
def _checkDynamipsPath(self, path):
|
||||
"""
|
||||
Checks that the Dynamips path is valid.
|
||||
|
||||
:param path: Dynamips path
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
if not os.path.exists(path):
|
||||
QtWidgets.QMessageBox.critical(self, "Dynamips", '"{}" does not exist'.format(path))
|
||||
return False
|
||||
|
||||
if not os.access(path, os.X_OK):
|
||||
QtWidgets.QMessageBox.critical(self, "Dynamips", "{} is not an executable".format(os.path.basename(path)))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _ghostIOSSupportSlot(self, state):
|
||||
"""
|
||||
@@ -128,11 +145,15 @@ class DynamipsPreferencesPage(QtGui.QWidget, Ui_DynamipsPreferencesPageWidget):
|
||||
Saves the Dynamips preferences.
|
||||
"""
|
||||
|
||||
new_settings = {}
|
||||
new_settings["dynamips_path"] = self.uiDynamipsPathLineEdit.text()
|
||||
new_settings["allocate_aux_console_ports"] = self.uiAllocateAuxConsolePortsCheckBox.isChecked()
|
||||
new_settings["use_local_server"] = self.uiUseLocalServercheckBox.isChecked()
|
||||
new_settings["ghost_ios_support"] = self.uiGhostIOSSupportCheckBox.isChecked()
|
||||
new_settings["mmap_support"] = self.uiMmapSupportCheckBox.isChecked()
|
||||
new_settings["sparse_memory_support"] = self.uiSparseMemorySupportCheckBox.isChecked()
|
||||
dynamips_path = self.uiDynamipsPathLineEdit.text().strip()
|
||||
if dynamips_path and self.uiUseLocalServercheckBox.isChecked() and not self._checkDynamipsPath(dynamips_path):
|
||||
return
|
||||
|
||||
new_settings = {"dynamips_path": dynamips_path,
|
||||
"allocate_aux_console_ports": self.uiAllocateAuxConsolePortsCheckBox.isChecked(),
|
||||
"use_local_server": self.uiUseLocalServercheckBox.isChecked(),
|
||||
"ghost_ios_support": self.uiGhostIOSSupportCheckBox.isChecked(),
|
||||
"mmap_support": self.uiMmapSupportCheckBox.isChecked(),
|
||||
"sparse_memory_support": self.uiSparseMemorySupportCheckBox.isChecked()}
|
||||
|
||||
Dynamips.instance().setSettings(new_settings)
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
Configuration page for Dynamips Ethernet hubs.
|
||||
"""
|
||||
|
||||
from gns3.qt import QtGui
|
||||
from gns3.dialogs.node_configurator_dialog import ConfigurationError
|
||||
from gns3.qt import QtWidgets
|
||||
from gns3.dialogs.node_properties_dialog import ConfigurationError
|
||||
from ..ui.ethernet_hub_configuration_page_ui import Ui_ethernetHubConfigPageWidget
|
||||
|
||||
|
||||
class EthernetHubConfigurationPage(QtGui.QWidget, Ui_ethernetHubConfigPageWidget):
|
||||
class EthernetHubConfigurationPage(QtWidgets.QWidget, Ui_ethernetHubConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for Ethernet hubs.
|
||||
@@ -32,7 +32,7 @@ class EthernetHubConfigurationPage(QtGui.QWidget, Ui_ethernetHubConfigPageWidget
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
def loadSettings(self, settings, node, group=False):
|
||||
@@ -66,7 +66,7 @@ class EthernetHubConfigurationPage(QtGui.QWidget, Ui_ethernetHubConfigPageWidget
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "Ethernet hub name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Ethernet hub name cannot be empty!")
|
||||
else:
|
||||
settings["name"] = name
|
||||
else:
|
||||
@@ -80,7 +80,7 @@ class EthernetHubConfigurationPage(QtGui.QWidget, Ui_ethernetHubConfigPageWidget
|
||||
for port in ports:
|
||||
if not port.isFree() and port.portNumber() > nbports:
|
||||
self.loadSettings(settings, node)
|
||||
QtGui.QMessageBox.critical(self, node.name(), "A link is connected to port {}, please remove it first".format(port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, node.name(), "A link is connected to port {}, please remove it first".format(port.name()))
|
||||
raise ConfigurationError()
|
||||
|
||||
settings["ports"] = []
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
Configuration page for Dynamips Ethernet switches.
|
||||
"""
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from ..utils.tree_widget_item import TreeWidgetItem
|
||||
from ..ui.ethernet_switch_configuration_page_ui import Ui_ethernetSwitchConfigPageWidget
|
||||
|
||||
|
||||
class EthernetSwitchConfigurationPage(QtGui.QWidget, Ui_ethernetSwitchConfigPageWidget):
|
||||
class EthernetSwitchConfigurationPage(QtWidgets.QWidget, Ui_ethernetSwitchConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for Ethernet switches.
|
||||
@@ -32,7 +32,7 @@ class EthernetSwitchConfigurationPage(QtGui.QWidget, Ui_ethernetSwitchConfigPage
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self._ports = {}
|
||||
|
||||
@@ -114,7 +114,7 @@ class EthernetSwitchConfigurationPage(QtGui.QWidget, Ui_ethernetSwitchConfigPage
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if node_port.portNumber() == port and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
return
|
||||
del self._ports[port]
|
||||
self.uiPortsTreeWidget.takeTopLevelItem(self.uiPortsTreeWidget.indexOfTopLevelItem(item))
|
||||
@@ -168,7 +168,7 @@ class EthernetSwitchConfigurationPage(QtGui.QWidget, Ui_ethernetSwitchConfigPage
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "Ethernet switch name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Ethernet switch name cannot be empty!")
|
||||
else:
|
||||
settings["name"] = name
|
||||
else:
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
Configuration page for Dynamips Frame Relay switches.
|
||||
"""
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from ..ui.frame_relay_switch_configuration_page_ui import Ui_frameRelaySwitchConfigPageWidget
|
||||
|
||||
|
||||
class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfigPageWidget):
|
||||
class FrameRelaySwitchConfigurationPage(QtWidgets.QWidget, Ui_frameRelaySwitchConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for Frame Relay switches.
|
||||
@@ -31,7 +31,7 @@ class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfig
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self._mapping = {}
|
||||
|
||||
@@ -82,17 +82,17 @@ class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfig
|
||||
destination_dlci = self.uiDestinationDLCISpinBox.value()
|
||||
|
||||
if source_port == destination_port:
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "Same source and destination ports")
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "Same source and destination ports")
|
||||
return
|
||||
|
||||
source = "{port}:{dlci}".format(port=source_port, dlci=source_dlci)
|
||||
destination = "{port}:{dlci}".format(port=destination_port, dlci=destination_dlci)
|
||||
|
||||
if source in self._mapping or destination in self._mapping:
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "Mapping already defined")
|
||||
return
|
||||
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, source)
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -120,7 +120,7 @@ class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfig
|
||||
node_ports = self._node.ports()
|
||||
for node_port in node_ports:
|
||||
if (node_port.portNumber() == source_port or node_port.portNumber() == destination_port) and not node_port.isFree():
|
||||
QtGui.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
QtWidgets.QMessageBox.critical(self, self._node.name(), "A link is connected to port {}, please remove it first".format(node_port.name()))
|
||||
return
|
||||
|
||||
del self._mapping[source]
|
||||
@@ -145,7 +145,7 @@ class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfig
|
||||
self._node = node
|
||||
|
||||
for source, destination in settings["mappings"].items():
|
||||
item = QtGui.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiMappingTreeWidget)
|
||||
item.setText(0, source)
|
||||
item.setText(1, destination)
|
||||
self.uiMappingTreeWidget.addTopLevelItem(item)
|
||||
@@ -167,7 +167,7 @@ class FrameRelaySwitchConfigurationPage(QtGui.QWidget, Ui_frameRelaySwitchConfig
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "Frame relay switch name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Frame relay switch name cannot be empty!")
|
||||
else:
|
||||
settings["name"] = name
|
||||
else:
|
||||
|
||||
@@ -22,13 +22,16 @@ Configuration page for Dynamips IOS routers.
|
||||
import os
|
||||
import re
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.dialogs.node_configurator_dialog import ConfigurationError
|
||||
from gns3.servers import Servers
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from gns3.dialogs.node_properties_dialog import ConfigurationError
|
||||
from gns3.dialogs.symbol_selection_dialog import SymbolSelectionDialog
|
||||
from gns3.node import Node
|
||||
from ..ui.ios_router_configuration_page_ui import Ui_iosRouterConfigPageWidget
|
||||
from ..settings import CHASSIS, ADAPTER_MATRIX, WIC_MATRIX
|
||||
|
||||
|
||||
class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
class IOSRouterConfigurationPage(QtWidgets.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
|
||||
"""
|
||||
QWidget configuration page for IOS routers.
|
||||
@@ -36,7 +39,7 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
self._widget_slots = {0: self.uiSlot0comboBox,
|
||||
@@ -53,14 +56,20 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
|
||||
self.uiStartupConfigToolButton.clicked.connect(self._startupConfigBrowserSlot)
|
||||
self.uiPrivateConfigToolButton.clicked.connect(self._privateConfigBrowserSlot)
|
||||
self.uiSymbolToolButton.clicked.connect(self._symbolBrowserSlot)
|
||||
self.uiIOSImageToolButton.clicked.connect(self._iosImageBrowserSlot)
|
||||
|
||||
self._server = None
|
||||
self._idle_valid = False
|
||||
idle_pc_rgx = QtCore.QRegExp("^(0x[0-9a-fA-F]{8})?$")
|
||||
validator = QtGui.QRegExpValidator(idle_pc_rgx, self)
|
||||
self.uiIdlepcLineEdit.setValidator(validator)
|
||||
self.uiIdlepcLineEdit.textChanged.connect(self._idlePCValidateSlot)
|
||||
self.uiIdlepcLineEdit.textChanged.emit(self.uiIdlepcLineEdit.text())
|
||||
self._default_configs_dir = Servers.instance().localServerSettings()["configs_path"]
|
||||
|
||||
# add the categories
|
||||
for name, category in Node.defaultCategories().items():
|
||||
self.uiCategoryComboBox.addItem(name, category)
|
||||
|
||||
def _idlePCValidateSlot(self):
|
||||
"""
|
||||
@@ -82,11 +91,11 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
|
||||
def _iosImageBrowserSlot(self):
|
||||
"""
|
||||
Slot to open a file browser and select an IOU image.
|
||||
Slot to open a file browser and select an IOS image.
|
||||
"""
|
||||
|
||||
from ..pages.ios_router_preferences_page import IOSRouterPreferencesPage
|
||||
path = IOSRouterPreferencesPage.getIOSImage(self)
|
||||
path = IOSRouterPreferencesPage.getIOSImage(self, self._server)
|
||||
if not path:
|
||||
return
|
||||
self.uiIOSImageLineEdit.clear()
|
||||
@@ -96,7 +105,7 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
image = os.path.basename(path)
|
||||
match = re.match("^(c[0-9]+)\\-\w+", image)
|
||||
if not match:
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
|
||||
return
|
||||
|
||||
detected_platform = match.group(1)
|
||||
@@ -112,23 +121,23 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
chassis = self.uiChassisTextLabel.text()
|
||||
|
||||
if detected_platform != platform:
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "Using an IOS image made for another platform will likely not work!")
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "Using an IOS image made for another platform will likely not work!")
|
||||
|
||||
if detected_chassis and chassis and detected_chassis != chassis:
|
||||
QtGui.QMessageBox.warning(self, "IOS image", "Using an IOS image made for another chassis will likely not work!")
|
||||
QtWidgets.QMessageBox.warning(self, "IOS image", "Using an IOS image made for another chassis will likely not work!")
|
||||
|
||||
def _startupConfigBrowserSlot(self):
|
||||
"""
|
||||
Slot to open a file browser and select a startup-config file.
|
||||
"""
|
||||
|
||||
config_dir = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), "base_configs")
|
||||
path = QtGui.QFileDialog.getOpenFileName(self, "Select a startup configuration", config_dir)
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select a startup configuration", self._default_configs_dir)
|
||||
if not path:
|
||||
return
|
||||
|
||||
self._default_configs_dir = os.path.dirname(path)
|
||||
if not os.access(path, os.R_OK):
|
||||
QtGui.QMessageBox.critical(self, "Startup configuration", "Cannot read {}".format(path))
|
||||
QtWidgets.QMessageBox.critical(self, "Startup configuration", "Cannot read {}".format(path))
|
||||
return
|
||||
|
||||
self.uiStartupConfigLineEdit.clear()
|
||||
@@ -139,18 +148,31 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
Slot to open a file browser and select a private-config file.
|
||||
"""
|
||||
|
||||
config_dir = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), "base_configs")
|
||||
path = QtGui.QFileDialog.getOpenFileName(self, "Select a private configuration", config_dir)
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select a private configuration", self._default_configs_dir)
|
||||
if not path:
|
||||
return
|
||||
|
||||
self._default_configs_dir = os.path.dirname(path)
|
||||
if not os.access(path, os.R_OK):
|
||||
QtGui.QMessageBox.critical(self, "Private configuration", "Cannot read {}".format(path))
|
||||
QtWidgets.QMessageBox.critical(self, "Private configuration", "Cannot read {}".format(path))
|
||||
return
|
||||
|
||||
self.uiPrivateConfigLineEdit.clear()
|
||||
self.uiPrivateConfigLineEdit.setText(path)
|
||||
|
||||
def _symbolBrowserSlot(self):
|
||||
"""
|
||||
Slot to open the symbol browser and select a new symbol.
|
||||
"""
|
||||
|
||||
symbol_path = self.uiSymbolLineEdit.text()
|
||||
dialog = SymbolSelectionDialog(self, symbol=symbol_path)
|
||||
dialog.show()
|
||||
if dialog.exec_():
|
||||
new_symbol_path = dialog.getSymbol()
|
||||
self.uiSymbolLineEdit.setText(new_symbol_path)
|
||||
self.uiSymbolLineEdit.setToolTip('<img src="{}"/>'.format(new_symbol_path))
|
||||
|
||||
def _loadAdapterConfig(self, platform, chassis, settings):
|
||||
"""
|
||||
Loads the adapter and WIC configuration.
|
||||
@@ -214,6 +236,11 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
:param group: indicates the settings apply to a group of routers
|
||||
"""
|
||||
|
||||
if node:
|
||||
self._server = node.server()
|
||||
else:
|
||||
self._server = Servers.instance().getServerFromString(settings["server"])
|
||||
|
||||
if not group:
|
||||
self.uiNameLineEdit.setText(settings["name"])
|
||||
|
||||
@@ -234,11 +261,6 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
|
||||
# load the MAC address setting
|
||||
self.uiBaseMACLineEdit.setInputMask("HHHH.HHHH.HHHH;_")
|
||||
|
||||
# regexp = QtCore.QRegExp("([0-9a-fA-F]{4}\.){2}[0-9a-fA-F]{4}")
|
||||
# validator = QtGui.QRegExpValidator(regexp)
|
||||
# self.uiBaseMACLineEdit.setValidator(validator)
|
||||
|
||||
if settings["mac_addr"]:
|
||||
self.uiBaseMACLineEdit.setText(settings["mac_addr"])
|
||||
else:
|
||||
@@ -261,8 +283,18 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
if not node:
|
||||
# load the startup-config
|
||||
self.uiStartupConfigLineEdit.setText(settings["startup_config"])
|
||||
|
||||
# load the private-config
|
||||
self.uiPrivateConfigLineEdit.setText(settings["private_config"])
|
||||
|
||||
# load the symbol
|
||||
self.uiSymbolLineEdit.setText(settings["symbol"])
|
||||
self.uiSymbolLineEdit.setToolTip('<img src="{}"/>'.format(settings["symbol"]))
|
||||
|
||||
# load the category
|
||||
index = self.uiCategoryComboBox.findData(settings["category"])
|
||||
if index != -1:
|
||||
self.uiCategoryComboBox.setCurrentIndex(index)
|
||||
else:
|
||||
self.uiStartupConfigLabel.hide()
|
||||
self.uiStartupConfigLineEdit.hide()
|
||||
@@ -270,6 +302,12 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
self.uiPrivateConfigLabel.hide()
|
||||
self.uiPrivateConfigLineEdit.hide()
|
||||
self.uiPrivateConfigToolButton.hide()
|
||||
self.uiSymbolLabel.hide()
|
||||
self.uiSymbolLineEdit.hide()
|
||||
self.uiSymbolToolButton.hide()
|
||||
self.uiCategoryComboBox.hide()
|
||||
self.uiCategoryLabel.hide()
|
||||
self.uiCategoryComboBox.hide()
|
||||
|
||||
# show the platform and chassis if applicable
|
||||
platform = settings["platform"]
|
||||
@@ -338,6 +376,7 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
self.uiNvramSpinBox.setValue(settings["nvram"])
|
||||
self.uiDisk0SpinBox.setValue(settings["disk0"])
|
||||
self.uiDisk1SpinBox.setValue(settings["disk1"])
|
||||
self.uiAutoDeleteCheckBox.setChecked(settings["auto_delete_disks"])
|
||||
|
||||
# load all the slots with configured adapters
|
||||
self._loadAdapterConfig(platform, chassis, settings)
|
||||
@@ -398,8 +437,8 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
index = self._widget_slots[slot_number].findText(adapter)
|
||||
if index != -1:
|
||||
self._widget_slots[slot_number].setCurrentIndex(index)
|
||||
QtGui.QMessageBox.critical(self, node.name(), "A link is connected to port {} on adapter {}, please remove it first".format(node_port.name(),
|
||||
adapter))
|
||||
QtWidgets.QMessageBox.critical(self, node.name(), "A link is connected to port {} on adapter {}, please remove it first".format(node_port.name(),
|
||||
adapter))
|
||||
raise ConfigurationError()
|
||||
|
||||
def _checkForLinkConnectedToWIC(self, wic_number, settings, node):
|
||||
@@ -419,8 +458,8 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
index = self._widget_wics[wic_number].findText(wic)
|
||||
if index != -1:
|
||||
self._widget_wics[wic_number].setCurrentIndex(index)
|
||||
QtGui.QMessageBox.critical(self, node.name(), "A link is connected to port {} on {}, please remove it first".format(node_port.name(),
|
||||
wic))
|
||||
QtWidgets.QMessageBox.critical(self, node.name(), "A link is connected to port {} on {}, please remove it first".format(node_port.name(),
|
||||
wic))
|
||||
raise ConfigurationError()
|
||||
|
||||
def saveSettings(self, settings, node=None, group=False):
|
||||
@@ -437,15 +476,15 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
# Check if the Idle-PC value has been validated okay
|
||||
if not self._idle_valid:
|
||||
idle_pc = self.uiIdlepcLineEdit.text()
|
||||
QtGui.QMessageBox.critical(self, "Idle-PC", "{} is not a valid Idle-PC value ".format(idle_pc))
|
||||
QtWidgets.QMessageBox.critical(self, "Idle-PC", "{} is not a valid Idle-PC value ".format(idle_pc))
|
||||
raise ConfigurationError()
|
||||
|
||||
# set the device name
|
||||
name = self.uiNameLineEdit.text()
|
||||
if not name:
|
||||
QtGui.QMessageBox.critical(self, "Name", "IOS router name cannot be empty!")
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "IOS router name cannot be empty!")
|
||||
elif node and not node.validateHostname(name):
|
||||
QtGui.QMessageBox.critical(self, "Name", "Invalid name detected for IOS router: {}".format(name))
|
||||
QtWidgets.QMessageBox.critical(self, "Name", "Invalid name detected for IOS router: {}".format(name))
|
||||
else:
|
||||
settings["name"] = name
|
||||
|
||||
@@ -456,11 +495,14 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
settings["aux"] = aux
|
||||
|
||||
# check and save the base MAC address
|
||||
# mac = self.uiBaseMACLineEdit.text()
|
||||
# if mac and not re.search(r"""^([0-9a-fA-F]{4}\.){2}[0-9a-fA-F]{4}$""", mac):
|
||||
# QtGui.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hhhh.hhhh.hhhh)")
|
||||
# elif mac != "":
|
||||
# settings["mac_addr"] = mac
|
||||
mac = self.uiBaseMACLineEdit.text()
|
||||
if mac != "..":
|
||||
if not re.search(r"""^([0-9a-fA-F]{4}\.){2}[0-9a-fA-F]{4}$""", mac):
|
||||
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hhhh.hhhh.hhhh)")
|
||||
else:
|
||||
settings["mac_addr"] = mac
|
||||
elif not node:
|
||||
settings["mac_addr"] = ""
|
||||
|
||||
# save the IOS image path
|
||||
settings["image"] = self.uiIOSImageLineEdit.text()
|
||||
@@ -484,7 +526,7 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
if os.access(startup_config, os.R_OK):
|
||||
settings["startup_config"] = startup_config
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self, "Startup-config", "Cannot read the startup-config file")
|
||||
QtWidgets.QMessageBox.critical(self, "Startup-config", "Cannot read the startup-config file")
|
||||
|
||||
private_config = self.uiPrivateConfigLineEdit.text().strip()
|
||||
if not private_config:
|
||||
@@ -493,7 +535,16 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
if os.access(private_config, os.R_OK):
|
||||
settings["private_config"] = private_config
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self, "Private-config", "Cannot read the private-config file")
|
||||
QtWidgets.QMessageBox.critical(self, "Private-config", "Cannot read the private-config file")
|
||||
|
||||
symbol_path = self.uiSymbolLineEdit.text()
|
||||
pixmap = QtGui.QPixmap(symbol_path)
|
||||
if pixmap.isNull():
|
||||
QtWidgets.QMessageBox.critical(self, "Symbol", "Invalid file or format not supported")
|
||||
else:
|
||||
settings["symbol"] = symbol_path
|
||||
|
||||
settings["category"] = self.uiCategoryComboBox.itemData(self.uiCategoryComboBox.currentIndex())
|
||||
|
||||
# get the platform and chassis if applicable
|
||||
platform = settings["platform"]
|
||||
@@ -533,6 +584,7 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
settings["nvram"] = self.uiNvramSpinBox.value()
|
||||
settings["disk0"] = self.uiDisk0SpinBox.value()
|
||||
settings["disk1"] = self.uiDisk1SpinBox.value()
|
||||
settings["auto_delete_disks"] = self.uiAutoDeleteCheckBox.isChecked()
|
||||
|
||||
# save the system ID (processor board ID in IOS) setting
|
||||
settings["system_id"] = self.uiSystemIdLineEdit.text()
|
||||
@@ -541,7 +593,6 @@ class IOSRouterConfigurationPage(QtGui.QWidget, Ui_iosRouterConfigPageWidget):
|
||||
settings["exec_area"] = self.uiExecAreaSpinBox.value()
|
||||
|
||||
# save the Idle-PC setting
|
||||
# TODO: check the format?
|
||||
settings["idlepc"] = self.uiIdlepcLineEdit.text()
|
||||
|
||||
# save the idlemax setting
|
||||
|
||||
@@ -26,13 +26,11 @@ import math
|
||||
import zipfile
|
||||
import logging
|
||||
|
||||
from gns3.qt import QtCore, QtGui
|
||||
from gns3.qt import QtCore, QtGui, QtWidgets
|
||||
from gns3.main_window import MainWindow
|
||||
from gns3.dialogs.symbol_selection_dialog import SymbolSelectionDialog
|
||||
from gns3.dialogs.configuration_dialog import ConfigurationDialog
|
||||
from gns3.cloud.utils import UploadFilesThread
|
||||
from gns3.utils.progress_dialog import ProgressDialog
|
||||
from gns3.utils.file_copy_worker import FileCopyWorker
|
||||
from gns3.image_manager import ImageManager
|
||||
|
||||
from .. import Dynamips
|
||||
from ..settings import IOS_ROUTER_SETTINGS
|
||||
@@ -46,14 +44,16 @@ from ..dialogs.ios_router_wizard import IOSRouterWizard
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget):
|
||||
class IOSRouterPreferencesPage(QtWidgets.QWidget, Ui_IOSRouterPreferencesPageWidget):
|
||||
|
||||
"""
|
||||
QWidget preference page for IOS routers.
|
||||
"""
|
||||
|
||||
_default_images_dir = ""
|
||||
|
||||
def __init__(self):
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
self._main_window = MainWindow.instance()
|
||||
@@ -63,28 +63,26 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
self.uiNewIOSRouterPushButton.clicked.connect(self._iosRouterNewSlot)
|
||||
self.uiEditIOSRouterPushButton.clicked.connect(self._iosRouterEditSlot)
|
||||
self.uiDeleteIOSRouterPushButton.clicked.connect(self._iosRouterDeleteSlot)
|
||||
self.uiIOSRoutersTreeWidget.currentItemChanged.connect(self._iosRouterChangedSlot)
|
||||
self.uiIOSRoutersTreeWidget.itemPressed.connect(self._iosRouterPressedSlot)
|
||||
self.uiIOSRoutersTreeWidget.itemSelectionChanged.connect(self._iosRouterChangedSlot)
|
||||
self.uiDecompressIOSPushButton.clicked.connect(self._decompressIOSSlot)
|
||||
|
||||
def _iosRouterChangedSlot(self, current, previous):
|
||||
def _iosRouterChangedSlot(self):
|
||||
"""
|
||||
Loads a selected an IOS router from the tree widget.
|
||||
|
||||
:param current: current QTreeWidgetItem instance
|
||||
:param previous: ignored
|
||||
"""
|
||||
|
||||
if not current:
|
||||
self.uiIOSRouterInfoTreeWidget.clear()
|
||||
return
|
||||
selection = self.uiIOSRoutersTreeWidget.selectedItems()
|
||||
self.uiDeleteIOSRouterPushButton.setEnabled(len(selection) != 0)
|
||||
single_selected = len(selection) == 1
|
||||
self.uiEditIOSRouterPushButton.setEnabled(single_selected)
|
||||
self.uiDecompressIOSPushButton.setEnabled(single_selected)
|
||||
|
||||
self.uiEditIOSRouterPushButton.setEnabled(True)
|
||||
self.uiDeleteIOSRouterPushButton.setEnabled(True)
|
||||
self.uiDecompressIOSPushButton.setEnabled(True)
|
||||
key = current.data(0, QtCore.Qt.UserRole)
|
||||
ios_router = self._ios_routers[key]
|
||||
self._refreshInfo(ios_router)
|
||||
if single_selected:
|
||||
key = selection[0].data(0, QtCore.Qt.UserRole)
|
||||
ios_router = self._ios_routers[key]
|
||||
self._refreshInfo(ios_router)
|
||||
else:
|
||||
self.uiIOSRouterInfoTreeWidget.clear()
|
||||
|
||||
def _iosRouterNewSlot(self):
|
||||
"""
|
||||
@@ -101,34 +99,6 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
self._ios_routers[key] = IOS_ROUTER_SETTINGS.copy()
|
||||
self._ios_routers[key].update(ios_settings)
|
||||
|
||||
if ios_settings["server"] == 'cloud':
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
log.debug(ios_settings["image"])
|
||||
# Start uploading the image to cloud files
|
||||
|
||||
self._upload_image_progress_dialog = QtGui.QProgressDialog("Uploading image file {}".format(ios_settings['image']), "Cancel", 0, 0, parent=self)
|
||||
self._upload_image_progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||
self._upload_image_progress_dialog.setWindowTitle("IOS image upload")
|
||||
self._upload_image_progress_dialog.show()
|
||||
try:
|
||||
upload_thread = UploadFilesThread(
|
||||
self,
|
||||
cloud_settings=MainWindow.instance().cloudSettings(),
|
||||
files_to_upload=[(
|
||||
self._ios_routers[key]["image"],
|
||||
'images/' + os.path.relpath(self._ios_routers[key]["image"],
|
||||
self._main_window.settings().imagesDirPath())
|
||||
)]
|
||||
)
|
||||
upload_thread.completed.connect(self._imageUploadComplete)
|
||||
upload_thread.start()
|
||||
except Exception as e:
|
||||
self._upload_image_progress_dialog.reject()
|
||||
log.error(e)
|
||||
QtGui.QMessageBox.critical(self, "IOS image upload", "Error uploading IOS image: {}".format(e))
|
||||
|
||||
if ios_settings["platform"] == "c7200":
|
||||
self._ios_routers[key]["midplane"] = "vxr"
|
||||
self._ios_routers[key]["npe"] = "npe-400"
|
||||
@@ -146,18 +116,13 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
self._ios_routers[key][wic] = ios_settings[wic]
|
||||
|
||||
self._ios_routers[key].update(ios_settings)
|
||||
item = QtGui.QTreeWidgetItem(self.uiIOSRoutersTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiIOSRoutersTreeWidget)
|
||||
item.setText(0, self._ios_routers[key]["name"])
|
||||
item.setIcon(0, QtGui.QIcon(self._ios_routers[key]["default_symbol"]))
|
||||
item.setIcon(0, QtGui.QIcon(self._ios_routers[key]["symbol"]))
|
||||
item.setData(0, QtCore.Qt.UserRole, key)
|
||||
self._items.append(item)
|
||||
self.uiIOSRoutersTreeWidget.setCurrentItem(item)
|
||||
|
||||
def _imageUploadComplete(self):
|
||||
if self._upload_image_progress_dialog.wasCanceled():
|
||||
return
|
||||
self._upload_image_progress_dialog.accept()
|
||||
|
||||
def _iosRouterEditSlot(self):
|
||||
"""
|
||||
Edits an IOS router.
|
||||
@@ -170,12 +135,14 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
dialog = ConfigurationDialog(ios_router["name"], ios_router, IOSRouterConfigurationPage(), parent=self)
|
||||
dialog.show()
|
||||
if dialog.exec_():
|
||||
# update the icon
|
||||
item.setIcon(0, QtGui.QIcon(ios_router["symbol"]))
|
||||
if ios_router["name"] != item.text(0):
|
||||
# rename the IOS router
|
||||
new_key = "{server}:{name}".format(server=ios_router["server"], name=ios_router["name"])
|
||||
if new_key in self._ios_routers:
|
||||
QtGui.QMessageBox.critical(self, "IOS router", "IOS router name {} already exists for server {}".format(ios_router["name"],
|
||||
ios_router["server"]))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS router", "IOS router name {} already exists for server {}".format(ios_router["name"],
|
||||
ios_router["server"]))
|
||||
ios_router["name"] = item.text(0)
|
||||
return
|
||||
self._ios_routers[new_key] = self._ios_routers[key]
|
||||
@@ -190,66 +157,78 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
Deletes an IOS router.
|
||||
"""
|
||||
|
||||
item = self.uiIOSRoutersTreeWidget.currentItem()
|
||||
if item:
|
||||
key = item.data(0, QtCore.Qt.UserRole)
|
||||
ios_router = self._ios_routers[key]
|
||||
for item in self.uiIOSRoutersTreeWidget.selectedItems():
|
||||
if item:
|
||||
key = item.data(0, QtCore.Qt.UserRole)
|
||||
ios_router = self._ios_routers[key]
|
||||
|
||||
del self._ios_routers[key]
|
||||
self.uiIOSRoutersTreeWidget.takeTopLevelItem(self.uiIOSRoutersTreeWidget.indexOfTopLevelItem(item))
|
||||
if self._ios_routers == {}:
|
||||
self.uiEditIOSRouterPushButton.setEnabled(False)
|
||||
self.uiDeleteIOSRouterPushButton.setEnabled(False)
|
||||
self.uiDecompressIOSPushButton.setEnabled(False)
|
||||
del self._ios_routers[key]
|
||||
self.uiIOSRoutersTreeWidget.takeTopLevelItem(self.uiIOSRoutersTreeWidget.indexOfTopLevelItem(item))
|
||||
if self._ios_routers == {}:
|
||||
self.uiEditIOSRouterPushButton.setEnabled(False)
|
||||
self.uiDeleteIOSRouterPushButton.setEnabled(False)
|
||||
self.uiDecompressIOSPushButton.setEnabled(False)
|
||||
|
||||
def _imageUploadComplete(self):
|
||||
if self._upload_image_progress_dialog.wasCanceled():
|
||||
return
|
||||
self._upload_image_progress_dialog.accept()
|
||||
|
||||
@staticmethod
|
||||
def getIOSImage(parent):
|
||||
def getImageDirectory():
|
||||
return ImageManager.instance().getDirectoryForType("DYNAMIPS")
|
||||
|
||||
@classmethod
|
||||
def getIOSImage(cls, parent, server):
|
||||
"""
|
||||
|
||||
:param parent: parent widget
|
||||
:param server: The server where the image is located
|
||||
|
||||
:return: path to the IOS image or None
|
||||
"""
|
||||
|
||||
destination_directory = os.path.join(MainWindow.instance().imagesDirPath(), "IOS")
|
||||
path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(parent,
|
||||
"Select an IOS image",
|
||||
destination_directory,
|
||||
"All files (*.*);;IOS image (*.bin *.image)",
|
||||
"IOS image (*.bin *.image)")
|
||||
if not cls._default_images_dir:
|
||||
cls._default_images_dir = cls.getImageDirectory()
|
||||
|
||||
path, _ = QtWidgets.QFileDialog.getOpenFileName(parent,
|
||||
"Select an IOS image",
|
||||
cls._default_images_dir,
|
||||
"All files (*.*);;IOS image (*.bin *.image)",
|
||||
"IOS image (*.bin *.image)")
|
||||
|
||||
if not path:
|
||||
return
|
||||
cls._default_images_dir = os.path.dirname(path)
|
||||
|
||||
if not os.access(path, os.R_OK):
|
||||
QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read {}".format(path))
|
||||
QtWidgets.QMessageBox.critical(parent, "IOS image", "Cannot read {}".format(path))
|
||||
return
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
# Dynamips (Cygwin acutally) doesn't like non ascii paths on Windows
|
||||
# Dynamips (Cygwin actually) doesn't like non ascii paths on Windows
|
||||
try:
|
||||
path.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
QtGui.QMessageBox.warning(parent, "IOS image", "The IOS image filename should contains only ascii (English) characters.")
|
||||
QtWidgets.QMessageBox.warning(parent, "IOS image", "The IOS image filename should contains only ascii (English) characters.")
|
||||
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
# read the first 7 bytes of the file.
|
||||
elf_header_start = f.read(7)
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read ELF magic number: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(parent, "IOS image", "Cannot read ELF magic number: {}".format(e))
|
||||
return
|
||||
|
||||
# file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
|
||||
if elf_header_start != b'\x7fELF\x01\x02\x01':
|
||||
QtGui.QMessageBox.critical(parent, "IOS image", "Sorry, this is not a valid IOS image!")
|
||||
QtWidgets.QMessageBox.critical(parent, "IOS image", "Sorry, this is not a valid IOS image!")
|
||||
return
|
||||
|
||||
try:
|
||||
os.makedirs(destination_directory)
|
||||
except FileExistsError:
|
||||
pass
|
||||
os.makedirs(cls.getImageDirectory(), exist_ok=True)
|
||||
except OSError as e:
|
||||
QtGui.QMessageBox.critical(parent, "IOS images directory", "Could not create the IOS images directory {}: {}".format(destination_directory, e))
|
||||
QtWidgets.QMessageBox.critical(parent, "IOS images directory", "Could not create the IOS images directory {}: {}".format(destination_directory, e))
|
||||
return
|
||||
|
||||
compressed = False
|
||||
@@ -258,10 +237,9 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
except (OSError, ValueError):
|
||||
pass # ignore errors if we cannot find out the IOS image is compressed.
|
||||
if compressed:
|
||||
reply = QtGui.QMessageBox.question(parent, "IOS image", "Would you like to decompress this IOS image?",
|
||||
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
decompressed_image_path = os.path.join(destination_directory, os.path.basename(os.path.splitext(path)[0] + ".image"))
|
||||
reply = QtWidgets.QMessageBox.question(parent, "IOS image", "Would you like to decompress this IOS image?", QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
||||
if reply == QtWidgets.QMessageBox.Yes:
|
||||
decompressed_image_path = os.path.join(cls.getImageDirectory(), os.path.basename(os.path.splitext(path)[0] + ".image"))
|
||||
worker = DecompressIOSWorker(path, decompressed_image_path)
|
||||
progress_dialog = ProgressDialog(worker,
|
||||
"IOS image",
|
||||
@@ -271,24 +249,7 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
if progress_dialog.exec_() is not False:
|
||||
path = decompressed_image_path
|
||||
|
||||
if os.path.normpath(os.path.dirname(path)) != destination_directory:
|
||||
# the IOS image is not in the default images directory
|
||||
reply = QtGui.QMessageBox.question(parent,
|
||||
"IOS image",
|
||||
"Would you like to copy {} to the default images directory".format(os.path.basename(path)),
|
||||
QtGui.QMessageBox.Yes,
|
||||
QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
destination_path = os.path.join(destination_directory, os.path.basename(path))
|
||||
worker = FileCopyWorker(path, destination_path)
|
||||
progress_dialog = ProgressDialog(worker, "IOS image", "Copying {}".format(os.path.basename(path)), "Cancel", busy=True, parent=parent)
|
||||
progress_dialog.show()
|
||||
progress_dialog.exec_()
|
||||
errors = progress_dialog.errors()
|
||||
if errors:
|
||||
QtGui.QMessageBox.critical(parent, "IOS image", "{}".format("".join(errors)))
|
||||
else:
|
||||
path = destination_path
|
||||
path = ImageManager.instance().askCopyUploadImage(parent, path, server, "DYNAMIPS")
|
||||
|
||||
return path
|
||||
|
||||
@@ -329,26 +290,26 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
ios_router = self._ios_routers[key]
|
||||
path = ios_router["image"]
|
||||
if not os.path.isfile(path):
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
|
||||
return
|
||||
try:
|
||||
if not isIOSCompressed(path):
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
|
||||
return
|
||||
except OSError as e:
|
||||
# errno 22, invalid argument means the file system where the IOS image is located doesn't support mmap
|
||||
if e.errno == 22:
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "IOS image {} cannot be memory mapped, most likely because the file system doesn't support it".format(os.path.basename(path)))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} cannot be memory mapped, most likely because the file system doesn't support it".format(os.path.basename(path)))
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
|
||||
return
|
||||
except ValueError as e:
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
|
||||
return
|
||||
|
||||
decompressed_image_path = os.path.splitext(path)[0] + ".image"
|
||||
if os.path.isfile(decompressed_image_path):
|
||||
QtGui.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
|
||||
QtWidgets.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
|
||||
return
|
||||
|
||||
worker = DecompressIOSWorker(path, decompressed_image_path)
|
||||
@@ -363,7 +324,7 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
|
||||
def _createSectionItem(self, name):
|
||||
|
||||
section_item = QtGui.QTreeWidgetItem(self.uiIOSRouterInfoTreeWidget)
|
||||
section_item = QtWidgets.QTreeWidgetItem(self.uiIOSRouterInfoTreeWidget)
|
||||
section_item.setText(0, name)
|
||||
font = section_item.font(0)
|
||||
font.setBold(True)
|
||||
@@ -376,37 +337,38 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
|
||||
# fill out the General section
|
||||
section_item = self._createSectionItem("General")
|
||||
QtGui.QTreeWidgetItem(section_item, ["Name:", ios_router["name"]])
|
||||
QtGui.QTreeWidgetItem(section_item, ["Server:", ios_router["server"]])
|
||||
QtGui.QTreeWidgetItem(section_item, ["Platform:", ios_router["platform"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Name:", ios_router["name"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Server:", ios_router["server"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Platform:", ios_router["platform"]])
|
||||
if ios_router["chassis"]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["Chassis:", ios_router["chassis"]])
|
||||
QtGui.QTreeWidgetItem(section_item, ["Image:", ios_router["image"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Chassis:", ios_router["chassis"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Image:", ios_router["image"]])
|
||||
if ios_router["idlepc"]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["Idle-PC:", ios_router["idlepc"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Idle-PC:", ios_router["idlepc"]])
|
||||
if ios_router["startup_config"]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["Startup-config:", ios_router["startup_config"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Startup-config:", ios_router["startup_config"]])
|
||||
if ios_router["private_config"]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["Private-config:", ios_router["private_config"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Private-config:", ios_router["private_config"]])
|
||||
if ios_router["platform"] == "c7200":
|
||||
QtGui.QTreeWidgetItem(section_item, ["Midplane:", ios_router["midplane"]])
|
||||
QtGui.QTreeWidgetItem(section_item, ["NPE:", ios_router["npe"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Midplane:", ios_router["midplane"]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["NPE:", ios_router["npe"]])
|
||||
|
||||
# fill out the Memories and disk section
|
||||
section_item = self._createSectionItem("Memories and disks")
|
||||
QtGui.QTreeWidgetItem(section_item, ["RAM:", "{} MiB".format(ios_router["ram"])])
|
||||
QtGui.QTreeWidgetItem(section_item, ["NVRAM:", "{} KiB".format(ios_router["nvram"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["RAM:", "{} MiB".format(ios_router["ram"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["NVRAM:", "{} KiB".format(ios_router["nvram"])])
|
||||
if "iomem" in ios_router and ios_router["iomem"]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["I/O memory:", "{}%".format(ios_router["iomem"])])
|
||||
QtGui.QTreeWidgetItem(section_item, ["PCMCIA disk0:", "{} MiB".format(ios_router["disk0"])])
|
||||
QtGui.QTreeWidgetItem(section_item, ["PCMCIA disk1:", "{} MiB".format(ios_router["disk1"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["I/O memory:", "{}%".format(ios_router["iomem"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["PCMCIA disk0:", "{} MiB".format(ios_router["disk0"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["PCMCIA disk1:", "{} MiB".format(ios_router["disk1"])])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Auto delete:", "{}".format(ios_router["auto_delete_disks"])])
|
||||
|
||||
# fill out the Adapters section
|
||||
section_item = self._createSectionItem("Adapters")
|
||||
for slot_id in range(0, 7):
|
||||
slot = "slot{}".format(slot_id)
|
||||
if slot in ios_router and ios_router[slot]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["Slot {}:".format(slot_id), ios_router[slot]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["Slot {}:".format(slot_id), ios_router[slot]])
|
||||
if section_item.childCount() == 0:
|
||||
self.uiIOSRouterInfoTreeWidget.takeTopLevelItem(self.uiIOSRouterInfoTreeWidget.indexOfTopLevelItem(section_item))
|
||||
|
||||
@@ -415,7 +377,7 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
for wic_id in range(0, 3):
|
||||
wic = "wic{}".format(wic_id)
|
||||
if wic in ios_router and ios_router[wic]:
|
||||
QtGui.QTreeWidgetItem(section_item, ["WIC {}:".format(wic_id), ios_router[wic]])
|
||||
QtWidgets.QTreeWidgetItem(section_item, ["WIC {}:".format(wic_id), ios_router[wic]])
|
||||
if section_item.childCount() == 0:
|
||||
self.uiIOSRouterInfoTreeWidget.takeTopLevelItem(self.uiIOSRouterInfoTreeWidget.indexOfTopLevelItem(section_item))
|
||||
|
||||
@@ -423,48 +385,6 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
self.uiIOSRouterInfoTreeWidget.resizeColumnToContents(0)
|
||||
self.uiIOSRouterInfoTreeWidget.resizeColumnToContents(1)
|
||||
|
||||
def _iosRouterPressedSlot(self, item, column):
|
||||
"""
|
||||
Slot for item pressed.
|
||||
|
||||
:param item: ignored
|
||||
:param column: ignored
|
||||
"""
|
||||
|
||||
if QtGui.QApplication.mouseButtons() & QtCore.Qt.RightButton:
|
||||
self._showContextualMenu()
|
||||
|
||||
def _showContextualMenu(self):
|
||||
"""
|
||||
Contextual menu.
|
||||
"""
|
||||
|
||||
menu = QtGui.QMenu()
|
||||
change_symbol_action = QtGui.QAction("Change symbol", menu)
|
||||
change_symbol_action.setIcon(QtGui.QIcon(":/icons/node_conception.svg"))
|
||||
self.connect(change_symbol_action, QtCore.SIGNAL('triggered()'), self._changeSymbolSlot)
|
||||
menu.addAction(change_symbol_action)
|
||||
menu.exec_(QtGui.QCursor.pos())
|
||||
|
||||
def _changeSymbolSlot(self):
|
||||
"""
|
||||
Change a symbol for an IOS router.
|
||||
"""
|
||||
|
||||
item = self.uiIOSRoutersTreeWidget.currentItem()
|
||||
if item:
|
||||
key = item.data(0, QtCore.Qt.UserRole)
|
||||
ios_router = self._ios_routers[key]
|
||||
dialog = SymbolSelectionDialog(self, symbol=ios_router["default_symbol"], category=ios_router["category"])
|
||||
dialog.show()
|
||||
if dialog.exec_():
|
||||
normal_symbol, selected_symbol = dialog.getSymbols()
|
||||
category = dialog.getCategory()
|
||||
item.setIcon(0, QtGui.QIcon(normal_symbol))
|
||||
ios_router["default_symbol"] = normal_symbol
|
||||
ios_router["hover_symbol"] = selected_symbol
|
||||
ios_router["category"] = category
|
||||
|
||||
def loadPreferences(self):
|
||||
"""
|
||||
Loads the IOS router preferences.
|
||||
@@ -475,9 +395,9 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
|
||||
self._items.clear()
|
||||
|
||||
for key, ios_router in self._ios_routers.items():
|
||||
item = QtGui.QTreeWidgetItem(self.uiIOSRoutersTreeWidget)
|
||||
item = QtWidgets.QTreeWidgetItem(self.uiIOSRoutersTreeWidget)
|
||||
item.setText(0, ios_router["name"])
|
||||
item.setIcon(0, QtGui.QIcon(ios_router["default_symbol"]))
|
||||
item.setIcon(0, QtGui.QIcon(ios_router["symbol"]))
|
||||
item.setData(0, QtCore.Qt.UserRole, key)
|
||||
self._items.append(item)
|
||||
|
||||
|
||||
@@ -30,20 +30,10 @@ DYNAMIPS_SETTINGS = {
|
||||
"mmap_support": True,
|
||||
}
|
||||
|
||||
DYNAMIPS_SETTING_TYPES = {
|
||||
"dynamips_path": str,
|
||||
"allocate_aux_console_ports": bool,
|
||||
"use_local_server": bool,
|
||||
"ghost_ios_support": bool,
|
||||
"sparse_memory_support": bool,
|
||||
"mmap_support": bool,
|
||||
}
|
||||
|
||||
IOS_ROUTER_SETTINGS = {
|
||||
"name": "",
|
||||
"image": "",
|
||||
"default_symbol": ":/symbols/router.normal.svg",
|
||||
"hover_symbol": ":/symbols/router.selected.svg",
|
||||
"symbol": ":/symbols/router.svg",
|
||||
"category": Node.routers,
|
||||
"startup_config": "",
|
||||
"private_config": "",
|
||||
@@ -60,35 +50,11 @@ IOS_ROUTER_SETTINGS = {
|
||||
"mac_addr": "",
|
||||
"disk0": 0,
|
||||
"disk1": 0,
|
||||
"auto_delete_disks": False,
|
||||
"system_id": "FTX0945W0MY",
|
||||
"server": "local"
|
||||
}
|
||||
|
||||
IOS_ROUTER_SETTING_TYPES = {
|
||||
"name": str,
|
||||
"image": str,
|
||||
"default_symbol": str,
|
||||
"hover_symbol": str,
|
||||
"category": int,
|
||||
"startup_config": str,
|
||||
"private_config": str,
|
||||
"platform": str,
|
||||
"chassis": str,
|
||||
"idlepc": str,
|
||||
"idlemax": int,
|
||||
"idlesleep": int,
|
||||
"exec_area": int,
|
||||
"mmap": bool,
|
||||
"sparsemem": bool,
|
||||
"ram": int,
|
||||
"nvram": int,
|
||||
"mac_addr": str,
|
||||
"disk0": int,
|
||||
"disk1": int,
|
||||
"system_id": str,
|
||||
"server": str
|
||||
}
|
||||
|
||||
# supported platforms with the default RAM value
|
||||
PLATFORMS_DEFAULT_RAM = {"c1700": 160,
|
||||
"c2600": 160,
|
||||
|
||||
@@ -1,65 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/atm_bridge_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/atm_bridge_configuration_page.ui'
|
||||
#
|
||||
# Created: Sun Mar 16 11:16:57 2014
|
||||
# by: PyQt4 UI code generator 4.10
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_atmBridgeConfigPageWidget(object):
|
||||
|
||||
def setupUi(self, atmBridgeConfigPageWidget):
|
||||
atmBridgeConfigPageWidget.setObjectName(_fromUtf8("atmBridgeConfigPageWidget"))
|
||||
atmBridgeConfigPageWidget.setObjectName("atmBridgeConfigPageWidget")
|
||||
atmBridgeConfigPageWidget.resize(432, 358)
|
||||
self.gridLayout_2 = QtGui.QGridLayout(atmBridgeConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiMappingGroupBox = QtGui.QGroupBox(atmBridgeConfigPageWidget)
|
||||
self.uiMappingGroupBox.setObjectName(_fromUtf8("uiMappingGroupBox"))
|
||||
self.vboxlayout = QtGui.QVBoxLayout(self.uiMappingGroupBox)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiMappingTreeWidget = QtGui.QTreeWidget(self.uiMappingGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(atmBridgeConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiMappingGroupBox = QtWidgets.QGroupBox(atmBridgeConfigPageWidget)
|
||||
self.uiMappingGroupBox.setObjectName("uiMappingGroupBox")
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(self.uiMappingGroupBox)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiMappingTreeWidget = QtWidgets.QTreeWidget(self.uiMappingGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiMappingTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiMappingTreeWidget.setSizePolicy(sizePolicy)
|
||||
self.uiMappingTreeWidget.setRootIsDecorated(False)
|
||||
self.uiMappingTreeWidget.setObjectName(_fromUtf8("uiMappingTreeWidget"))
|
||||
self.uiMappingTreeWidget.setObjectName("uiMappingTreeWidget")
|
||||
self.vboxlayout.addWidget(self.uiMappingTreeWidget)
|
||||
self.gridLayout_2.addWidget(self.uiMappingGroupBox, 0, 2, 3, 1)
|
||||
self.uiEthernetGroupBox = QtGui.QGroupBox(atmBridgeConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiEthernetGroupBox = QtWidgets.QGroupBox(atmBridgeConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiEthernetGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiEthernetGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiEthernetGroupBox.setObjectName(_fromUtf8("uiEthernetGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiEthernetGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiEthernetPortLabel = QtGui.QLabel(self.uiEthernetGroupBox)
|
||||
self.uiEthernetPortLabel.setObjectName(_fromUtf8("uiEthernetPortLabel"))
|
||||
self.uiEthernetGroupBox.setObjectName("uiEthernetGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiEthernetGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiEthernetPortLabel = QtWidgets.QLabel(self.uiEthernetGroupBox)
|
||||
self.uiEthernetPortLabel.setObjectName("uiEthernetPortLabel")
|
||||
self.gridlayout.addWidget(self.uiEthernetPortLabel, 0, 0, 1, 1)
|
||||
self.uiEthernetPortSpinBox = QtGui.QSpinBox(self.uiEthernetGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiEthernetPortSpinBox = QtWidgets.QSpinBox(self.uiEthernetGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiEthernetPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -67,23 +50,23 @@ class Ui_atmBridgeConfigPageWidget(object):
|
||||
self.uiEthernetPortSpinBox.setMinimum(0)
|
||||
self.uiEthernetPortSpinBox.setMaximum(65535)
|
||||
self.uiEthernetPortSpinBox.setProperty("value", 1)
|
||||
self.uiEthernetPortSpinBox.setObjectName(_fromUtf8("uiEthernetPortSpinBox"))
|
||||
self.uiEthernetPortSpinBox.setObjectName("uiEthernetPortSpinBox")
|
||||
self.gridlayout.addWidget(self.uiEthernetPortSpinBox, 0, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiEthernetGroupBox, 1, 0, 1, 2)
|
||||
self.uiATMGroupBox = QtGui.QGroupBox(atmBridgeConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiATMGroupBox = QtWidgets.QGroupBox(atmBridgeConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiATMGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiATMGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiATMGroupBox.setObjectName(_fromUtf8("uiATMGroupBox"))
|
||||
self.gridlayout1 = QtGui.QGridLayout(self.uiATMGroupBox)
|
||||
self.gridlayout1.setObjectName(_fromUtf8("gridlayout1"))
|
||||
self.uiATMPortLabel = QtGui.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMPortLabel.setObjectName(_fromUtf8("uiATMPortLabel"))
|
||||
self.uiATMGroupBox.setObjectName("uiATMGroupBox")
|
||||
self.gridlayout1 = QtWidgets.QGridLayout(self.uiATMGroupBox)
|
||||
self.gridlayout1.setObjectName("gridlayout1")
|
||||
self.uiATMPortLabel = QtWidgets.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMPortLabel.setObjectName("uiATMPortLabel")
|
||||
self.gridlayout1.addWidget(self.uiATMPortLabel, 0, 0, 1, 1)
|
||||
self.uiATMPortSpinBox = QtGui.QSpinBox(self.uiATMGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiATMPortSpinBox = QtWidgets.QSpinBox(self.uiATMGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiATMPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -91,14 +74,14 @@ class Ui_atmBridgeConfigPageWidget(object):
|
||||
self.uiATMPortSpinBox.setMinimum(0)
|
||||
self.uiATMPortSpinBox.setMaximum(65535)
|
||||
self.uiATMPortSpinBox.setProperty("value", 10)
|
||||
self.uiATMPortSpinBox.setObjectName(_fromUtf8("uiATMPortSpinBox"))
|
||||
self.uiATMPortSpinBox.setObjectName("uiATMPortSpinBox")
|
||||
self.gridlayout1.addWidget(self.uiATMPortSpinBox, 0, 1, 1, 1)
|
||||
self.uiATMVPILabel = QtGui.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMVPILabel.setObjectName(_fromUtf8("uiATMVPILabel"))
|
||||
self.uiATMVPILabel = QtWidgets.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMVPILabel.setObjectName("uiATMVPILabel")
|
||||
self.gridlayout1.addWidget(self.uiATMVPILabel, 1, 0, 1, 1)
|
||||
self.uiATMVPISpinBox = QtGui.QSpinBox(self.uiATMGroupBox)
|
||||
self.uiATMVPISpinBox = QtWidgets.QSpinBox(self.uiATMGroupBox)
|
||||
self.uiATMVPISpinBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiATMVPISpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -107,40 +90,40 @@ class Ui_atmBridgeConfigPageWidget(object):
|
||||
self.uiATMVPISpinBox.setMaximum(65535)
|
||||
self.uiATMVPISpinBox.setSingleStep(1)
|
||||
self.uiATMVPISpinBox.setProperty("value", 0)
|
||||
self.uiATMVPISpinBox.setObjectName(_fromUtf8("uiATMVPISpinBox"))
|
||||
self.uiATMVPISpinBox.setObjectName("uiATMVPISpinBox")
|
||||
self.gridlayout1.addWidget(self.uiATMVPISpinBox, 1, 1, 1, 1)
|
||||
self.uiATMVCILabel = QtGui.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMVCILabel.setObjectName(_fromUtf8("uiATMVCILabel"))
|
||||
self.uiATMVCILabel = QtWidgets.QLabel(self.uiATMGroupBox)
|
||||
self.uiATMVCILabel.setObjectName("uiATMVCILabel")
|
||||
self.gridlayout1.addWidget(self.uiATMVCILabel, 2, 0, 1, 1)
|
||||
self.uiATMVCISpinBox = QtGui.QSpinBox(self.uiATMGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiATMVCISpinBox = QtWidgets.QSpinBox(self.uiATMGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiATMVCISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiATMVCISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiATMVCISpinBox.setMaximum(65535)
|
||||
self.uiATMVCISpinBox.setProperty("value", 100)
|
||||
self.uiATMVCISpinBox.setObjectName(_fromUtf8("uiATMVCISpinBox"))
|
||||
self.uiATMVCISpinBox.setObjectName("uiATMVCISpinBox")
|
||||
self.gridlayout1.addWidget(self.uiATMVCISpinBox, 2, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiATMGroupBox, 2, 0, 1, 2)
|
||||
self.uiAddPushButton = QtGui.QPushButton(atmBridgeConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName(_fromUtf8("uiAddPushButton"))
|
||||
self.uiAddPushButton = QtWidgets.QPushButton(atmBridgeConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName("uiAddPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiAddPushButton, 3, 0, 1, 1)
|
||||
self.uiDeletePushButton = QtGui.QPushButton(atmBridgeConfigPageWidget)
|
||||
self.uiDeletePushButton = QtWidgets.QPushButton(atmBridgeConfigPageWidget)
|
||||
self.uiDeletePushButton.setEnabled(False)
|
||||
self.uiDeletePushButton.setObjectName(_fromUtf8("uiDeletePushButton"))
|
||||
self.uiDeletePushButton.setObjectName("uiDeletePushButton")
|
||||
self.gridLayout_2.addWidget(self.uiDeletePushButton, 3, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(371, 121, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(371, 121, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 4, 0, 1, 3)
|
||||
self.uiGeneralGroupBox = QtGui.QGroupBox(atmBridgeConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName(_fromUtf8("uiGeneralGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.uiGeneralGroupBox = QtWidgets.QGroupBox(atmBridgeConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName("uiGeneralGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiGeneralGroupBox, 0, 0, 1, 2)
|
||||
|
||||
@@ -153,17 +136,19 @@ class Ui_atmBridgeConfigPageWidget(object):
|
||||
atmBridgeConfigPageWidget.setTabOrder(self.uiAddPushButton, self.uiDeletePushButton)
|
||||
|
||||
def retranslateUi(self, atmBridgeConfigPageWidget):
|
||||
atmBridgeConfigPageWidget.setWindowTitle(_translate("atmBridgeConfigPageWidget", "ATM Bridge", None))
|
||||
self.uiMappingGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "Mapping", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("atmBridgeConfigPageWidget", "Ethernet Port", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("atmBridgeConfigPageWidget", "Port:VPI:VCI", None))
|
||||
self.uiEthernetGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "Ethernet side", None))
|
||||
self.uiEthernetPortLabel.setText(_translate("atmBridgeConfigPageWidget", "Port:", None))
|
||||
self.uiATMGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "ATM side", None))
|
||||
self.uiATMPortLabel.setText(_translate("atmBridgeConfigPageWidget", "Port:", None))
|
||||
self.uiATMVPILabel.setText(_translate("atmBridgeConfigPageWidget", "VPI:", None))
|
||||
self.uiATMVCILabel.setText(_translate("atmBridgeConfigPageWidget", "VCI:", None))
|
||||
self.uiAddPushButton.setText(_translate("atmBridgeConfigPageWidget", "&Add", None))
|
||||
self.uiDeletePushButton.setText(_translate("atmBridgeConfigPageWidget", "&Delete", None))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "General", None))
|
||||
self.uiNameLabel.setText(_translate("atmBridgeConfigPageWidget", "Name:", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
atmBridgeConfigPageWidget.setWindowTitle(_translate("atmBridgeConfigPageWidget", "ATM Bridge"))
|
||||
self.uiMappingGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "Mapping"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("atmBridgeConfigPageWidget", "Ethernet Port"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("atmBridgeConfigPageWidget", "Port:VPI:VCI"))
|
||||
self.uiEthernetGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "Ethernet side"))
|
||||
self.uiEthernetPortLabel.setText(_translate("atmBridgeConfigPageWidget", "Port:"))
|
||||
self.uiATMGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "ATM side"))
|
||||
self.uiATMPortLabel.setText(_translate("atmBridgeConfigPageWidget", "Port:"))
|
||||
self.uiATMVPILabel.setText(_translate("atmBridgeConfigPageWidget", "VPI:"))
|
||||
self.uiATMVCILabel.setText(_translate("atmBridgeConfigPageWidget", "VCI:"))
|
||||
self.uiAddPushButton.setText(_translate("atmBridgeConfigPageWidget", "&Add"))
|
||||
self.uiDeletePushButton.setText(_translate("atmBridgeConfigPageWidget", "&Delete"))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("atmBridgeConfigPageWidget", "General"))
|
||||
self.uiNameLabel.setText(_translate("atmBridgeConfigPageWidget", "Name:"))
|
||||
|
||||
|
||||
@@ -1,88 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/atm_switch_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/atm_switch_configuration_page.ui'
|
||||
#
|
||||
# Created: Sun Mar 16 11:16:57 2014
|
||||
# by: PyQt4 UI code generator 4.10
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_atmSwitchConfigPageWidget(object):
|
||||
|
||||
def setupUi(self, atmSwitchConfigPageWidget):
|
||||
atmSwitchConfigPageWidget.setObjectName(_fromUtf8("atmSwitchConfigPageWidget"))
|
||||
atmSwitchConfigPageWidget.setObjectName("atmSwitchConfigPageWidget")
|
||||
atmSwitchConfigPageWidget.resize(459, 419)
|
||||
self.gridLayout_2 = QtGui.QGridLayout(atmSwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiGeneralGroupBox = QtGui.QGroupBox(atmSwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName(_fromUtf8("uiGeneralGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(atmSwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiGeneralGroupBox = QtWidgets.QGroupBox(atmSwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName("uiGeneralGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.uiVPICheckBox = QtGui.QCheckBox(self.uiGeneralGroupBox)
|
||||
self.uiVPICheckBox.setObjectName(_fromUtf8("uiVPICheckBox"))
|
||||
self.uiVPICheckBox = QtWidgets.QCheckBox(self.uiGeneralGroupBox)
|
||||
self.uiVPICheckBox.setObjectName("uiVPICheckBox")
|
||||
self.gridLayout.addWidget(self.uiVPICheckBox, 1, 0, 1, 2)
|
||||
self.gridLayout_2.addWidget(self.uiGeneralGroupBox, 0, 0, 1, 3)
|
||||
self.uiMappingGroupBox = QtGui.QGroupBox(atmSwitchConfigPageWidget)
|
||||
self.uiMappingGroupBox.setObjectName(_fromUtf8("uiMappingGroupBox"))
|
||||
self.vboxlayout = QtGui.QVBoxLayout(self.uiMappingGroupBox)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiMappingTreeWidget = QtGui.QTreeWidget(self.uiMappingGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
self.uiMappingGroupBox = QtWidgets.QGroupBox(atmSwitchConfigPageWidget)
|
||||
self.uiMappingGroupBox.setObjectName("uiMappingGroupBox")
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(self.uiMappingGroupBox)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiMappingTreeWidget = QtWidgets.QTreeWidget(self.uiMappingGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiMappingTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiMappingTreeWidget.setSizePolicy(sizePolicy)
|
||||
self.uiMappingTreeWidget.setRootIsDecorated(False)
|
||||
self.uiMappingTreeWidget.setObjectName(_fromUtf8("uiMappingTreeWidget"))
|
||||
self.uiMappingTreeWidget.setObjectName("uiMappingTreeWidget")
|
||||
self.vboxlayout.addWidget(self.uiMappingTreeWidget)
|
||||
self.gridLayout_2.addWidget(self.uiMappingGroupBox, 0, 3, 3, 1)
|
||||
self.uiAddPushButton = QtGui.QPushButton(atmSwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName(_fromUtf8("uiAddPushButton"))
|
||||
self.uiAddPushButton = QtWidgets.QPushButton(atmSwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName("uiAddPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiAddPushButton, 3, 0, 1, 1)
|
||||
self.uiDeletePushButton = QtGui.QPushButton(atmSwitchConfigPageWidget)
|
||||
self.uiDeletePushButton = QtWidgets.QPushButton(atmSwitchConfigPageWidget)
|
||||
self.uiDeletePushButton.setEnabled(False)
|
||||
self.uiDeletePushButton.setObjectName(_fromUtf8("uiDeletePushButton"))
|
||||
self.uiDeletePushButton.setObjectName("uiDeletePushButton")
|
||||
self.gridLayout_2.addWidget(self.uiDeletePushButton, 3, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(213, 31, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(213, 31, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 4, 2, 1, 2)
|
||||
self.uiSourceGroupBox = QtGui.QGroupBox(atmSwitchConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSourceGroupBox = QtWidgets.QGroupBox(atmSwitchConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourceGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSourceGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiSourceGroupBox.setObjectName(_fromUtf8("uiSourceGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiSourceGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiSourcePortLabel = QtGui.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourcePortLabel.setObjectName(_fromUtf8("uiSourcePortLabel"))
|
||||
self.uiSourceGroupBox.setObjectName("uiSourceGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiSourceGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiSourcePortLabel = QtWidgets.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourcePortLabel.setObjectName("uiSourcePortLabel")
|
||||
self.gridlayout.addWidget(self.uiSourcePortLabel, 0, 0, 1, 1)
|
||||
self.uiSourcePortSpinBox = QtGui.QSpinBox(self.uiSourceGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSourcePortSpinBox = QtWidgets.QSpinBox(self.uiSourceGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourcePortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -90,50 +73,50 @@ class Ui_atmSwitchConfigPageWidget(object):
|
||||
self.uiSourcePortSpinBox.setMinimum(0)
|
||||
self.uiSourcePortSpinBox.setMaximum(65535)
|
||||
self.uiSourcePortSpinBox.setProperty("value", 1)
|
||||
self.uiSourcePortSpinBox.setObjectName(_fromUtf8("uiSourcePortSpinBox"))
|
||||
self.uiSourcePortSpinBox.setObjectName("uiSourcePortSpinBox")
|
||||
self.gridlayout.addWidget(self.uiSourcePortSpinBox, 0, 1, 1, 1)
|
||||
self.uiSourceVPILabel = QtGui.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourceVPILabel.setObjectName(_fromUtf8("uiSourceVPILabel"))
|
||||
self.uiSourceVPILabel = QtWidgets.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourceVPILabel.setObjectName("uiSourceVPILabel")
|
||||
self.gridlayout.addWidget(self.uiSourceVPILabel, 1, 0, 1, 1)
|
||||
self.uiSourceVPISpinBox = QtGui.QSpinBox(self.uiSourceGroupBox)
|
||||
self.uiSourceVPISpinBox = QtWidgets.QSpinBox(self.uiSourceGroupBox)
|
||||
self.uiSourceVPISpinBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourceVPISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSourceVPISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSourceVPISpinBox.setMaximum(65535)
|
||||
self.uiSourceVPISpinBox.setProperty("value", 0)
|
||||
self.uiSourceVPISpinBox.setObjectName(_fromUtf8("uiSourceVPISpinBox"))
|
||||
self.uiSourceVPISpinBox.setObjectName("uiSourceVPISpinBox")
|
||||
self.gridlayout.addWidget(self.uiSourceVPISpinBox, 1, 1, 1, 1)
|
||||
self.uiSourceVCILabel = QtGui.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourceVCILabel.setObjectName(_fromUtf8("uiSourceVCILabel"))
|
||||
self.uiSourceVCILabel = QtWidgets.QLabel(self.uiSourceGroupBox)
|
||||
self.uiSourceVCILabel.setObjectName("uiSourceVCILabel")
|
||||
self.gridlayout.addWidget(self.uiSourceVCILabel, 2, 0, 1, 1)
|
||||
self.uiSourceVCISpinBox = QtGui.QSpinBox(self.uiSourceGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSourceVCISpinBox = QtWidgets.QSpinBox(self.uiSourceGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourceVCISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSourceVCISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSourceVCISpinBox.setMaximum(65535)
|
||||
self.uiSourceVCISpinBox.setProperty("value", 100)
|
||||
self.uiSourceVCISpinBox.setObjectName(_fromUtf8("uiSourceVCISpinBox"))
|
||||
self.uiSourceVCISpinBox.setObjectName("uiSourceVCISpinBox")
|
||||
self.gridlayout.addWidget(self.uiSourceVCISpinBox, 2, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiSourceGroupBox, 1, 0, 1, 3)
|
||||
self.uiDestinationGroupBox = QtGui.QGroupBox(atmSwitchConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiDestinationGroupBox = QtWidgets.QGroupBox(atmSwitchConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDestinationGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiDestinationGroupBox.setObjectName(_fromUtf8("uiDestinationGroupBox"))
|
||||
self.gridlayout1 = QtGui.QGridLayout(self.uiDestinationGroupBox)
|
||||
self.gridlayout1.setObjectName(_fromUtf8("gridlayout1"))
|
||||
self.uiDestinationPortLabel = QtGui.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationPortLabel.setObjectName(_fromUtf8("uiDestinationPortLabel"))
|
||||
self.uiDestinationGroupBox.setObjectName("uiDestinationGroupBox")
|
||||
self.gridlayout1 = QtWidgets.QGridLayout(self.uiDestinationGroupBox)
|
||||
self.gridlayout1.setObjectName("gridlayout1")
|
||||
self.uiDestinationPortLabel = QtWidgets.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationPortLabel.setObjectName("uiDestinationPortLabel")
|
||||
self.gridlayout1.addWidget(self.uiDestinationPortLabel, 0, 0, 1, 1)
|
||||
self.uiDestinationPortSpinBox = QtGui.QSpinBox(self.uiDestinationGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDestinationPortSpinBox = QtWidgets.QSpinBox(self.uiDestinationGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -141,34 +124,34 @@ class Ui_atmSwitchConfigPageWidget(object):
|
||||
self.uiDestinationPortSpinBox.setMinimum(0)
|
||||
self.uiDestinationPortSpinBox.setMaximum(65535)
|
||||
self.uiDestinationPortSpinBox.setProperty("value", 10)
|
||||
self.uiDestinationPortSpinBox.setObjectName(_fromUtf8("uiDestinationPortSpinBox"))
|
||||
self.uiDestinationPortSpinBox.setObjectName("uiDestinationPortSpinBox")
|
||||
self.gridlayout1.addWidget(self.uiDestinationPortSpinBox, 0, 1, 1, 1)
|
||||
self.uiDestinationVPILabel = QtGui.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVPILabel.setObjectName(_fromUtf8("uiDestinationVPILabel"))
|
||||
self.uiDestinationVPILabel = QtWidgets.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVPILabel.setObjectName("uiDestinationVPILabel")
|
||||
self.gridlayout1.addWidget(self.uiDestinationVPILabel, 1, 0, 1, 1)
|
||||
self.uiDestinationVPISpinBox = QtGui.QSpinBox(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVPISpinBox = QtWidgets.QSpinBox(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVPISpinBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationVPISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDestinationVPISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiDestinationVPISpinBox.setMaximum(65535)
|
||||
self.uiDestinationVPISpinBox.setProperty("value", 0)
|
||||
self.uiDestinationVPISpinBox.setObjectName(_fromUtf8("uiDestinationVPISpinBox"))
|
||||
self.uiDestinationVPISpinBox.setObjectName("uiDestinationVPISpinBox")
|
||||
self.gridlayout1.addWidget(self.uiDestinationVPISpinBox, 1, 1, 1, 1)
|
||||
self.uiDestinationVCILabel = QtGui.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVCILabel.setObjectName(_fromUtf8("uiDestinationVCILabel"))
|
||||
self.uiDestinationVCILabel = QtWidgets.QLabel(self.uiDestinationGroupBox)
|
||||
self.uiDestinationVCILabel.setObjectName("uiDestinationVCILabel")
|
||||
self.gridlayout1.addWidget(self.uiDestinationVCILabel, 2, 0, 1, 1)
|
||||
self.uiDestinationVCISpinBox = QtGui.QSpinBox(self.uiDestinationGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDestinationVCISpinBox = QtWidgets.QSpinBox(self.uiDestinationGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationVCISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDestinationVCISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiDestinationVCISpinBox.setMaximum(65535)
|
||||
self.uiDestinationVCISpinBox.setProperty("value", 200)
|
||||
self.uiDestinationVCISpinBox.setObjectName(_fromUtf8("uiDestinationVCISpinBox"))
|
||||
self.uiDestinationVCISpinBox.setObjectName("uiDestinationVCISpinBox")
|
||||
self.gridlayout1.addWidget(self.uiDestinationVCISpinBox, 2, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiDestinationGroupBox, 2, 0, 1, 3)
|
||||
|
||||
@@ -184,20 +167,22 @@ class Ui_atmSwitchConfigPageWidget(object):
|
||||
atmSwitchConfigPageWidget.setTabOrder(self.uiAddPushButton, self.uiDeletePushButton)
|
||||
|
||||
def retranslateUi(self, atmSwitchConfigPageWidget):
|
||||
atmSwitchConfigPageWidget.setWindowTitle(_translate("atmSwitchConfigPageWidget", "ATM Switch", None))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "General", None))
|
||||
self.uiNameLabel.setText(_translate("atmSwitchConfigPageWidget", "Name:", None))
|
||||
self.uiVPICheckBox.setText(_translate("atmSwitchConfigPageWidget", "Use VPI only (VP tunnel)", None))
|
||||
self.uiMappingGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Mapping", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("atmSwitchConfigPageWidget", "Port:VPI:VCI", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("atmSwitchConfigPageWidget", "Port:VPI:VCI", None))
|
||||
self.uiAddPushButton.setText(_translate("atmSwitchConfigPageWidget", "&Add", None))
|
||||
self.uiDeletePushButton.setText(_translate("atmSwitchConfigPageWidget", "&Delete", None))
|
||||
self.uiSourceGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Source", None))
|
||||
self.uiSourcePortLabel.setText(_translate("atmSwitchConfigPageWidget", "Port:", None))
|
||||
self.uiSourceVPILabel.setText(_translate("atmSwitchConfigPageWidget", "VPI:", None))
|
||||
self.uiSourceVCILabel.setText(_translate("atmSwitchConfigPageWidget", "VCI:", None))
|
||||
self.uiDestinationGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Destination", None))
|
||||
self.uiDestinationPortLabel.setText(_translate("atmSwitchConfigPageWidget", "Port:", None))
|
||||
self.uiDestinationVPILabel.setText(_translate("atmSwitchConfigPageWidget", "VPI:", None))
|
||||
self.uiDestinationVCILabel.setText(_translate("atmSwitchConfigPageWidget", "VCI:", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
atmSwitchConfigPageWidget.setWindowTitle(_translate("atmSwitchConfigPageWidget", "ATM Switch"))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "General"))
|
||||
self.uiNameLabel.setText(_translate("atmSwitchConfigPageWidget", "Name:"))
|
||||
self.uiVPICheckBox.setText(_translate("atmSwitchConfigPageWidget", "Use VPI only (VP tunnel)"))
|
||||
self.uiMappingGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Mapping"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("atmSwitchConfigPageWidget", "Port:VPI:VCI"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("atmSwitchConfigPageWidget", "Port:VPI:VCI"))
|
||||
self.uiAddPushButton.setText(_translate("atmSwitchConfigPageWidget", "&Add"))
|
||||
self.uiDeletePushButton.setText(_translate("atmSwitchConfigPageWidget", "&Delete"))
|
||||
self.uiSourceGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Source"))
|
||||
self.uiSourcePortLabel.setText(_translate("atmSwitchConfigPageWidget", "Port:"))
|
||||
self.uiSourceVPILabel.setText(_translate("atmSwitchConfigPageWidget", "VPI:"))
|
||||
self.uiSourceVCILabel.setText(_translate("atmSwitchConfigPageWidget", "VCI:"))
|
||||
self.uiDestinationGroupBox.setTitle(_translate("atmSwitchConfigPageWidget", "Destination"))
|
||||
self.uiDestinationPortLabel.setText(_translate("atmSwitchConfigPageWidget", "Port:"))
|
||||
self.uiDestinationVPILabel.setText(_translate("atmSwitchConfigPageWidget", "VPI:"))
|
||||
self.uiDestinationVCILabel.setText(_translate("atmSwitchConfigPageWidget", "VCI:"))
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>539</height>
|
||||
<width>435</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -154,8 +154,6 @@
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>spacer_2</zorder>
|
||||
<zorder>uiMemoryUsageOptimisationGroupBox</zorder>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -1,99 +1,85 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/dynamips/ui/dynamips_preferences_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/dynamips_preferences_page.ui'
|
||||
#
|
||||
# Created: Mon Mar 9 17:56:06 2015
|
||||
# by: PyQt4 UI code generator 4.10.4
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_DynamipsPreferencesPageWidget(object):
|
||||
def setupUi(self, DynamipsPreferencesPageWidget):
|
||||
DynamipsPreferencesPageWidget.setObjectName(_fromUtf8("DynamipsPreferencesPageWidget"))
|
||||
DynamipsPreferencesPageWidget.resize(430, 539)
|
||||
self.vboxlayout = QtGui.QVBoxLayout(DynamipsPreferencesPageWidget)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiTabWidget = QtGui.QTabWidget(DynamipsPreferencesPageWidget)
|
||||
self.uiTabWidget.setObjectName(_fromUtf8("uiTabWidget"))
|
||||
self.uiGeneralSettingsTabWidget = QtGui.QWidget()
|
||||
self.uiGeneralSettingsTabWidget.setObjectName(_fromUtf8("uiGeneralSettingsTabWidget"))
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout(self.uiGeneralSettingsTabWidget)
|
||||
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
|
||||
self.uiUseLocalServercheckBox = QtGui.QCheckBox(self.uiGeneralSettingsTabWidget)
|
||||
DynamipsPreferencesPageWidget.setObjectName("DynamipsPreferencesPageWidget")
|
||||
DynamipsPreferencesPageWidget.resize(435, 200)
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(DynamipsPreferencesPageWidget)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiTabWidget = QtWidgets.QTabWidget(DynamipsPreferencesPageWidget)
|
||||
self.uiTabWidget.setObjectName("uiTabWidget")
|
||||
self.uiGeneralSettingsTabWidget = QtWidgets.QWidget()
|
||||
self.uiGeneralSettingsTabWidget.setObjectName("uiGeneralSettingsTabWidget")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.uiGeneralSettingsTabWidget)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.uiUseLocalServercheckBox = QtWidgets.QCheckBox(self.uiGeneralSettingsTabWidget)
|
||||
self.uiUseLocalServercheckBox.setChecked(True)
|
||||
self.uiUseLocalServercheckBox.setObjectName(_fromUtf8("uiUseLocalServercheckBox"))
|
||||
self.uiUseLocalServercheckBox.setObjectName("uiUseLocalServercheckBox")
|
||||
self.verticalLayout_2.addWidget(self.uiUseLocalServercheckBox)
|
||||
self.uiDynamipsPathLabel = QtGui.QLabel(self.uiGeneralSettingsTabWidget)
|
||||
self.uiDynamipsPathLabel.setObjectName(_fromUtf8("uiDynamipsPathLabel"))
|
||||
self.uiDynamipsPathLabel = QtWidgets.QLabel(self.uiGeneralSettingsTabWidget)
|
||||
self.uiDynamipsPathLabel.setObjectName("uiDynamipsPathLabel")
|
||||
self.verticalLayout_2.addWidget(self.uiDynamipsPathLabel)
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||
self.uiDynamipsPathLineEdit = QtGui.QLineEdit(self.uiGeneralSettingsTabWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.uiDynamipsPathLineEdit = QtWidgets.QLineEdit(self.uiGeneralSettingsTabWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDynamipsPathLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiDynamipsPathLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiDynamipsPathLineEdit.setObjectName(_fromUtf8("uiDynamipsPathLineEdit"))
|
||||
self.uiDynamipsPathLineEdit.setObjectName("uiDynamipsPathLineEdit")
|
||||
self.horizontalLayout.addWidget(self.uiDynamipsPathLineEdit)
|
||||
self.uiDynamipsPathToolButton = QtGui.QToolButton(self.uiGeneralSettingsTabWidget)
|
||||
self.uiDynamipsPathToolButton = QtWidgets.QToolButton(self.uiGeneralSettingsTabWidget)
|
||||
self.uiDynamipsPathToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||
self.uiDynamipsPathToolButton.setObjectName(_fromUtf8("uiDynamipsPathToolButton"))
|
||||
self.uiDynamipsPathToolButton.setObjectName("uiDynamipsPathToolButton")
|
||||
self.horizontalLayout.addWidget(self.uiDynamipsPathToolButton)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
self.uiAllocateAuxConsolePortsCheckBox = QtGui.QCheckBox(self.uiGeneralSettingsTabWidget)
|
||||
self.uiAllocateAuxConsolePortsCheckBox.setObjectName(_fromUtf8("uiAllocateAuxConsolePortsCheckBox"))
|
||||
self.uiAllocateAuxConsolePortsCheckBox = QtWidgets.QCheckBox(self.uiGeneralSettingsTabWidget)
|
||||
self.uiAllocateAuxConsolePortsCheckBox.setObjectName("uiAllocateAuxConsolePortsCheckBox")
|
||||
self.verticalLayout_2.addWidget(self.uiAllocateAuxConsolePortsCheckBox)
|
||||
spacerItem = QtGui.QSpacerItem(390, 193, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(390, 193, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem)
|
||||
self.uiTabWidget.addTab(self.uiGeneralSettingsTabWidget, _fromUtf8(""))
|
||||
self.uiAdvancedSettingsTabWidget = QtGui.QWidget()
|
||||
self.uiAdvancedSettingsTabWidget.setObjectName(_fromUtf8("uiAdvancedSettingsTabWidget"))
|
||||
self.verticalLayout_3 = QtGui.QVBoxLayout(self.uiAdvancedSettingsTabWidget)
|
||||
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
|
||||
self.uiMemoryUsageOptimisationGroupBox = QtGui.QGroupBox(self.uiAdvancedSettingsTabWidget)
|
||||
self.uiMemoryUsageOptimisationGroupBox.setObjectName(_fromUtf8("uiMemoryUsageOptimisationGroupBox"))
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.uiGhostIOSSupportCheckBox = QtGui.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiTabWidget.addTab(self.uiGeneralSettingsTabWidget, "")
|
||||
self.uiAdvancedSettingsTabWidget = QtWidgets.QWidget()
|
||||
self.uiAdvancedSettingsTabWidget.setObjectName("uiAdvancedSettingsTabWidget")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.uiAdvancedSettingsTabWidget)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.uiMemoryUsageOptimisationGroupBox = QtWidgets.QGroupBox(self.uiAdvancedSettingsTabWidget)
|
||||
self.uiMemoryUsageOptimisationGroupBox.setObjectName("uiMemoryUsageOptimisationGroupBox")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.uiGhostIOSSupportCheckBox = QtWidgets.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiGhostIOSSupportCheckBox.setChecked(True)
|
||||
self.uiGhostIOSSupportCheckBox.setObjectName(_fromUtf8("uiGhostIOSSupportCheckBox"))
|
||||
self.uiGhostIOSSupportCheckBox.setObjectName("uiGhostIOSSupportCheckBox")
|
||||
self.verticalLayout.addWidget(self.uiGhostIOSSupportCheckBox)
|
||||
self.uiMmapSupportCheckBox = QtGui.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiMmapSupportCheckBox = QtWidgets.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiMmapSupportCheckBox.setChecked(True)
|
||||
self.uiMmapSupportCheckBox.setObjectName(_fromUtf8("uiMmapSupportCheckBox"))
|
||||
self.uiMmapSupportCheckBox.setObjectName("uiMmapSupportCheckBox")
|
||||
self.verticalLayout.addWidget(self.uiMmapSupportCheckBox)
|
||||
self.uiSparseMemorySupportCheckBox = QtGui.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiSparseMemorySupportCheckBox = QtWidgets.QCheckBox(self.uiMemoryUsageOptimisationGroupBox)
|
||||
self.uiSparseMemorySupportCheckBox.setChecked(False)
|
||||
self.uiSparseMemorySupportCheckBox.setObjectName(_fromUtf8("uiSparseMemorySupportCheckBox"))
|
||||
self.uiSparseMemorySupportCheckBox.setObjectName("uiSparseMemorySupportCheckBox")
|
||||
self.verticalLayout.addWidget(self.uiSparseMemorySupportCheckBox)
|
||||
self.verticalLayout_3.addWidget(self.uiMemoryUsageOptimisationGroupBox)
|
||||
spacerItem1 = QtGui.QSpacerItem(390, 12, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(390, 12, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_3.addItem(spacerItem1)
|
||||
self.uiTabWidget.addTab(self.uiAdvancedSettingsTabWidget, _fromUtf8(""))
|
||||
self.uiTabWidget.addTab(self.uiAdvancedSettingsTabWidget, "")
|
||||
self.vboxlayout.addWidget(self.uiTabWidget)
|
||||
self.horizontalLayout_2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
|
||||
spacerItem2 = QtGui.QSpacerItem(164, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
spacerItem2 = QtWidgets.QSpacerItem(164, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem2)
|
||||
self.uiRestoreDefaultsPushButton = QtGui.QPushButton(DynamipsPreferencesPageWidget)
|
||||
self.uiRestoreDefaultsPushButton.setObjectName(_fromUtf8("uiRestoreDefaultsPushButton"))
|
||||
self.uiRestoreDefaultsPushButton = QtWidgets.QPushButton(DynamipsPreferencesPageWidget)
|
||||
self.uiRestoreDefaultsPushButton.setObjectName("uiRestoreDefaultsPushButton")
|
||||
self.horizontalLayout_2.addWidget(self.uiRestoreDefaultsPushButton)
|
||||
self.vboxlayout.addLayout(self.horizontalLayout_2)
|
||||
|
||||
@@ -106,19 +92,20 @@ class Ui_DynamipsPreferencesPageWidget(object):
|
||||
DynamipsPreferencesPageWidget.setTabOrder(self.uiMmapSupportCheckBox, self.uiSparseMemorySupportCheckBox)
|
||||
|
||||
def retranslateUi(self, DynamipsPreferencesPageWidget):
|
||||
DynamipsPreferencesPageWidget.setWindowTitle(_translate("DynamipsPreferencesPageWidget", "Dynamips", None))
|
||||
self.uiUseLocalServercheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Use the local server", None))
|
||||
self.uiDynamipsPathLabel.setText(_translate("DynamipsPreferencesPageWidget", "Path to Dynamips:", None))
|
||||
self.uiDynamipsPathToolButton.setText(_translate("DynamipsPreferencesPageWidget", "&Browse...", None))
|
||||
self.uiAllocateAuxConsolePortsCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Allocate AUX console ports", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralSettingsTabWidget), _translate("DynamipsPreferencesPageWidget", "General settings", None))
|
||||
self.uiMemoryUsageOptimisationGroupBox.setTitle(_translate("DynamipsPreferencesPageWidget", "Memory usage optimisation", None))
|
||||
self.uiGhostIOSSupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The ghost IOS feature is a solution that helps to decrease memory usage by sharing an IOS image between different router instances.", None))
|
||||
self.uiGhostIOSSupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable ghost IOS support", None))
|
||||
self.uiMmapSupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The mmap feature tells Dynamips to use disk files instead of real memory for router instances.", None))
|
||||
self.uiMmapSupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable mmap support", None))
|
||||
self.uiSparseMemorySupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The sparse memory feature reduces the amount of virtual memory used by router instances.", None))
|
||||
self.uiSparseMemorySupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable sparse memory support", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiAdvancedSettingsTabWidget), _translate("DynamipsPreferencesPageWidget", "Advanced settings", None))
|
||||
self.uiRestoreDefaultsPushButton.setText(_translate("DynamipsPreferencesPageWidget", "Restore defaults", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DynamipsPreferencesPageWidget.setWindowTitle(_translate("DynamipsPreferencesPageWidget", "Dynamips"))
|
||||
self.uiUseLocalServercheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Use the local server"))
|
||||
self.uiDynamipsPathLabel.setText(_translate("DynamipsPreferencesPageWidget", "Path to Dynamips:"))
|
||||
self.uiDynamipsPathToolButton.setText(_translate("DynamipsPreferencesPageWidget", "&Browse..."))
|
||||
self.uiAllocateAuxConsolePortsCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Allocate AUX console ports"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralSettingsTabWidget), _translate("DynamipsPreferencesPageWidget", "General settings"))
|
||||
self.uiMemoryUsageOptimisationGroupBox.setTitle(_translate("DynamipsPreferencesPageWidget", "Memory usage optimisation"))
|
||||
self.uiGhostIOSSupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The ghost IOS feature is a solution that helps to decrease memory usage by sharing an IOS image between different router instances."))
|
||||
self.uiGhostIOSSupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable ghost IOS support"))
|
||||
self.uiMmapSupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The mmap feature tells Dynamips to use disk files instead of real memory for router instances."))
|
||||
self.uiMmapSupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable mmap support"))
|
||||
self.uiSparseMemorySupportCheckBox.setToolTip(_translate("DynamipsPreferencesPageWidget", "The sparse memory feature reduces the amount of virtual memory used by router instances."))
|
||||
self.uiSparseMemorySupportCheckBox.setText(_translate("DynamipsPreferencesPageWidget", "Enable sparse memory support"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiAdvancedSettingsTabWidget), _translate("DynamipsPreferencesPageWidget", "Advanced settings"))
|
||||
self.uiRestoreDefaultsPushButton.setText(_translate("DynamipsPreferencesPageWidget", "Restore defaults"))
|
||||
|
||||
|
||||
@@ -1,57 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/ethernet_hub_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/ethernet_hub_configuration_page.ui'
|
||||
#
|
||||
# Created: Sun Mar 16 11:16:57 2014
|
||||
# by: PyQt4 UI code generator 4.10
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_ethernetHubConfigPageWidget(object):
|
||||
|
||||
def setupUi(self, ethernetHubConfigPageWidget):
|
||||
ethernetHubConfigPageWidget.setObjectName(_fromUtf8("ethernetHubConfigPageWidget"))
|
||||
ethernetHubConfigPageWidget.setObjectName("ethernetHubConfigPageWidget")
|
||||
ethernetHubConfigPageWidget.resize(381, 270)
|
||||
self.gridlayout = QtGui.QGridLayout(ethernetHubConfigPageWidget)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiSettingsGroupBox = QtGui.QGroupBox(ethernetHubConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.gridlayout = QtWidgets.QGridLayout(ethernetHubConfigPageWidget)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiSettingsGroupBox = QtWidgets.QGroupBox(ethernetHubConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSettingsGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSettingsGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiSettingsGroupBox.setObjectName(_fromUtf8("uiSettingsGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiSettingsGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiSettingsGroupBox)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.uiSettingsGroupBox.setObjectName("uiSettingsGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiSettingsGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiSettingsGroupBox)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiSettingsGroupBox)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiSettingsGroupBox)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.uiPortsLabel = QtGui.QLabel(self.uiSettingsGroupBox)
|
||||
self.uiPortsLabel.setObjectName(_fromUtf8("uiPortsLabel"))
|
||||
self.uiPortsLabel = QtWidgets.QLabel(self.uiSettingsGroupBox)
|
||||
self.uiPortsLabel.setObjectName("uiPortsLabel")
|
||||
self.gridLayout.addWidget(self.uiPortsLabel, 1, 0, 1, 1)
|
||||
self.uiPortsSpinBox = QtGui.QSpinBox(self.uiSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiPortsSpinBox = QtWidgets.QSpinBox(self.uiSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPortsSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -59,9 +42,9 @@ class Ui_ethernetHubConfigPageWidget(object):
|
||||
self.uiPortsSpinBox.setMinimum(0)
|
||||
self.uiPortsSpinBox.setMaximum(65535)
|
||||
self.uiPortsSpinBox.setProperty("value", 1)
|
||||
self.uiPortsSpinBox.setObjectName(_fromUtf8("uiPortsSpinBox"))
|
||||
self.uiPortsSpinBox.setObjectName("uiPortsSpinBox")
|
||||
self.gridLayout.addWidget(self.uiPortsSpinBox, 1, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(20, 71, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 71, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem, 2, 1, 1, 1)
|
||||
self.gridlayout.addWidget(self.uiSettingsGroupBox, 0, 1, 1, 1)
|
||||
|
||||
@@ -69,7 +52,9 @@ class Ui_ethernetHubConfigPageWidget(object):
|
||||
QtCore.QMetaObject.connectSlotsByName(ethernetHubConfigPageWidget)
|
||||
|
||||
def retranslateUi(self, ethernetHubConfigPageWidget):
|
||||
ethernetHubConfigPageWidget.setWindowTitle(_translate("ethernetHubConfigPageWidget", "Ethernet hub", None))
|
||||
self.uiSettingsGroupBox.setTitle(_translate("ethernetHubConfigPageWidget", "Settings", None))
|
||||
self.uiNameLabel.setText(_translate("ethernetHubConfigPageWidget", "Name:", None))
|
||||
self.uiPortsLabel.setText(_translate("ethernetHubConfigPageWidget", "Number of ports:", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ethernetHubConfigPageWidget.setWindowTitle(_translate("ethernetHubConfigPageWidget", "Ethernet hub"))
|
||||
self.uiSettingsGroupBox.setTitle(_translate("ethernetHubConfigPageWidget", "Settings"))
|
||||
self.uiNameLabel.setText(_translate("ethernetHubConfigPageWidget", "Name:"))
|
||||
self.uiPortsLabel.setText(_translate("ethernetHubConfigPageWidget", "Number of ports:"))
|
||||
|
||||
|
||||
@@ -1,76 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/dynamips/ui/ethernet_switch_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/ethernet_switch_configuration_page.ui'
|
||||
#
|
||||
# Created: Thu Jul 17 16:13:17 2014
|
||||
# by: PyQt4 UI code generator 4.10.4
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_ethernetSwitchConfigPageWidget(object):
|
||||
|
||||
def setupUi(self, ethernetSwitchConfigPageWidget):
|
||||
ethernetSwitchConfigPageWidget.setObjectName(_fromUtf8("ethernetSwitchConfigPageWidget"))
|
||||
ethernetSwitchConfigPageWidget.setObjectName("ethernetSwitchConfigPageWidget")
|
||||
ethernetSwitchConfigPageWidget.resize(397, 315)
|
||||
self.gridLayout_2 = QtGui.QGridLayout(ethernetSwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiGeneralGroupBox = QtGui.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName(_fromUtf8("uiGeneralGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(ethernetSwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiGeneralGroupBox = QtWidgets.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName("uiGeneralGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiGeneralGroupBox, 0, 0, 1, 2)
|
||||
self.uiEthernetSwitchPortsGroupBox = QtGui.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
self.uiEthernetSwitchPortsGroupBox.setObjectName(_fromUtf8("uiEthernetSwitchPortsGroupBox"))
|
||||
self.vboxlayout = QtGui.QVBoxLayout(self.uiEthernetSwitchPortsGroupBox)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiPortsTreeWidget = QtGui.QTreeWidget(self.uiEthernetSwitchPortsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
self.uiEthernetSwitchPortsGroupBox = QtWidgets.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
self.uiEthernetSwitchPortsGroupBox.setObjectName("uiEthernetSwitchPortsGroupBox")
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(self.uiEthernetSwitchPortsGroupBox)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiPortsTreeWidget = QtWidgets.QTreeWidget(self.uiEthernetSwitchPortsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPortsTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiPortsTreeWidget.setSizePolicy(sizePolicy)
|
||||
self.uiPortsTreeWidget.setRootIsDecorated(False)
|
||||
self.uiPortsTreeWidget.setObjectName(_fromUtf8("uiPortsTreeWidget"))
|
||||
self.uiPortsTreeWidget.setObjectName("uiPortsTreeWidget")
|
||||
self.vboxlayout.addWidget(self.uiPortsTreeWidget)
|
||||
self.gridLayout_2.addWidget(self.uiEthernetSwitchPortsGroupBox, 0, 2, 3, 1)
|
||||
self.uiEthernetSwitchSettingsGroupBox = QtGui.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiEthernetSwitchSettingsGroupBox = QtWidgets.QGroupBox(ethernetSwitchConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiEthernetSwitchSettingsGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiEthernetSwitchSettingsGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiEthernetSwitchSettingsGroupBox.setObjectName(_fromUtf8("uiEthernetSwitchSettingsGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.label = QtGui.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.uiEthernetSwitchSettingsGroupBox.setObjectName("uiEthernetSwitchSettingsGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.label = QtWidgets.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label.setObjectName("label")
|
||||
self.gridlayout.addWidget(self.label, 0, 0, 1, 1)
|
||||
self.uiPortSpinBox = QtGui.QSpinBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiPortSpinBox = QtWidgets.QSpinBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -78,13 +61,13 @@ class Ui_ethernetSwitchConfigPageWidget(object):
|
||||
self.uiPortSpinBox.setMinimum(1)
|
||||
self.uiPortSpinBox.setMaximum(65535)
|
||||
self.uiPortSpinBox.setProperty("value", 1)
|
||||
self.uiPortSpinBox.setObjectName(_fromUtf8("uiPortSpinBox"))
|
||||
self.uiPortSpinBox.setObjectName("uiPortSpinBox")
|
||||
self.gridlayout.addWidget(self.uiPortSpinBox, 0, 1, 1, 1)
|
||||
self.label_3 = QtGui.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.label_3 = QtWidgets.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridlayout.addWidget(self.label_3, 1, 0, 1, 1)
|
||||
self.uiVlanSpinBox = QtGui.QSpinBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiVlanSpinBox = QtWidgets.QSpinBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiVlanSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -92,28 +75,28 @@ class Ui_ethernetSwitchConfigPageWidget(object):
|
||||
self.uiVlanSpinBox.setMinimum(1)
|
||||
self.uiVlanSpinBox.setMaximum(65535)
|
||||
self.uiVlanSpinBox.setProperty("value", 1)
|
||||
self.uiVlanSpinBox.setObjectName(_fromUtf8("uiVlanSpinBox"))
|
||||
self.uiVlanSpinBox.setObjectName("uiVlanSpinBox")
|
||||
self.gridlayout.addWidget(self.uiVlanSpinBox, 1, 1, 1, 1)
|
||||
self.label_2 = QtGui.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.label_2 = QtWidgets.QLabel(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridlayout.addWidget(self.label_2, 2, 0, 1, 1)
|
||||
self.uiPortTypeComboBox = QtGui.QComboBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.uiPortTypeComboBox.setObjectName(_fromUtf8("uiPortTypeComboBox"))
|
||||
self.uiPortTypeComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPortTypeComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPortTypeComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPortTypeComboBox = QtWidgets.QComboBox(self.uiEthernetSwitchSettingsGroupBox)
|
||||
self.uiPortTypeComboBox.setObjectName("uiPortTypeComboBox")
|
||||
self.uiPortTypeComboBox.addItem("")
|
||||
self.uiPortTypeComboBox.addItem("")
|
||||
self.uiPortTypeComboBox.addItem("")
|
||||
self.gridlayout.addWidget(self.uiPortTypeComboBox, 2, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiEthernetSwitchSettingsGroupBox, 1, 0, 1, 2)
|
||||
self.uiAddPushButton = QtGui.QPushButton(ethernetSwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName(_fromUtf8("uiAddPushButton"))
|
||||
self.uiAddPushButton = QtWidgets.QPushButton(ethernetSwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName("uiAddPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiAddPushButton, 2, 0, 1, 1)
|
||||
self.uiDeletePushButton = QtGui.QPushButton(ethernetSwitchConfigPageWidget)
|
||||
self.uiDeletePushButton = QtWidgets.QPushButton(ethernetSwitchConfigPageWidget)
|
||||
self.uiDeletePushButton.setEnabled(False)
|
||||
self.uiDeletePushButton.setObjectName(_fromUtf8("uiDeletePushButton"))
|
||||
self.uiDeletePushButton.setObjectName("uiDeletePushButton")
|
||||
self.gridLayout_2.addWidget(self.uiDeletePushButton, 2, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(20, 71, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 71, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 3, 1, 1, 1)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem1, 3, 2, 1, 1)
|
||||
|
||||
self.retranslateUi(ethernetSwitchConfigPageWidget)
|
||||
@@ -125,19 +108,21 @@ class Ui_ethernetSwitchConfigPageWidget(object):
|
||||
ethernetSwitchConfigPageWidget.setTabOrder(self.uiDeletePushButton, self.uiPortsTreeWidget)
|
||||
|
||||
def retranslateUi(self, ethernetSwitchConfigPageWidget):
|
||||
ethernetSwitchConfigPageWidget.setWindowTitle(_translate("ethernetSwitchConfigPageWidget", "Ethernet switch configuration", None))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "General", None))
|
||||
self.uiNameLabel.setText(_translate("ethernetSwitchConfigPageWidget", "Name:", None))
|
||||
self.uiEthernetSwitchPortsGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "Ports", None))
|
||||
self.uiPortsTreeWidget.headerItem().setText(0, _translate("ethernetSwitchConfigPageWidget", "Port", None))
|
||||
self.uiPortsTreeWidget.headerItem().setText(1, _translate("ethernetSwitchConfigPageWidget", "VLAN", None))
|
||||
self.uiPortsTreeWidget.headerItem().setText(2, _translate("ethernetSwitchConfigPageWidget", "Type", None))
|
||||
self.uiEthernetSwitchSettingsGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "Settings", None))
|
||||
self.label.setText(_translate("ethernetSwitchConfigPageWidget", "Port:", None))
|
||||
self.label_3.setText(_translate("ethernetSwitchConfigPageWidget", "VLAN:", None))
|
||||
self.label_2.setText(_translate("ethernetSwitchConfigPageWidget", "Type:", None))
|
||||
self.uiPortTypeComboBox.setItemText(0, _translate("ethernetSwitchConfigPageWidget", "access", None))
|
||||
self.uiPortTypeComboBox.setItemText(1, _translate("ethernetSwitchConfigPageWidget", "dot1q", None))
|
||||
self.uiPortTypeComboBox.setItemText(2, _translate("ethernetSwitchConfigPageWidget", "qinq", None))
|
||||
self.uiAddPushButton.setText(_translate("ethernetSwitchConfigPageWidget", "&Add", None))
|
||||
self.uiDeletePushButton.setText(_translate("ethernetSwitchConfigPageWidget", "&Delete", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ethernetSwitchConfigPageWidget.setWindowTitle(_translate("ethernetSwitchConfigPageWidget", "Ethernet switch configuration"))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "General"))
|
||||
self.uiNameLabel.setText(_translate("ethernetSwitchConfigPageWidget", "Name:"))
|
||||
self.uiEthernetSwitchPortsGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "Ports"))
|
||||
self.uiPortsTreeWidget.headerItem().setText(0, _translate("ethernetSwitchConfigPageWidget", "Port"))
|
||||
self.uiPortsTreeWidget.headerItem().setText(1, _translate("ethernetSwitchConfigPageWidget", "VLAN"))
|
||||
self.uiPortsTreeWidget.headerItem().setText(2, _translate("ethernetSwitchConfigPageWidget", "Type"))
|
||||
self.uiEthernetSwitchSettingsGroupBox.setTitle(_translate("ethernetSwitchConfigPageWidget", "Settings"))
|
||||
self.label.setText(_translate("ethernetSwitchConfigPageWidget", "Port:"))
|
||||
self.label_3.setText(_translate("ethernetSwitchConfigPageWidget", "VLAN:"))
|
||||
self.label_2.setText(_translate("ethernetSwitchConfigPageWidget", "Type:"))
|
||||
self.uiPortTypeComboBox.setItemText(0, _translate("ethernetSwitchConfigPageWidget", "access"))
|
||||
self.uiPortTypeComboBox.setItemText(1, _translate("ethernetSwitchConfigPageWidget", "dot1q"))
|
||||
self.uiPortTypeComboBox.setItemText(2, _translate("ethernetSwitchConfigPageWidget", "qinq"))
|
||||
self.uiAddPushButton.setText(_translate("ethernetSwitchConfigPageWidget", "&Add"))
|
||||
self.uiDeletePushButton.setText(_translate("ethernetSwitchConfigPageWidget", "&Delete"))
|
||||
|
||||
|
||||
@@ -1,76 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/frame_relay_switch_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/frame_relay_switch_configuration_page.ui'
|
||||
#
|
||||
# Created: Sun Mar 16 13:50:36 2014
|
||||
# by: PyQt4 UI code generator 4.10
|
||||
# Created: Wed Jul 15 12:22:32 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_frameRelaySwitchConfigPageWidget(object):
|
||||
|
||||
def setupUi(self, frameRelaySwitchConfigPageWidget):
|
||||
frameRelaySwitchConfigPageWidget.setObjectName(_fromUtf8("frameRelaySwitchConfigPageWidget"))
|
||||
frameRelaySwitchConfigPageWidget.setObjectName("frameRelaySwitchConfigPageWidget")
|
||||
frameRelaySwitchConfigPageWidget.resize(499, 405)
|
||||
self.gridLayout_2 = QtGui.QGridLayout(frameRelaySwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiGeneralGroupBox = QtGui.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName(_fromUtf8("uiGeneralGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(frameRelaySwitchConfigPageWidget)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiGeneralGroupBox = QtWidgets.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
self.uiGeneralGroupBox.setObjectName("uiGeneralGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiGeneralGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiGeneralGroupBox)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiGeneralGroupBox)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiGeneralGroupBox, 0, 0, 1, 2)
|
||||
self.uiFrameRelayMappingGroupBox = QtGui.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
self.uiFrameRelayMappingGroupBox.setObjectName(_fromUtf8("uiFrameRelayMappingGroupBox"))
|
||||
self.vboxlayout = QtGui.QVBoxLayout(self.uiFrameRelayMappingGroupBox)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiMappingTreeWidget = QtGui.QTreeWidget(self.uiFrameRelayMappingGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
self.uiFrameRelayMappingGroupBox = QtWidgets.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
self.uiFrameRelayMappingGroupBox.setObjectName("uiFrameRelayMappingGroupBox")
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(self.uiFrameRelayMappingGroupBox)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiMappingTreeWidget = QtWidgets.QTreeWidget(self.uiFrameRelayMappingGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiMappingTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiMappingTreeWidget.setSizePolicy(sizePolicy)
|
||||
self.uiMappingTreeWidget.setRootIsDecorated(False)
|
||||
self.uiMappingTreeWidget.setObjectName(_fromUtf8("uiMappingTreeWidget"))
|
||||
self.uiMappingTreeWidget.setObjectName("uiMappingTreeWidget")
|
||||
self.vboxlayout.addWidget(self.uiMappingTreeWidget)
|
||||
self.gridLayout_2.addWidget(self.uiFrameRelayMappingGroupBox, 0, 2, 4, 1)
|
||||
self.uiFrameRelaySourceGroupBox = QtGui.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiFrameRelaySourceGroupBox = QtWidgets.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiFrameRelaySourceGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiFrameRelaySourceGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiFrameRelaySourceGroupBox.setObjectName(_fromUtf8("uiFrameRelaySourceGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiFrameRelaySourceGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiSourcePortLabel = QtGui.QLabel(self.uiFrameRelaySourceGroupBox)
|
||||
self.uiSourcePortLabel.setObjectName(_fromUtf8("uiSourcePortLabel"))
|
||||
self.uiFrameRelaySourceGroupBox.setObjectName("uiFrameRelaySourceGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiFrameRelaySourceGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiSourcePortLabel = QtWidgets.QLabel(self.uiFrameRelaySourceGroupBox)
|
||||
self.uiSourcePortLabel.setObjectName("uiSourcePortLabel")
|
||||
self.gridlayout.addWidget(self.uiSourcePortLabel, 0, 0, 1, 1)
|
||||
self.uiSourcePortSpinBox = QtGui.QSpinBox(self.uiFrameRelaySourceGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSourcePortSpinBox = QtWidgets.QSpinBox(self.uiFrameRelaySourceGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourcePortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -78,36 +61,36 @@ class Ui_frameRelaySwitchConfigPageWidget(object):
|
||||
self.uiSourcePortSpinBox.setMinimum(0)
|
||||
self.uiSourcePortSpinBox.setMaximum(65535)
|
||||
self.uiSourcePortSpinBox.setProperty("value", 1)
|
||||
self.uiSourcePortSpinBox.setObjectName(_fromUtf8("uiSourcePortSpinBox"))
|
||||
self.uiSourcePortSpinBox.setObjectName("uiSourcePortSpinBox")
|
||||
self.gridlayout.addWidget(self.uiSourcePortSpinBox, 0, 1, 1, 1)
|
||||
self.uiSourceDLCILabel = QtGui.QLabel(self.uiFrameRelaySourceGroupBox)
|
||||
self.uiSourceDLCILabel.setObjectName(_fromUtf8("uiSourceDLCILabel"))
|
||||
self.uiSourceDLCILabel = QtWidgets.QLabel(self.uiFrameRelaySourceGroupBox)
|
||||
self.uiSourceDLCILabel.setObjectName("uiSourceDLCILabel")
|
||||
self.gridlayout.addWidget(self.uiSourceDLCILabel, 1, 0, 1, 1)
|
||||
self.uiSourceDLCISpinBox = QtGui.QSpinBox(self.uiFrameRelaySourceGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSourceDLCISpinBox = QtWidgets.QSpinBox(self.uiFrameRelaySourceGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSourceDLCISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSourceDLCISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSourceDLCISpinBox.setMaximum(65535)
|
||||
self.uiSourceDLCISpinBox.setProperty("value", 101)
|
||||
self.uiSourceDLCISpinBox.setObjectName(_fromUtf8("uiSourceDLCISpinBox"))
|
||||
self.uiSourceDLCISpinBox.setObjectName("uiSourceDLCISpinBox")
|
||||
self.gridlayout.addWidget(self.uiSourceDLCISpinBox, 1, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiFrameRelaySourceGroupBox, 1, 0, 1, 2)
|
||||
self.uiFrameRelayDestinationGroupBox = QtGui.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.uiFrameRelayDestinationGroupBox = QtWidgets.QGroupBox(frameRelaySwitchConfigPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiFrameRelayDestinationGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiFrameRelayDestinationGroupBox.setSizePolicy(sizePolicy)
|
||||
self.uiFrameRelayDestinationGroupBox.setObjectName(_fromUtf8("uiFrameRelayDestinationGroupBox"))
|
||||
self.gridlayout1 = QtGui.QGridLayout(self.uiFrameRelayDestinationGroupBox)
|
||||
self.gridlayout1.setObjectName(_fromUtf8("gridlayout1"))
|
||||
self.uiDestinationPortLabel = QtGui.QLabel(self.uiFrameRelayDestinationGroupBox)
|
||||
self.uiDestinationPortLabel.setObjectName(_fromUtf8("uiDestinationPortLabel"))
|
||||
self.uiFrameRelayDestinationGroupBox.setObjectName("uiFrameRelayDestinationGroupBox")
|
||||
self.gridlayout1 = QtWidgets.QGridLayout(self.uiFrameRelayDestinationGroupBox)
|
||||
self.gridlayout1.setObjectName("gridlayout1")
|
||||
self.uiDestinationPortLabel = QtWidgets.QLabel(self.uiFrameRelayDestinationGroupBox)
|
||||
self.uiDestinationPortLabel.setObjectName("uiDestinationPortLabel")
|
||||
self.gridlayout1.addWidget(self.uiDestinationPortLabel, 0, 0, 1, 1)
|
||||
self.uiDestinationPortSpinBox = QtGui.QSpinBox(self.uiFrameRelayDestinationGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDestinationPortSpinBox = QtWidgets.QSpinBox(self.uiFrameRelayDestinationGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationPortSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -115,30 +98,30 @@ class Ui_frameRelaySwitchConfigPageWidget(object):
|
||||
self.uiDestinationPortSpinBox.setMinimum(0)
|
||||
self.uiDestinationPortSpinBox.setMaximum(65535)
|
||||
self.uiDestinationPortSpinBox.setProperty("value", 10)
|
||||
self.uiDestinationPortSpinBox.setObjectName(_fromUtf8("uiDestinationPortSpinBox"))
|
||||
self.uiDestinationPortSpinBox.setObjectName("uiDestinationPortSpinBox")
|
||||
self.gridlayout1.addWidget(self.uiDestinationPortSpinBox, 0, 1, 1, 1)
|
||||
self.uiDestinationDLCILabel = QtGui.QLabel(self.uiFrameRelayDestinationGroupBox)
|
||||
self.uiDestinationDLCILabel.setObjectName(_fromUtf8("uiDestinationDLCILabel"))
|
||||
self.uiDestinationDLCILabel = QtWidgets.QLabel(self.uiFrameRelayDestinationGroupBox)
|
||||
self.uiDestinationDLCILabel.setObjectName("uiDestinationDLCILabel")
|
||||
self.gridlayout1.addWidget(self.uiDestinationDLCILabel, 1, 0, 1, 1)
|
||||
self.uiDestinationDLCISpinBox = QtGui.QSpinBox(self.uiFrameRelayDestinationGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDestinationDLCISpinBox = QtWidgets.QSpinBox(self.uiFrameRelayDestinationGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDestinationDLCISpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDestinationDLCISpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiDestinationDLCISpinBox.setMaximum(65535)
|
||||
self.uiDestinationDLCISpinBox.setProperty("value", 202)
|
||||
self.uiDestinationDLCISpinBox.setObjectName(_fromUtf8("uiDestinationDLCISpinBox"))
|
||||
self.uiDestinationDLCISpinBox.setObjectName("uiDestinationDLCISpinBox")
|
||||
self.gridlayout1.addWidget(self.uiDestinationDLCISpinBox, 1, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.uiFrameRelayDestinationGroupBox, 2, 0, 1, 2)
|
||||
self.uiAddPushButton = QtGui.QPushButton(frameRelaySwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName(_fromUtf8("uiAddPushButton"))
|
||||
self.uiAddPushButton = QtWidgets.QPushButton(frameRelaySwitchConfigPageWidget)
|
||||
self.uiAddPushButton.setObjectName("uiAddPushButton")
|
||||
self.gridLayout_2.addWidget(self.uiAddPushButton, 3, 0, 1, 1)
|
||||
self.uiDeletePushButton = QtGui.QPushButton(frameRelaySwitchConfigPageWidget)
|
||||
self.uiDeletePushButton = QtWidgets.QPushButton(frameRelaySwitchConfigPageWidget)
|
||||
self.uiDeletePushButton.setEnabled(False)
|
||||
self.uiDeletePushButton.setObjectName(_fromUtf8("uiDeletePushButton"))
|
||||
self.uiDeletePushButton.setObjectName("uiDeletePushButton")
|
||||
self.gridLayout_2.addWidget(self.uiDeletePushButton, 3, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 4, 2, 1, 1)
|
||||
|
||||
self.retranslateUi(frameRelaySwitchConfigPageWidget)
|
||||
@@ -150,17 +133,19 @@ class Ui_frameRelaySwitchConfigPageWidget(object):
|
||||
frameRelaySwitchConfigPageWidget.setTabOrder(self.uiAddPushButton, self.uiDeletePushButton)
|
||||
|
||||
def retranslateUi(self, frameRelaySwitchConfigPageWidget):
|
||||
frameRelaySwitchConfigPageWidget.setWindowTitle(_translate("frameRelaySwitchConfigPageWidget", "Frame Relay Switch", None))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "General", None))
|
||||
self.uiNameLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Name:", None))
|
||||
self.uiFrameRelayMappingGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Mapping", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("frameRelaySwitchConfigPageWidget", "Port:DLCI", None))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("frameRelaySwitchConfigPageWidget", "Port:DLCI", None))
|
||||
self.uiFrameRelaySourceGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Source", None))
|
||||
self.uiSourcePortLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Port:", None))
|
||||
self.uiSourceDLCILabel.setText(_translate("frameRelaySwitchConfigPageWidget", "DLCI:", None))
|
||||
self.uiFrameRelayDestinationGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Destination", None))
|
||||
self.uiDestinationPortLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Port:", None))
|
||||
self.uiDestinationDLCILabel.setText(_translate("frameRelaySwitchConfigPageWidget", "DLCI:", None))
|
||||
self.uiAddPushButton.setText(_translate("frameRelaySwitchConfigPageWidget", "&Add", None))
|
||||
self.uiDeletePushButton.setText(_translate("frameRelaySwitchConfigPageWidget", "&Delete", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
frameRelaySwitchConfigPageWidget.setWindowTitle(_translate("frameRelaySwitchConfigPageWidget", "Frame Relay Switch"))
|
||||
self.uiGeneralGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "General"))
|
||||
self.uiNameLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Name:"))
|
||||
self.uiFrameRelayMappingGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Mapping"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(0, _translate("frameRelaySwitchConfigPageWidget", "Port:DLCI"))
|
||||
self.uiMappingTreeWidget.headerItem().setText(1, _translate("frameRelaySwitchConfigPageWidget", "Port:DLCI"))
|
||||
self.uiFrameRelaySourceGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Source"))
|
||||
self.uiSourcePortLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Port:"))
|
||||
self.uiSourceDLCILabel.setText(_translate("frameRelaySwitchConfigPageWidget", "DLCI:"))
|
||||
self.uiFrameRelayDestinationGroupBox.setTitle(_translate("frameRelaySwitchConfigPageWidget", "Destination"))
|
||||
self.uiDestinationPortLabel.setText(_translate("frameRelaySwitchConfigPageWidget", "Port:"))
|
||||
self.uiDestinationDLCILabel.setText(_translate("frameRelaySwitchConfigPageWidget", "DLCI:"))
|
||||
self.uiAddPushButton.setText(_translate("frameRelaySwitchConfigPageWidget", "&Add"))
|
||||
self.uiDeletePushButton.setText(_translate("frameRelaySwitchConfigPageWidget", "&Delete"))
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>449</width>
|
||||
<height>491</height>
|
||||
<width>476</width>
|
||||
<height>506</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -34,42 +34,42 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="uiNameLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="uiPlatformLabel">
|
||||
<property name="text">
|
||||
<string>Platform:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="uiPlatformTextLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="uiChassisLabel">
|
||||
<property name="text">
|
||||
<string>Chassis:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="uiChassisTextLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="uiIOSImageLabel">
|
||||
<property name="text">
|
||||
<string>IOS image path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiIOSImageLineEdit"/>
|
||||
@@ -86,14 +86,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="uiStartupConfigLabel">
|
||||
<property name="text">
|
||||
<string>Initial startup-config:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiStartupConfigLineEdit"/>
|
||||
@@ -110,14 +110,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="uiPrivateConfigLabel">
|
||||
<property name="text">
|
||||
<string>Initial private-config:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="10" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiPrivateConfigLineEdit"/>
|
||||
@@ -134,42 +134,42 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="uiConsolePortLabel">
|
||||
<property name="text">
|
||||
<string>Console port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QSpinBox" name="uiConsolePortSpinBox">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="uiAuxPortLabel">
|
||||
<property name="text">
|
||||
<string>Aux port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="uiAuxPortSpinBox">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="uiMidplaneLabel">
|
||||
<property name="text">
|
||||
<string>Midplane:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="15" column="1">
|
||||
<widget class="QComboBox" name="uiMidplaneComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -182,27 +182,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="uiNPELabel">
|
||||
<property name="text">
|
||||
<string>NPE:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="uiNPEComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="17" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -215,180 +202,216 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QComboBox" name="uiNPEComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="uiSymbolLabel">
|
||||
<property name="text">
|
||||
<string>Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiSymbolLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="uiSymbolToolButton">
|
||||
<property name="text">
|
||||
<string>&Browse...</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="uiCategoryLabel">
|
||||
<property name="text">
|
||||
<string>Category:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="uiCategoryComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="uiMemoriesPageWidget">
|
||||
<attribute name="title">
|
||||
<string>Memories and disks</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="uiMemoriesGroupBox">
|
||||
<property name="title">
|
||||
<string>Memories</string>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiRamLabel">
|
||||
<property name="text">
|
||||
<string>RAM size:</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiRamLabel">
|
||||
<property name="text">
|
||||
<string>RAM size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="uiRamSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiNvramLabel">
|
||||
<property name="text">
|
||||
<string>NVRAM size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="uiNvramSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> KiB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uiIomemLabel">
|
||||
<property name="text">
|
||||
<string>I/O memory :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="uiIomemSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> %</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="uiDisksGroupBox">
|
||||
<property name="title">
|
||||
<string>Disks</string>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="uiRamSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiDisk0Label">
|
||||
<property name="text">
|
||||
<string>PCMCIA disk0 size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="uiDisk0SpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiDisk1Label">
|
||||
<property name="text">
|
||||
<string>PCMCIA disk1 size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="uiDisk1SpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiNvramLabel">
|
||||
<property name="text">
|
||||
<string>NVRAM size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="uiNvramSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> KiB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uiIomemLabel">
|
||||
<property name="text">
|
||||
<string>I/O memory :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="uiIomemSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> %</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="uiDisk0Label">
|
||||
<property name="text">
|
||||
<string>PCMCIA disk0:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="uiDisk0SpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="uiDisk1Label">
|
||||
<property name="text">
|
||||
<string>PCMCIA disk1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="uiDisk1SpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MiB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="uiAutoDeleteCheckBox">
|
||||
<property name="text">
|
||||
<string>Automatically delete NVRAM and disk files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -974,10 +997,6 @@
|
||||
<tabstops>
|
||||
<tabstop>uiMidplaneComboBox</tabstop>
|
||||
<tabstop>uiNPEComboBox</tabstop>
|
||||
<tabstop>uiRamSpinBox</tabstop>
|
||||
<tabstop>uiNvramSpinBox</tabstop>
|
||||
<tabstop>uiDisk0SpinBox</tabstop>
|
||||
<tabstop>uiDisk1SpinBox</tabstop>
|
||||
<tabstop>uiSlot0comboBox</tabstop>
|
||||
<tabstop>uiSlot1comboBox</tabstop>
|
||||
<tabstop>uiSlot2comboBox</tabstop>
|
||||
|
||||
@@ -1,153 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/dynamips/ui/ios_router_configuration_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/ios_router_configuration_page.ui'
|
||||
#
|
||||
# Created: Sat Mar 14 16:29:27 2015
|
||||
# by: PyQt4 UI code generator 4.10.4
|
||||
# Created: Wed Jul 15 12:22:33 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_iosRouterConfigPageWidget(object):
|
||||
def setupUi(self, iosRouterConfigPageWidget):
|
||||
iosRouterConfigPageWidget.setObjectName(_fromUtf8("iosRouterConfigPageWidget"))
|
||||
iosRouterConfigPageWidget.resize(449, 491)
|
||||
self.vboxlayout = QtGui.QVBoxLayout(iosRouterConfigPageWidget)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.uiTabWidget = QtGui.QTabWidget(iosRouterConfigPageWidget)
|
||||
self.uiTabWidget.setObjectName(_fromUtf8("uiTabWidget"))
|
||||
self.uiGeneralPageWidget = QtGui.QWidget()
|
||||
self.uiGeneralPageWidget.setObjectName(_fromUtf8("uiGeneralPageWidget"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.uiGeneralPageWidget)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.uiNameLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
|
||||
iosRouterConfigPageWidget.setObjectName("iosRouterConfigPageWidget")
|
||||
iosRouterConfigPageWidget.resize(476, 506)
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(iosRouterConfigPageWidget)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.uiTabWidget = QtWidgets.QTabWidget(iosRouterConfigPageWidget)
|
||||
self.uiTabWidget.setObjectName("uiTabWidget")
|
||||
self.uiGeneralPageWidget = QtWidgets.QWidget()
|
||||
self.uiGeneralPageWidget.setObjectName("uiGeneralPageWidget")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.uiGeneralPageWidget)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.uiNameLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiNameLabel.setObjectName("uiNameLabel")
|
||||
self.gridLayout_2.addWidget(self.uiNameLabel, 0, 0, 1, 1)
|
||||
self.uiNameLineEdit = QtGui.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
|
||||
self.uiNameLineEdit = QtWidgets.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiNameLineEdit.setObjectName("uiNameLineEdit")
|
||||
self.gridLayout_2.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
|
||||
self.uiPlatformLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPlatformLabel.setObjectName(_fromUtf8("uiPlatformLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiPlatformLabel, 1, 0, 1, 1)
|
||||
self.uiPlatformTextLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPlatformTextLabel.setText(_fromUtf8(""))
|
||||
self.uiPlatformTextLabel.setObjectName(_fromUtf8("uiPlatformTextLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiPlatformTextLabel, 1, 1, 1, 1)
|
||||
self.uiChassisLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiChassisLabel.setObjectName(_fromUtf8("uiChassisLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiChassisLabel, 2, 0, 1, 1)
|
||||
self.uiChassisTextLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiChassisTextLabel.setText(_fromUtf8(""))
|
||||
self.uiChassisTextLabel.setObjectName(_fromUtf8("uiChassisTextLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiChassisTextLabel, 2, 1, 1, 1)
|
||||
self.uiIOSImageLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageLabel.setObjectName(_fromUtf8("uiIOSImageLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiIOSImageLabel, 3, 0, 1, 1)
|
||||
self.horizontalLayout_5 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
|
||||
self.uiIOSImageLineEdit = QtGui.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageLineEdit.setObjectName(_fromUtf8("uiIOSImageLineEdit"))
|
||||
self.uiPlatformLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPlatformLabel.setObjectName("uiPlatformLabel")
|
||||
self.gridLayout_2.addWidget(self.uiPlatformLabel, 3, 0, 1, 1)
|
||||
self.uiPlatformTextLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPlatformTextLabel.setText("")
|
||||
self.uiPlatformTextLabel.setObjectName("uiPlatformTextLabel")
|
||||
self.gridLayout_2.addWidget(self.uiPlatformTextLabel, 3, 1, 1, 1)
|
||||
self.uiChassisLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiChassisLabel.setObjectName("uiChassisLabel")
|
||||
self.gridLayout_2.addWidget(self.uiChassisLabel, 4, 0, 1, 1)
|
||||
self.uiChassisTextLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiChassisTextLabel.setText("")
|
||||
self.uiChassisTextLabel.setObjectName("uiChassisTextLabel")
|
||||
self.gridLayout_2.addWidget(self.uiChassisTextLabel, 4, 1, 1, 1)
|
||||
self.uiIOSImageLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageLabel.setObjectName("uiIOSImageLabel")
|
||||
self.gridLayout_2.addWidget(self.uiIOSImageLabel, 8, 0, 1, 1)
|
||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
||||
self.uiIOSImageLineEdit = QtWidgets.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageLineEdit.setObjectName("uiIOSImageLineEdit")
|
||||
self.horizontalLayout_5.addWidget(self.uiIOSImageLineEdit)
|
||||
self.uiIOSImageToolButton = QtGui.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageToolButton = QtWidgets.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiIOSImageToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||
self.uiIOSImageToolButton.setObjectName(_fromUtf8("uiIOSImageToolButton"))
|
||||
self.uiIOSImageToolButton.setObjectName("uiIOSImageToolButton")
|
||||
self.horizontalLayout_5.addWidget(self.uiIOSImageToolButton)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_5, 3, 1, 1, 1)
|
||||
self.uiStartupConfigLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigLabel.setObjectName(_fromUtf8("uiStartupConfigLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiStartupConfigLabel, 4, 0, 1, 1)
|
||||
self.horizontalLayout_4 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
|
||||
self.uiStartupConfigLineEdit = QtGui.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigLineEdit.setObjectName(_fromUtf8("uiStartupConfigLineEdit"))
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_5, 8, 1, 1, 1)
|
||||
self.uiStartupConfigLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigLabel.setObjectName("uiStartupConfigLabel")
|
||||
self.gridLayout_2.addWidget(self.uiStartupConfigLabel, 9, 0, 1, 1)
|
||||
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.uiStartupConfigLineEdit = QtWidgets.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigLineEdit.setObjectName("uiStartupConfigLineEdit")
|
||||
self.horizontalLayout_4.addWidget(self.uiStartupConfigLineEdit)
|
||||
self.uiStartupConfigToolButton = QtGui.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigToolButton = QtWidgets.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiStartupConfigToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||
self.uiStartupConfigToolButton.setObjectName(_fromUtf8("uiStartupConfigToolButton"))
|
||||
self.uiStartupConfigToolButton.setObjectName("uiStartupConfigToolButton")
|
||||
self.horizontalLayout_4.addWidget(self.uiStartupConfigToolButton)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_4, 4, 1, 1, 1)
|
||||
self.uiPrivateConfigLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigLabel.setObjectName(_fromUtf8("uiPrivateConfigLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiPrivateConfigLabel, 5, 0, 1, 1)
|
||||
self.horizontalLayout_6 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6"))
|
||||
self.uiPrivateConfigLineEdit = QtGui.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigLineEdit.setObjectName(_fromUtf8("uiPrivateConfigLineEdit"))
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_4, 9, 1, 1, 1)
|
||||
self.uiPrivateConfigLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigLabel.setObjectName("uiPrivateConfigLabel")
|
||||
self.gridLayout_2.addWidget(self.uiPrivateConfigLabel, 10, 0, 1, 1)
|
||||
self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
|
||||
self.uiPrivateConfigLineEdit = QtWidgets.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigLineEdit.setObjectName("uiPrivateConfigLineEdit")
|
||||
self.horizontalLayout_6.addWidget(self.uiPrivateConfigLineEdit)
|
||||
self.uiPrivateConfigToolButton = QtGui.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigToolButton = QtWidgets.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiPrivateConfigToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||
self.uiPrivateConfigToolButton.setObjectName(_fromUtf8("uiPrivateConfigToolButton"))
|
||||
self.uiPrivateConfigToolButton.setObjectName("uiPrivateConfigToolButton")
|
||||
self.horizontalLayout_6.addWidget(self.uiPrivateConfigToolButton)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_6, 5, 1, 1, 1)
|
||||
self.uiConsolePortLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiConsolePortLabel.setObjectName(_fromUtf8("uiConsolePortLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiConsolePortLabel, 6, 0, 1, 1)
|
||||
self.uiConsolePortSpinBox = QtGui.QSpinBox(self.uiGeneralPageWidget)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_6, 10, 1, 1, 1)
|
||||
self.uiConsolePortLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiConsolePortLabel.setObjectName("uiConsolePortLabel")
|
||||
self.gridLayout_2.addWidget(self.uiConsolePortLabel, 13, 0, 1, 1)
|
||||
self.uiConsolePortSpinBox = QtWidgets.QSpinBox(self.uiGeneralPageWidget)
|
||||
self.uiConsolePortSpinBox.setMaximum(65535)
|
||||
self.uiConsolePortSpinBox.setObjectName(_fromUtf8("uiConsolePortSpinBox"))
|
||||
self.gridLayout_2.addWidget(self.uiConsolePortSpinBox, 6, 1, 1, 1)
|
||||
self.uiAuxPortLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiAuxPortLabel.setObjectName(_fromUtf8("uiAuxPortLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiAuxPortLabel, 7, 0, 1, 1)
|
||||
self.uiAuxPortSpinBox = QtGui.QSpinBox(self.uiGeneralPageWidget)
|
||||
self.uiConsolePortSpinBox.setObjectName("uiConsolePortSpinBox")
|
||||
self.gridLayout_2.addWidget(self.uiConsolePortSpinBox, 13, 1, 1, 1)
|
||||
self.uiAuxPortLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiAuxPortLabel.setObjectName("uiAuxPortLabel")
|
||||
self.gridLayout_2.addWidget(self.uiAuxPortLabel, 14, 0, 1, 1)
|
||||
self.uiAuxPortSpinBox = QtWidgets.QSpinBox(self.uiGeneralPageWidget)
|
||||
self.uiAuxPortSpinBox.setMaximum(65535)
|
||||
self.uiAuxPortSpinBox.setObjectName(_fromUtf8("uiAuxPortSpinBox"))
|
||||
self.gridLayout_2.addWidget(self.uiAuxPortSpinBox, 7, 1, 1, 1)
|
||||
self.uiMidplaneLabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiMidplaneLabel.setObjectName(_fromUtf8("uiMidplaneLabel"))
|
||||
self.gridLayout_2.addWidget(self.uiMidplaneLabel, 8, 0, 1, 1)
|
||||
self.uiMidplaneComboBox = QtGui.QComboBox(self.uiGeneralPageWidget)
|
||||
self.uiAuxPortSpinBox.setObjectName("uiAuxPortSpinBox")
|
||||
self.gridLayout_2.addWidget(self.uiAuxPortSpinBox, 14, 1, 1, 1)
|
||||
self.uiMidplaneLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiMidplaneLabel.setObjectName("uiMidplaneLabel")
|
||||
self.gridLayout_2.addWidget(self.uiMidplaneLabel, 15, 0, 1, 1)
|
||||
self.uiMidplaneComboBox = QtWidgets.QComboBox(self.uiGeneralPageWidget)
|
||||
self.uiMidplaneComboBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiMidplaneComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiMidplaneComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiMidplaneComboBox.setObjectName(_fromUtf8("uiMidplaneComboBox"))
|
||||
self.gridLayout_2.addWidget(self.uiMidplaneComboBox, 8, 1, 1, 1)
|
||||
self.uiNPELabel = QtGui.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiNPELabel.setObjectName(_fromUtf8("uiNPELabel"))
|
||||
self.gridLayout_2.addWidget(self.uiNPELabel, 9, 0, 1, 1)
|
||||
self.uiNPEComboBox = QtGui.QComboBox(self.uiGeneralPageWidget)
|
||||
self.uiMidplaneComboBox.setObjectName("uiMidplaneComboBox")
|
||||
self.gridLayout_2.addWidget(self.uiMidplaneComboBox, 15, 1, 1, 1)
|
||||
self.uiNPELabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiNPELabel.setObjectName("uiNPELabel")
|
||||
self.gridLayout_2.addWidget(self.uiNPELabel, 16, 0, 1, 1)
|
||||
spacerItem = QtWidgets.QSpacerItem(263, 151, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 17, 1, 1, 1)
|
||||
self.uiNPEComboBox = QtWidgets.QComboBox(self.uiGeneralPageWidget)
|
||||
self.uiNPEComboBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNPEComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiNPEComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiNPEComboBox.setObjectName(_fromUtf8("uiNPEComboBox"))
|
||||
self.gridLayout_2.addWidget(self.uiNPEComboBox, 9, 1, 1, 1)
|
||||
spacerItem = QtGui.QSpacerItem(263, 151, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem, 10, 1, 1, 1)
|
||||
self.uiTabWidget.addTab(self.uiGeneralPageWidget, _fromUtf8(""))
|
||||
self.uiMemoriesPageWidget = QtGui.QWidget()
|
||||
self.uiMemoriesPageWidget.setObjectName(_fromUtf8("uiMemoriesPageWidget"))
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout(self.uiMemoriesPageWidget)
|
||||
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
|
||||
self.uiMemoriesGroupBox = QtGui.QGroupBox(self.uiMemoriesPageWidget)
|
||||
self.uiMemoriesGroupBox.setObjectName(_fromUtf8("uiMemoriesGroupBox"))
|
||||
self.gridLayout_5 = QtGui.QGridLayout(self.uiMemoriesGroupBox)
|
||||
self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
|
||||
self.uiRamLabel = QtGui.QLabel(self.uiMemoriesGroupBox)
|
||||
self.uiRamLabel.setObjectName(_fromUtf8("uiRamLabel"))
|
||||
self.uiNPEComboBox.setObjectName("uiNPEComboBox")
|
||||
self.gridLayout_2.addWidget(self.uiNPEComboBox, 16, 1, 1, 1)
|
||||
self.uiSymbolLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiSymbolLabel.setObjectName("uiSymbolLabel")
|
||||
self.gridLayout_2.addWidget(self.uiSymbolLabel, 5, 0, 1, 1)
|
||||
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
|
||||
self.uiSymbolLineEdit = QtWidgets.QLineEdit(self.uiGeneralPageWidget)
|
||||
self.uiSymbolLineEdit.setObjectName("uiSymbolLineEdit")
|
||||
self.horizontalLayout_7.addWidget(self.uiSymbolLineEdit)
|
||||
self.uiSymbolToolButton = QtWidgets.QToolButton(self.uiGeneralPageWidget)
|
||||
self.uiSymbolToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||
self.uiSymbolToolButton.setObjectName("uiSymbolToolButton")
|
||||
self.horizontalLayout_7.addWidget(self.uiSymbolToolButton)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_7, 5, 1, 1, 1)
|
||||
self.uiCategoryLabel = QtWidgets.QLabel(self.uiGeneralPageWidget)
|
||||
self.uiCategoryLabel.setObjectName("uiCategoryLabel")
|
||||
self.gridLayout_2.addWidget(self.uiCategoryLabel, 6, 0, 1, 1)
|
||||
self.uiCategoryComboBox = QtWidgets.QComboBox(self.uiGeneralPageWidget)
|
||||
self.uiCategoryComboBox.setObjectName("uiCategoryComboBox")
|
||||
self.gridLayout_2.addWidget(self.uiCategoryComboBox, 6, 1, 1, 1)
|
||||
self.uiTabWidget.addTab(self.uiGeneralPageWidget, "")
|
||||
self.uiMemoriesPageWidget = QtWidgets.QWidget()
|
||||
self.uiMemoriesPageWidget.setObjectName("uiMemoriesPageWidget")
|
||||
self.gridLayout_5 = QtWidgets.QGridLayout(self.uiMemoriesPageWidget)
|
||||
self.gridLayout_5.setObjectName("gridLayout_5")
|
||||
self.uiRamLabel = QtWidgets.QLabel(self.uiMemoriesPageWidget)
|
||||
self.uiRamLabel.setObjectName("uiRamLabel")
|
||||
self.gridLayout_5.addWidget(self.uiRamLabel, 0, 0, 1, 1)
|
||||
self.uiRamSpinBox = QtGui.QSpinBox(self.uiMemoriesGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiRamSpinBox = QtWidgets.QSpinBox(self.uiMemoriesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiRamSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -156,13 +157,13 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
self.uiRamSpinBox.setMaximum(65535)
|
||||
self.uiRamSpinBox.setSingleStep(32)
|
||||
self.uiRamSpinBox.setProperty("value", 128)
|
||||
self.uiRamSpinBox.setObjectName(_fromUtf8("uiRamSpinBox"))
|
||||
self.uiRamSpinBox.setObjectName("uiRamSpinBox")
|
||||
self.gridLayout_5.addWidget(self.uiRamSpinBox, 0, 1, 1, 1)
|
||||
self.uiNvramLabel = QtGui.QLabel(self.uiMemoriesGroupBox)
|
||||
self.uiNvramLabel.setObjectName(_fromUtf8("uiNvramLabel"))
|
||||
self.uiNvramLabel = QtWidgets.QLabel(self.uiMemoriesPageWidget)
|
||||
self.uiNvramLabel.setObjectName("uiNvramLabel")
|
||||
self.gridLayout_5.addWidget(self.uiNvramLabel, 1, 0, 1, 1)
|
||||
self.uiNvramSpinBox = QtGui.QSpinBox(self.uiMemoriesGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiNvramSpinBox = QtWidgets.QSpinBox(self.uiMemoriesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiNvramSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -171,14 +172,14 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
self.uiNvramSpinBox.setMaximum(65535)
|
||||
self.uiNvramSpinBox.setSingleStep(32)
|
||||
self.uiNvramSpinBox.setProperty("value", 128)
|
||||
self.uiNvramSpinBox.setObjectName(_fromUtf8("uiNvramSpinBox"))
|
||||
self.uiNvramSpinBox.setObjectName("uiNvramSpinBox")
|
||||
self.gridLayout_5.addWidget(self.uiNvramSpinBox, 1, 1, 1, 1)
|
||||
self.uiIomemLabel = QtGui.QLabel(self.uiMemoriesGroupBox)
|
||||
self.uiIomemLabel.setObjectName(_fromUtf8("uiIomemLabel"))
|
||||
self.uiIomemLabel = QtWidgets.QLabel(self.uiMemoriesPageWidget)
|
||||
self.uiIomemLabel.setObjectName("uiIomemLabel")
|
||||
self.gridLayout_5.addWidget(self.uiIomemLabel, 2, 0, 1, 1)
|
||||
self.uiIomemSpinBox = QtGui.QSpinBox(self.uiMemoriesGroupBox)
|
||||
self.uiIomemSpinBox = QtWidgets.QSpinBox(self.uiMemoriesPageWidget)
|
||||
self.uiIomemSpinBox.setEnabled(True)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiIomemSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -186,206 +187,203 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
self.uiIomemSpinBox.setMaximum(100)
|
||||
self.uiIomemSpinBox.setSingleStep(5)
|
||||
self.uiIomemSpinBox.setProperty("value", 5)
|
||||
self.uiIomemSpinBox.setObjectName(_fromUtf8("uiIomemSpinBox"))
|
||||
self.uiIomemSpinBox.setObjectName("uiIomemSpinBox")
|
||||
self.gridLayout_5.addWidget(self.uiIomemSpinBox, 2, 1, 1, 1)
|
||||
self.verticalLayout_2.addWidget(self.uiMemoriesGroupBox)
|
||||
self.uiDisksGroupBox = QtGui.QGroupBox(self.uiMemoriesPageWidget)
|
||||
self.uiDisksGroupBox.setObjectName(_fromUtf8("uiDisksGroupBox"))
|
||||
self.gridlayout = QtGui.QGridLayout(self.uiDisksGroupBox)
|
||||
self.gridlayout.setObjectName(_fromUtf8("gridlayout"))
|
||||
self.uiDisk0Label = QtGui.QLabel(self.uiDisksGroupBox)
|
||||
self.uiDisk0Label.setObjectName(_fromUtf8("uiDisk0Label"))
|
||||
self.gridlayout.addWidget(self.uiDisk0Label, 0, 0, 1, 1)
|
||||
self.uiDisk0SpinBox = QtGui.QSpinBox(self.uiDisksGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDisk0Label = QtWidgets.QLabel(self.uiMemoriesPageWidget)
|
||||
self.uiDisk0Label.setObjectName("uiDisk0Label")
|
||||
self.gridLayout_5.addWidget(self.uiDisk0Label, 3, 0, 1, 1)
|
||||
self.uiDisk0SpinBox = QtWidgets.QSpinBox(self.uiMemoriesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDisk0SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDisk0SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiDisk0SpinBox.setMaximum(99999)
|
||||
self.uiDisk0SpinBox.setSingleStep(4)
|
||||
self.uiDisk0SpinBox.setObjectName(_fromUtf8("uiDisk0SpinBox"))
|
||||
self.gridlayout.addWidget(self.uiDisk0SpinBox, 0, 1, 1, 1)
|
||||
self.uiDisk1Label = QtGui.QLabel(self.uiDisksGroupBox)
|
||||
self.uiDisk1Label.setObjectName(_fromUtf8("uiDisk1Label"))
|
||||
self.gridlayout.addWidget(self.uiDisk1Label, 1, 0, 1, 1)
|
||||
self.uiDisk1SpinBox = QtGui.QSpinBox(self.uiDisksGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiDisk0SpinBox.setObjectName("uiDisk0SpinBox")
|
||||
self.gridLayout_5.addWidget(self.uiDisk0SpinBox, 3, 1, 1, 1)
|
||||
self.uiDisk1Label = QtWidgets.QLabel(self.uiMemoriesPageWidget)
|
||||
self.uiDisk1Label.setObjectName("uiDisk1Label")
|
||||
self.gridLayout_5.addWidget(self.uiDisk1Label, 4, 0, 1, 1)
|
||||
self.uiDisk1SpinBox = QtWidgets.QSpinBox(self.uiMemoriesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiDisk1SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiDisk1SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiDisk1SpinBox.setMaximum(99999)
|
||||
self.uiDisk1SpinBox.setSingleStep(4)
|
||||
self.uiDisk1SpinBox.setObjectName(_fromUtf8("uiDisk1SpinBox"))
|
||||
self.gridlayout.addWidget(self.uiDisk1SpinBox, 1, 1, 1, 1)
|
||||
self.verticalLayout_2.addWidget(self.uiDisksGroupBox)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.verticalLayout_2.addItem(spacerItem1)
|
||||
self.uiTabWidget.addTab(self.uiMemoriesPageWidget, _fromUtf8(""))
|
||||
self.uiSlotsPageWidget = QtGui.QWidget()
|
||||
self.uiSlotsPageWidget.setObjectName(_fromUtf8("uiSlotsPageWidget"))
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self.uiSlotsPageWidget)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.uiAdaptersGroupBox = QtGui.QGroupBox(self.uiSlotsPageWidget)
|
||||
self.uiAdaptersGroupBox.setObjectName(_fromUtf8("uiAdaptersGroupBox"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.uiAdaptersGroupBox)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiSlot1comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot1comboBox.setObjectName(_fromUtf8("uiSlot1comboBox"))
|
||||
self.uiDisk1SpinBox.setObjectName("uiDisk1SpinBox")
|
||||
self.gridLayout_5.addWidget(self.uiDisk1SpinBox, 4, 1, 1, 1)
|
||||
self.uiAutoDeleteCheckBox = QtWidgets.QCheckBox(self.uiMemoriesPageWidget)
|
||||
self.uiAutoDeleteCheckBox.setObjectName("uiAutoDeleteCheckBox")
|
||||
self.gridLayout_5.addWidget(self.uiAutoDeleteCheckBox, 5, 0, 1, 2)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 21, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_5.addItem(spacerItem1, 6, 0, 1, 1)
|
||||
self.uiTabWidget.addTab(self.uiMemoriesPageWidget, "")
|
||||
self.uiSlotsPageWidget = QtWidgets.QWidget()
|
||||
self.uiSlotsPageWidget.setObjectName("uiSlotsPageWidget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.uiSlotsPageWidget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.uiAdaptersGroupBox = QtWidgets.QGroupBox(self.uiSlotsPageWidget)
|
||||
self.uiAdaptersGroupBox.setObjectName("uiAdaptersGroupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.uiAdaptersGroupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiSlot1comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot1comboBox.setObjectName("uiSlot1comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot1comboBox, 1, 1, 1, 1)
|
||||
self.uiSlot0Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot0Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot0Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot0Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot0Label.setObjectName(_fromUtf8("uiSlot0Label"))
|
||||
self.uiSlot0Label.setObjectName("uiSlot0Label")
|
||||
self.gridLayout.addWidget(self.uiSlot0Label, 0, 0, 1, 1)
|
||||
self.uiSlot0comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot0comboBox.setObjectName(_fromUtf8("uiSlot0comboBox"))
|
||||
self.uiSlot0comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot0comboBox.setObjectName("uiSlot0comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot0comboBox, 0, 1, 1, 1)
|
||||
self.uiSlot1Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot1Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot1Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot1Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot1Label.setObjectName(_fromUtf8("uiSlot1Label"))
|
||||
self.uiSlot1Label.setObjectName("uiSlot1Label")
|
||||
self.gridLayout.addWidget(self.uiSlot1Label, 1, 0, 1, 1)
|
||||
self.uiSlot2Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot2Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot2Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot2Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot2Label.setObjectName(_fromUtf8("uiSlot2Label"))
|
||||
self.uiSlot2Label.setObjectName("uiSlot2Label")
|
||||
self.gridLayout.addWidget(self.uiSlot2Label, 2, 0, 1, 1)
|
||||
self.uiSlot2comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot2comboBox.setObjectName(_fromUtf8("uiSlot2comboBox"))
|
||||
self.uiSlot2comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot2comboBox.setObjectName("uiSlot2comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot2comboBox, 2, 1, 1, 1)
|
||||
self.uiSlot3Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot3Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot3Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot3Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot3Label.setObjectName(_fromUtf8("uiSlot3Label"))
|
||||
self.uiSlot3Label.setObjectName("uiSlot3Label")
|
||||
self.gridLayout.addWidget(self.uiSlot3Label, 3, 0, 1, 1)
|
||||
self.uiSlot3comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot3comboBox.setObjectName(_fromUtf8("uiSlot3comboBox"))
|
||||
self.uiSlot3comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot3comboBox.setObjectName("uiSlot3comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot3comboBox, 3, 1, 1, 1)
|
||||
self.uiSlot4Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot4Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot4Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot4Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot4Label.setObjectName(_fromUtf8("uiSlot4Label"))
|
||||
self.uiSlot4Label.setObjectName("uiSlot4Label")
|
||||
self.gridLayout.addWidget(self.uiSlot4Label, 4, 0, 1, 1)
|
||||
self.uiSlot4comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot4comboBox.setObjectName(_fromUtf8("uiSlot4comboBox"))
|
||||
self.uiSlot4comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot4comboBox.setObjectName("uiSlot4comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot4comboBox, 4, 1, 1, 1)
|
||||
self.uiSlot5Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot5Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot5Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot5Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot5Label.setObjectName(_fromUtf8("uiSlot5Label"))
|
||||
self.uiSlot5Label.setObjectName("uiSlot5Label")
|
||||
self.gridLayout.addWidget(self.uiSlot5Label, 5, 0, 1, 1)
|
||||
self.uiSlot5comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot5comboBox.setObjectName(_fromUtf8("uiSlot5comboBox"))
|
||||
self.uiSlot5comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot5comboBox.setObjectName("uiSlot5comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot5comboBox, 5, 1, 1, 1)
|
||||
self.uiSlot6Label = QtGui.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiSlot6Label = QtWidgets.QLabel(self.uiAdaptersGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSlot6Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiSlot6Label.setSizePolicy(sizePolicy)
|
||||
self.uiSlot6Label.setObjectName(_fromUtf8("uiSlot6Label"))
|
||||
self.uiSlot6Label.setObjectName("uiSlot6Label")
|
||||
self.gridLayout.addWidget(self.uiSlot6Label, 6, 0, 1, 1)
|
||||
self.uiSlot6comboBox = QtGui.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot6comboBox.setObjectName(_fromUtf8("uiSlot6comboBox"))
|
||||
self.uiSlot6comboBox = QtWidgets.QComboBox(self.uiAdaptersGroupBox)
|
||||
self.uiSlot6comboBox.setObjectName("uiSlot6comboBox")
|
||||
self.gridLayout.addWidget(self.uiSlot6comboBox, 6, 1, 1, 1)
|
||||
self.verticalLayout.addWidget(self.uiAdaptersGroupBox)
|
||||
self.uiWicsGroupBox = QtGui.QGroupBox(self.uiSlotsPageWidget)
|
||||
self.uiWicsGroupBox.setObjectName(_fromUtf8("uiWicsGroupBox"))
|
||||
self.gridlayout1 = QtGui.QGridLayout(self.uiWicsGroupBox)
|
||||
self.gridlayout1.setObjectName(_fromUtf8("gridlayout1"))
|
||||
self.uiWic0Label = QtGui.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiWicsGroupBox = QtWidgets.QGroupBox(self.uiSlotsPageWidget)
|
||||
self.uiWicsGroupBox.setObjectName("uiWicsGroupBox")
|
||||
self.gridlayout = QtWidgets.QGridLayout(self.uiWicsGroupBox)
|
||||
self.gridlayout.setObjectName("gridlayout")
|
||||
self.uiWic0Label = QtWidgets.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiWic0Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiWic0Label.setSizePolicy(sizePolicy)
|
||||
self.uiWic0Label.setObjectName(_fromUtf8("uiWic0Label"))
|
||||
self.gridlayout1.addWidget(self.uiWic0Label, 0, 0, 1, 1)
|
||||
self.uiWic0comboBox = QtGui.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic0comboBox.setObjectName(_fromUtf8("uiWic0comboBox"))
|
||||
self.gridlayout1.addWidget(self.uiWic0comboBox, 0, 1, 1, 1)
|
||||
self.uiWic1Label = QtGui.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiWic0Label.setObjectName("uiWic0Label")
|
||||
self.gridlayout.addWidget(self.uiWic0Label, 0, 0, 1, 1)
|
||||
self.uiWic0comboBox = QtWidgets.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic0comboBox.setObjectName("uiWic0comboBox")
|
||||
self.gridlayout.addWidget(self.uiWic0comboBox, 0, 1, 1, 1)
|
||||
self.uiWic1Label = QtWidgets.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiWic1Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiWic1Label.setSizePolicy(sizePolicy)
|
||||
self.uiWic1Label.setObjectName(_fromUtf8("uiWic1Label"))
|
||||
self.gridlayout1.addWidget(self.uiWic1Label, 1, 0, 1, 1)
|
||||
self.uiWic1comboBox = QtGui.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic1comboBox.setObjectName(_fromUtf8("uiWic1comboBox"))
|
||||
self.gridlayout1.addWidget(self.uiWic1comboBox, 1, 1, 1, 1)
|
||||
self.uiWic2Label = QtGui.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||
self.uiWic1Label.setObjectName("uiWic1Label")
|
||||
self.gridlayout.addWidget(self.uiWic1Label, 1, 0, 1, 1)
|
||||
self.uiWic1comboBox = QtWidgets.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic1comboBox.setObjectName("uiWic1comboBox")
|
||||
self.gridlayout.addWidget(self.uiWic1comboBox, 1, 1, 1, 1)
|
||||
self.uiWic2Label = QtWidgets.QLabel(self.uiWicsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiWic2Label.sizePolicy().hasHeightForWidth())
|
||||
self.uiWic2Label.setSizePolicy(sizePolicy)
|
||||
self.uiWic2Label.setObjectName(_fromUtf8("uiWic2Label"))
|
||||
self.gridlayout1.addWidget(self.uiWic2Label, 2, 0, 1, 1)
|
||||
self.uiWic2comboBox = QtGui.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic2comboBox.setObjectName(_fromUtf8("uiWic2comboBox"))
|
||||
self.gridlayout1.addWidget(self.uiWic2comboBox, 2, 1, 1, 1)
|
||||
self.uiWic2Label.setObjectName("uiWic2Label")
|
||||
self.gridlayout.addWidget(self.uiWic2Label, 2, 0, 1, 1)
|
||||
self.uiWic2comboBox = QtWidgets.QComboBox(self.uiWicsGroupBox)
|
||||
self.uiWic2comboBox.setObjectName("uiWic2comboBox")
|
||||
self.gridlayout.addWidget(self.uiWic2comboBox, 2, 1, 1, 1)
|
||||
self.verticalLayout.addWidget(self.uiWicsGroupBox)
|
||||
spacerItem2 = QtGui.QSpacerItem(325, 31, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(325, 31, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem2)
|
||||
self.uiTabWidget.addTab(self.uiSlotsPageWidget, _fromUtf8(""))
|
||||
self.uiAdvancedPageWidget = QtGui.QWidget()
|
||||
self.uiAdvancedPageWidget.setObjectName(_fromUtf8("uiAdvancedPageWidget"))
|
||||
self.verticalLayout_4 = QtGui.QVBoxLayout(self.uiAdvancedPageWidget)
|
||||
self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4"))
|
||||
self.uiSystemGroupBox = QtGui.QGroupBox(self.uiAdvancedPageWidget)
|
||||
self.uiSystemGroupBox.setObjectName(_fromUtf8("uiSystemGroupBox"))
|
||||
self.gridLayout_6 = QtGui.QGridLayout(self.uiSystemGroupBox)
|
||||
self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6"))
|
||||
self.uiSystemIdLineEdit = QtGui.QLineEdit(self.uiSystemGroupBox)
|
||||
self.uiSystemIdLineEdit.setObjectName(_fromUtf8("uiSystemIdLineEdit"))
|
||||
self.uiTabWidget.addTab(self.uiSlotsPageWidget, "")
|
||||
self.uiAdvancedPageWidget = QtWidgets.QWidget()
|
||||
self.uiAdvancedPageWidget.setObjectName("uiAdvancedPageWidget")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.uiAdvancedPageWidget)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.uiSystemGroupBox = QtWidgets.QGroupBox(self.uiAdvancedPageWidget)
|
||||
self.uiSystemGroupBox.setObjectName("uiSystemGroupBox")
|
||||
self.gridLayout_6 = QtWidgets.QGridLayout(self.uiSystemGroupBox)
|
||||
self.gridLayout_6.setObjectName("gridLayout_6")
|
||||
self.uiSystemIdLineEdit = QtWidgets.QLineEdit(self.uiSystemGroupBox)
|
||||
self.uiSystemIdLineEdit.setObjectName("uiSystemIdLineEdit")
|
||||
self.gridLayout_6.addWidget(self.uiSystemIdLineEdit, 0, 1, 1, 1)
|
||||
self.label = QtGui.QLabel(self.uiSystemGroupBox)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.label = QtWidgets.QLabel(self.uiSystemGroupBox)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout_6.addWidget(self.label, 0, 0, 1, 1)
|
||||
self.uiBaseMacLabel = QtGui.QLabel(self.uiSystemGroupBox)
|
||||
self.uiBaseMacLabel.setObjectName(_fromUtf8("uiBaseMacLabel"))
|
||||
self.uiBaseMacLabel = QtWidgets.QLabel(self.uiSystemGroupBox)
|
||||
self.uiBaseMacLabel.setObjectName("uiBaseMacLabel")
|
||||
self.gridLayout_6.addWidget(self.uiBaseMacLabel, 1, 0, 1, 1)
|
||||
self.uiBaseMACLineEdit = QtGui.QLineEdit(self.uiSystemGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiBaseMACLineEdit = QtWidgets.QLineEdit(self.uiSystemGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiBaseMACLineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.uiBaseMACLineEdit.setSizePolicy(sizePolicy)
|
||||
self.uiBaseMACLineEdit.setText(_fromUtf8(""))
|
||||
self.uiBaseMACLineEdit.setObjectName(_fromUtf8("uiBaseMACLineEdit"))
|
||||
self.uiBaseMACLineEdit.setText("")
|
||||
self.uiBaseMACLineEdit.setObjectName("uiBaseMACLineEdit")
|
||||
self.gridLayout_6.addWidget(self.uiBaseMACLineEdit, 1, 1, 1, 1)
|
||||
self.verticalLayout_4.addWidget(self.uiSystemGroupBox)
|
||||
self.uiOptimizationsGroupBox = QtGui.QGroupBox(self.uiAdvancedPageWidget)
|
||||
self.uiOptimizationsGroupBox.setObjectName(_fromUtf8("uiOptimizationsGroupBox"))
|
||||
self.gridLayout_4 = QtGui.QGridLayout(self.uiOptimizationsGroupBox)
|
||||
self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
|
||||
self.uiExecAreaLabel = QtGui.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiExecAreaLabel.setObjectName(_fromUtf8("uiExecAreaLabel"))
|
||||
self.uiOptimizationsGroupBox = QtWidgets.QGroupBox(self.uiAdvancedPageWidget)
|
||||
self.uiOptimizationsGroupBox.setObjectName("uiOptimizationsGroupBox")
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout(self.uiOptimizationsGroupBox)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.uiExecAreaLabel = QtWidgets.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiExecAreaLabel.setObjectName("uiExecAreaLabel")
|
||||
self.gridLayout_4.addWidget(self.uiExecAreaLabel, 3, 0, 1, 1)
|
||||
self.uiExecAreaSpinBox = QtGui.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiExecAreaSpinBox = QtWidgets.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiExecAreaSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@@ -393,137 +391,137 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
self.uiExecAreaSpinBox.setMaximum(4096)
|
||||
self.uiExecAreaSpinBox.setSingleStep(4)
|
||||
self.uiExecAreaSpinBox.setProperty("value", 64)
|
||||
self.uiExecAreaSpinBox.setObjectName(_fromUtf8("uiExecAreaSpinBox"))
|
||||
self.uiExecAreaSpinBox.setObjectName("uiExecAreaSpinBox")
|
||||
self.gridLayout_4.addWidget(self.uiExecAreaSpinBox, 3, 1, 1, 1)
|
||||
self.uiSparseMemoryCheckBox = QtGui.QCheckBox(self.uiOptimizationsGroupBox)
|
||||
self.uiSparseMemoryCheckBox = QtWidgets.QCheckBox(self.uiOptimizationsGroupBox)
|
||||
self.uiSparseMemoryCheckBox.setChecked(False)
|
||||
self.uiSparseMemoryCheckBox.setObjectName(_fromUtf8("uiSparseMemoryCheckBox"))
|
||||
self.uiSparseMemoryCheckBox.setObjectName("uiSparseMemoryCheckBox")
|
||||
self.gridLayout_4.addWidget(self.uiSparseMemoryCheckBox, 5, 0, 1, 2)
|
||||
self.uiIdlepcLabel = QtGui.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlepcLabel.setObjectName(_fromUtf8("uiIdlepcLabel"))
|
||||
self.uiIdlepcLabel = QtWidgets.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlepcLabel.setObjectName("uiIdlepcLabel")
|
||||
self.gridLayout_4.addWidget(self.uiIdlepcLabel, 0, 0, 1, 1)
|
||||
self.uiIdlepcLineEdit = QtGui.QLineEdit(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlepcLineEdit.setObjectName(_fromUtf8("uiIdlepcLineEdit"))
|
||||
self.uiIdlepcLineEdit = QtWidgets.QLineEdit(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlepcLineEdit.setObjectName("uiIdlepcLineEdit")
|
||||
self.gridLayout_4.addWidget(self.uiIdlepcLineEdit, 0, 1, 1, 1)
|
||||
self.uiIdlemaxLabel = QtGui.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlemaxLabel.setObjectName(_fromUtf8("uiIdlemaxLabel"))
|
||||
self.uiIdlemaxLabel = QtWidgets.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlemaxLabel.setObjectName("uiIdlemaxLabel")
|
||||
self.gridLayout_4.addWidget(self.uiIdlemaxLabel, 1, 0, 1, 1)
|
||||
self.uiIdlemaxSpinBox = QtGui.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlemaxSpinBox = QtWidgets.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlemaxSpinBox.setMinimum(100)
|
||||
self.uiIdlemaxSpinBox.setMaximum(10000)
|
||||
self.uiIdlemaxSpinBox.setSingleStep(100)
|
||||
self.uiIdlemaxSpinBox.setProperty("value", 500)
|
||||
self.uiIdlemaxSpinBox.setObjectName(_fromUtf8("uiIdlemaxSpinBox"))
|
||||
self.uiIdlemaxSpinBox.setObjectName("uiIdlemaxSpinBox")
|
||||
self.gridLayout_4.addWidget(self.uiIdlemaxSpinBox, 1, 1, 1, 1)
|
||||
self.uiIdlesleepLabel = QtGui.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlesleepLabel.setObjectName(_fromUtf8("uiIdlesleepLabel"))
|
||||
self.uiIdlesleepLabel = QtWidgets.QLabel(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlesleepLabel.setObjectName("uiIdlesleepLabel")
|
||||
self.gridLayout_4.addWidget(self.uiIdlesleepLabel, 2, 0, 1, 1)
|
||||
self.uiMmapCheckBox = QtGui.QCheckBox(self.uiOptimizationsGroupBox)
|
||||
self.uiMmapCheckBox = QtWidgets.QCheckBox(self.uiOptimizationsGroupBox)
|
||||
self.uiMmapCheckBox.setChecked(True)
|
||||
self.uiMmapCheckBox.setObjectName(_fromUtf8("uiMmapCheckBox"))
|
||||
self.uiMmapCheckBox.setObjectName("uiMmapCheckBox")
|
||||
self.gridLayout_4.addWidget(self.uiMmapCheckBox, 4, 0, 1, 2)
|
||||
self.uiIdlesleepSpinBox = QtGui.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlesleepSpinBox = QtWidgets.QSpinBox(self.uiOptimizationsGroupBox)
|
||||
self.uiIdlesleepSpinBox.setMinimum(1)
|
||||
self.uiIdlesleepSpinBox.setMaximum(500)
|
||||
self.uiIdlesleepSpinBox.setSingleStep(10)
|
||||
self.uiIdlesleepSpinBox.setProperty("value", 30)
|
||||
self.uiIdlesleepSpinBox.setObjectName(_fromUtf8("uiIdlesleepSpinBox"))
|
||||
self.uiIdlesleepSpinBox.setObjectName("uiIdlesleepSpinBox")
|
||||
self.gridLayout_4.addWidget(self.uiIdlesleepSpinBox, 2, 1, 1, 1)
|
||||
self.verticalLayout_4.addWidget(self.uiOptimizationsGroupBox)
|
||||
spacerItem3 = QtGui.QSpacerItem(304, 251, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem3 = QtWidgets.QSpacerItem(304, 251, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_4.addItem(spacerItem3)
|
||||
self.uiTabWidget.addTab(self.uiAdvancedPageWidget, _fromUtf8(""))
|
||||
self.uiEnvironmentPageWidget = QtGui.QWidget()
|
||||
self.uiEnvironmentPageWidget.setObjectName(_fromUtf8("uiEnvironmentPageWidget"))
|
||||
self.verticalLayout_3 = QtGui.QVBoxLayout(self.uiEnvironmentPageWidget)
|
||||
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
|
||||
self.uiPowerSuppliesGroupBox = QtGui.QGroupBox(self.uiEnvironmentPageWidget)
|
||||
self.uiPowerSuppliesGroupBox.setObjectName(_fromUtf8("uiPowerSuppliesGroupBox"))
|
||||
self.gridLayout_7 = QtGui.QGridLayout(self.uiPowerSuppliesGroupBox)
|
||||
self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7"))
|
||||
self.uiPowerSupply2Label = QtGui.QLabel(self.uiPowerSuppliesGroupBox)
|
||||
self.uiPowerSupply2Label.setObjectName(_fromUtf8("uiPowerSupply2Label"))
|
||||
self.uiTabWidget.addTab(self.uiAdvancedPageWidget, "")
|
||||
self.uiEnvironmentPageWidget = QtWidgets.QWidget()
|
||||
self.uiEnvironmentPageWidget.setObjectName("uiEnvironmentPageWidget")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.uiEnvironmentPageWidget)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.uiPowerSuppliesGroupBox = QtWidgets.QGroupBox(self.uiEnvironmentPageWidget)
|
||||
self.uiPowerSuppliesGroupBox.setObjectName("uiPowerSuppliesGroupBox")
|
||||
self.gridLayout_7 = QtWidgets.QGridLayout(self.uiPowerSuppliesGroupBox)
|
||||
self.gridLayout_7.setObjectName("gridLayout_7")
|
||||
self.uiPowerSupply2Label = QtWidgets.QLabel(self.uiPowerSuppliesGroupBox)
|
||||
self.uiPowerSupply2Label.setObjectName("uiPowerSupply2Label")
|
||||
self.gridLayout_7.addWidget(self.uiPowerSupply2Label, 1, 0, 1, 1)
|
||||
self.uiPowerSupply1ComboBox = QtGui.QComboBox(self.uiPowerSuppliesGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiPowerSupply1ComboBox = QtWidgets.QComboBox(self.uiPowerSuppliesGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPowerSupply1ComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiPowerSupply1ComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiPowerSupply1ComboBox.setObjectName(_fromUtf8("uiPowerSupply1ComboBox"))
|
||||
self.uiPowerSupply1ComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPowerSupply1ComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPowerSupply1ComboBox.setObjectName("uiPowerSupply1ComboBox")
|
||||
self.uiPowerSupply1ComboBox.addItem("")
|
||||
self.uiPowerSupply1ComboBox.addItem("")
|
||||
self.gridLayout_7.addWidget(self.uiPowerSupply1ComboBox, 0, 1, 1, 1)
|
||||
self.uiPowerSupply1Label = QtGui.QLabel(self.uiPowerSuppliesGroupBox)
|
||||
self.uiPowerSupply1Label.setObjectName(_fromUtf8("uiPowerSupply1Label"))
|
||||
self.uiPowerSupply1Label = QtWidgets.QLabel(self.uiPowerSuppliesGroupBox)
|
||||
self.uiPowerSupply1Label.setObjectName("uiPowerSupply1Label")
|
||||
self.gridLayout_7.addWidget(self.uiPowerSupply1Label, 0, 0, 1, 1)
|
||||
self.uiPowerSupply2ComboBox = QtGui.QComboBox(self.uiPowerSuppliesGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiPowerSupply2ComboBox = QtWidgets.QComboBox(self.uiPowerSuppliesGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiPowerSupply2ComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiPowerSupply2ComboBox.setSizePolicy(sizePolicy)
|
||||
self.uiPowerSupply2ComboBox.setObjectName(_fromUtf8("uiPowerSupply2ComboBox"))
|
||||
self.uiPowerSupply2ComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPowerSupply2ComboBox.addItem(_fromUtf8(""))
|
||||
self.uiPowerSupply2ComboBox.setObjectName("uiPowerSupply2ComboBox")
|
||||
self.uiPowerSupply2ComboBox.addItem("")
|
||||
self.uiPowerSupply2ComboBox.addItem("")
|
||||
self.gridLayout_7.addWidget(self.uiPowerSupply2ComboBox, 1, 1, 1, 1)
|
||||
self.verticalLayout_3.addWidget(self.uiPowerSuppliesGroupBox)
|
||||
self.uiSensorsGroupBox = QtGui.QGroupBox(self.uiEnvironmentPageWidget)
|
||||
self.uiSensorsGroupBox.setObjectName(_fromUtf8("uiSensorsGroupBox"))
|
||||
self.gridLayout_3 = QtGui.QGridLayout(self.uiSensorsGroupBox)
|
||||
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
|
||||
self.uiSensor1Label = QtGui.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor1Label.setObjectName(_fromUtf8("uiSensor1Label"))
|
||||
self.uiSensorsGroupBox = QtWidgets.QGroupBox(self.uiEnvironmentPageWidget)
|
||||
self.uiSensorsGroupBox.setObjectName("uiSensorsGroupBox")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.uiSensorsGroupBox)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.uiSensor1Label = QtWidgets.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor1Label.setObjectName("uiSensor1Label")
|
||||
self.gridLayout_3.addWidget(self.uiSensor1Label, 0, 0, 1, 1)
|
||||
self.uiSensor1SpinBox = QtGui.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSensor1SpinBox = QtWidgets.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSensor1SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSensor1SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSensor1SpinBox.setMaximum(100)
|
||||
self.uiSensor1SpinBox.setObjectName(_fromUtf8("uiSensor1SpinBox"))
|
||||
self.uiSensor1SpinBox.setObjectName("uiSensor1SpinBox")
|
||||
self.gridLayout_3.addWidget(self.uiSensor1SpinBox, 0, 1, 1, 1)
|
||||
self.uiSensor2Label = QtGui.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor2Label.setObjectName(_fromUtf8("uiSensor2Label"))
|
||||
self.uiSensor2Label = QtWidgets.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor2Label.setObjectName("uiSensor2Label")
|
||||
self.gridLayout_3.addWidget(self.uiSensor2Label, 1, 0, 1, 1)
|
||||
self.uiSensor2SpinBox = QtGui.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSensor2SpinBox = QtWidgets.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSensor2SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSensor2SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSensor2SpinBox.setMaximum(100)
|
||||
self.uiSensor2SpinBox.setObjectName(_fromUtf8("uiSensor2SpinBox"))
|
||||
self.uiSensor2SpinBox.setObjectName("uiSensor2SpinBox")
|
||||
self.gridLayout_3.addWidget(self.uiSensor2SpinBox, 1, 1, 1, 1)
|
||||
self.uiSensor3Label = QtGui.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor3Label.setObjectName(_fromUtf8("uiSensor3Label"))
|
||||
self.uiSensor3Label = QtWidgets.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor3Label.setObjectName("uiSensor3Label")
|
||||
self.gridLayout_3.addWidget(self.uiSensor3Label, 2, 0, 1, 1)
|
||||
self.uiSensor3SpinBox = QtGui.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSensor3SpinBox = QtWidgets.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSensor3SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSensor3SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSensor3SpinBox.setMaximum(100)
|
||||
self.uiSensor3SpinBox.setObjectName(_fromUtf8("uiSensor3SpinBox"))
|
||||
self.uiSensor3SpinBox.setObjectName("uiSensor3SpinBox")
|
||||
self.gridLayout_3.addWidget(self.uiSensor3SpinBox, 2, 1, 1, 1)
|
||||
self.uiSensor4Label = QtGui.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor4Label.setObjectName(_fromUtf8("uiSensor4Label"))
|
||||
self.uiSensor4Label = QtWidgets.QLabel(self.uiSensorsGroupBox)
|
||||
self.uiSensor4Label.setObjectName("uiSensor4Label")
|
||||
self.gridLayout_3.addWidget(self.uiSensor4Label, 3, 0, 1, 1)
|
||||
self.uiSensor4SpinBox = QtGui.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
self.uiSensor4SpinBox = QtWidgets.QSpinBox(self.uiSensorsGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiSensor4SpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.uiSensor4SpinBox.setSizePolicy(sizePolicy)
|
||||
self.uiSensor4SpinBox.setMaximum(100)
|
||||
self.uiSensor4SpinBox.setObjectName(_fromUtf8("uiSensor4SpinBox"))
|
||||
self.uiSensor4SpinBox.setObjectName("uiSensor4SpinBox")
|
||||
self.gridLayout_3.addWidget(self.uiSensor4SpinBox, 3, 1, 1, 1)
|
||||
self.verticalLayout_3.addWidget(self.uiSensorsGroupBox)
|
||||
spacerItem4 = QtGui.QSpacerItem(20, 194, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
spacerItem4 = QtWidgets.QSpacerItem(20, 194, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_3.addItem(spacerItem4)
|
||||
self.uiTabWidget.addTab(self.uiEnvironmentPageWidget, _fromUtf8(""))
|
||||
self.uiTabWidget.addTab(self.uiEnvironmentPageWidget, "")
|
||||
self.vboxlayout.addWidget(self.uiTabWidget)
|
||||
|
||||
self.retranslateUi(iosRouterConfigPageWidget)
|
||||
@@ -532,11 +530,7 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
self.uiPowerSupply2ComboBox.setCurrentIndex(1)
|
||||
QtCore.QMetaObject.connectSlotsByName(iosRouterConfigPageWidget)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiMidplaneComboBox, self.uiNPEComboBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiNPEComboBox, self.uiRamSpinBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiRamSpinBox, self.uiNvramSpinBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiNvramSpinBox, self.uiDisk0SpinBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiDisk0SpinBox, self.uiDisk1SpinBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiDisk1SpinBox, self.uiSlot0comboBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiNPEComboBox, self.uiSlot0comboBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiSlot0comboBox, self.uiSlot1comboBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiSlot1comboBox, self.uiSlot2comboBox)
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiSlot2comboBox, self.uiSlot3comboBox)
|
||||
@@ -550,75 +544,78 @@ class Ui_iosRouterConfigPageWidget(object):
|
||||
iosRouterConfigPageWidget.setTabOrder(self.uiBaseMACLineEdit, self.uiExecAreaSpinBox)
|
||||
|
||||
def retranslateUi(self, iosRouterConfigPageWidget):
|
||||
iosRouterConfigPageWidget.setWindowTitle(_translate("iosRouterConfigPageWidget", "Dynamips IOS Router configuration", None))
|
||||
self.uiNameLabel.setText(_translate("iosRouterConfigPageWidget", "Name:", None))
|
||||
self.uiPlatformLabel.setText(_translate("iosRouterConfigPageWidget", "Platform:", None))
|
||||
self.uiChassisLabel.setText(_translate("iosRouterConfigPageWidget", "Chassis:", None))
|
||||
self.uiIOSImageLabel.setText(_translate("iosRouterConfigPageWidget", "IOS image path:", None))
|
||||
self.uiIOSImageToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse...", None))
|
||||
self.uiStartupConfigLabel.setText(_translate("iosRouterConfigPageWidget", "Initial startup-config:", None))
|
||||
self.uiStartupConfigToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse...", None))
|
||||
self.uiPrivateConfigLabel.setText(_translate("iosRouterConfigPageWidget", "Initial private-config:", None))
|
||||
self.uiPrivateConfigToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse...", None))
|
||||
self.uiConsolePortLabel.setText(_translate("iosRouterConfigPageWidget", "Console port:", None))
|
||||
self.uiAuxPortLabel.setText(_translate("iosRouterConfigPageWidget", "Aux port:", None))
|
||||
self.uiMidplaneLabel.setText(_translate("iosRouterConfigPageWidget", "Midplane:", None))
|
||||
self.uiNPELabel.setText(_translate("iosRouterConfigPageWidget", "NPE:", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralPageWidget), _translate("iosRouterConfigPageWidget", "General", None))
|
||||
self.uiMemoriesGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Memories", None))
|
||||
self.uiRamLabel.setText(_translate("iosRouterConfigPageWidget", "RAM size:", None))
|
||||
self.uiRamSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB", None))
|
||||
self.uiNvramLabel.setText(_translate("iosRouterConfigPageWidget", "NVRAM size:", None))
|
||||
self.uiNvramSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " KiB", None))
|
||||
self.uiIomemLabel.setText(_translate("iosRouterConfigPageWidget", "I/O memory :", None))
|
||||
self.uiIomemSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " %", None))
|
||||
self.uiDisksGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Disks", None))
|
||||
self.uiDisk0Label.setText(_translate("iosRouterConfigPageWidget", "PCMCIA disk0 size:", None))
|
||||
self.uiDisk0SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB", None))
|
||||
self.uiDisk1Label.setText(_translate("iosRouterConfigPageWidget", "PCMCIA disk1 size:", None))
|
||||
self.uiDisk1SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiMemoriesPageWidget), _translate("iosRouterConfigPageWidget", "Memories and disks", None))
|
||||
self.uiAdaptersGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Adapters", None))
|
||||
self.uiSlot0Label.setText(_translate("iosRouterConfigPageWidget", "slot 0:", None))
|
||||
self.uiSlot1Label.setText(_translate("iosRouterConfigPageWidget", "slot 1:", None))
|
||||
self.uiSlot2Label.setText(_translate("iosRouterConfigPageWidget", "slot 2:", None))
|
||||
self.uiSlot3Label.setText(_translate("iosRouterConfigPageWidget", "slot 3:", None))
|
||||
self.uiSlot4Label.setText(_translate("iosRouterConfigPageWidget", "slot 4:", None))
|
||||
self.uiSlot5Label.setText(_translate("iosRouterConfigPageWidget", "slot 5:", None))
|
||||
self.uiSlot6Label.setText(_translate("iosRouterConfigPageWidget", "slot 6:", None))
|
||||
self.uiWicsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "WICs", None))
|
||||
self.uiWic0Label.setText(_translate("iosRouterConfigPageWidget", "wic 0:", None))
|
||||
self.uiWic1Label.setText(_translate("iosRouterConfigPageWidget", "wic 1:", None))
|
||||
self.uiWic2Label.setText(_translate("iosRouterConfigPageWidget", "wic 2:", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiSlotsPageWidget), _translate("iosRouterConfigPageWidget", "Slots", None))
|
||||
self.uiSystemGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "System", None))
|
||||
self.label.setText(_translate("iosRouterConfigPageWidget", "System ID:", None))
|
||||
self.uiBaseMacLabel.setText(_translate("iosRouterConfigPageWidget", "Base MAC:", None))
|
||||
self.uiOptimizationsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Optimisations", None))
|
||||
self.uiExecAreaLabel.setText(_translate("iosRouterConfigPageWidget", "Exec area:", None))
|
||||
self.uiExecAreaSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB", None))
|
||||
self.uiSparseMemoryCheckBox.setText(_translate("iosRouterConfigPageWidget", "Enable sparse memory support", None))
|
||||
self.uiIdlepcLabel.setText(_translate("iosRouterConfigPageWidget", "Idle-PC:", None))
|
||||
self.uiIdlemaxLabel.setText(_translate("iosRouterConfigPageWidget", "Idlemax:", None))
|
||||
self.uiIdlesleepLabel.setText(_translate("iosRouterConfigPageWidget", "Idlesleep:", None))
|
||||
self.uiMmapCheckBox.setText(_translate("iosRouterConfigPageWidget", "Enable mmap support", None))
|
||||
self.uiIdlesleepSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " ms", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiAdvancedPageWidget), _translate("iosRouterConfigPageWidget", "Advanced", None))
|
||||
self.uiPowerSuppliesGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Power supplies", None))
|
||||
self.uiPowerSupply2Label.setText(_translate("iosRouterConfigPageWidget", "Power supply 2:", None))
|
||||
self.uiPowerSupply1ComboBox.setItemText(0, _translate("iosRouterConfigPageWidget", "on", None))
|
||||
self.uiPowerSupply1ComboBox.setItemText(1, _translate("iosRouterConfigPageWidget", "off", None))
|
||||
self.uiPowerSupply1Label.setText(_translate("iosRouterConfigPageWidget", "Power supply 1:", None))
|
||||
self.uiPowerSupply2ComboBox.setItemText(0, _translate("iosRouterConfigPageWidget", "on", None))
|
||||
self.uiPowerSupply2ComboBox.setItemText(1, _translate("iosRouterConfigPageWidget", "off", None))
|
||||
self.uiSensorsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Temperature sensors", None))
|
||||
self.uiSensor1Label.setText(_translate("iosRouterConfigPageWidget", "I/0 controller inlet:", None))
|
||||
self.uiSensor1SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C", None))
|
||||
self.uiSensor2Label.setText(_translate("iosRouterConfigPageWidget", "I/0 controller outlet:", None))
|
||||
self.uiSensor2SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C", None))
|
||||
self.uiSensor3Label.setText(_translate("iosRouterConfigPageWidget", "NPE inlet:", None))
|
||||
self.uiSensor3SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C", None))
|
||||
self.uiSensor4Label.setText(_translate("iosRouterConfigPageWidget", "NPE outlet:", None))
|
||||
self.uiSensor4SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C", None))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiEnvironmentPageWidget), _translate("iosRouterConfigPageWidget", "Environment", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
iosRouterConfigPageWidget.setWindowTitle(_translate("iosRouterConfigPageWidget", "Dynamips IOS Router configuration"))
|
||||
self.uiNameLabel.setText(_translate("iosRouterConfigPageWidget", "Name:"))
|
||||
self.uiPlatformLabel.setText(_translate("iosRouterConfigPageWidget", "Platform:"))
|
||||
self.uiChassisLabel.setText(_translate("iosRouterConfigPageWidget", "Chassis:"))
|
||||
self.uiIOSImageLabel.setText(_translate("iosRouterConfigPageWidget", "IOS image path:"))
|
||||
self.uiIOSImageToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse..."))
|
||||
self.uiStartupConfigLabel.setText(_translate("iosRouterConfigPageWidget", "Initial startup-config:"))
|
||||
self.uiStartupConfigToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse..."))
|
||||
self.uiPrivateConfigLabel.setText(_translate("iosRouterConfigPageWidget", "Initial private-config:"))
|
||||
self.uiPrivateConfigToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse..."))
|
||||
self.uiConsolePortLabel.setText(_translate("iosRouterConfigPageWidget", "Console port:"))
|
||||
self.uiAuxPortLabel.setText(_translate("iosRouterConfigPageWidget", "Aux port:"))
|
||||
self.uiMidplaneLabel.setText(_translate("iosRouterConfigPageWidget", "Midplane:"))
|
||||
self.uiNPELabel.setText(_translate("iosRouterConfigPageWidget", "NPE:"))
|
||||
self.uiSymbolLabel.setText(_translate("iosRouterConfigPageWidget", "Symbol:"))
|
||||
self.uiSymbolToolButton.setText(_translate("iosRouterConfigPageWidget", "&Browse..."))
|
||||
self.uiCategoryLabel.setText(_translate("iosRouterConfigPageWidget", "Category:"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralPageWidget), _translate("iosRouterConfigPageWidget", "General"))
|
||||
self.uiRamLabel.setText(_translate("iosRouterConfigPageWidget", "RAM size:"))
|
||||
self.uiRamSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB"))
|
||||
self.uiNvramLabel.setText(_translate("iosRouterConfigPageWidget", "NVRAM size:"))
|
||||
self.uiNvramSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " KiB"))
|
||||
self.uiIomemLabel.setText(_translate("iosRouterConfigPageWidget", "I/O memory :"))
|
||||
self.uiIomemSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " %"))
|
||||
self.uiDisk0Label.setText(_translate("iosRouterConfigPageWidget", "PCMCIA disk0:"))
|
||||
self.uiDisk0SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB"))
|
||||
self.uiDisk1Label.setText(_translate("iosRouterConfigPageWidget", "PCMCIA disk1:"))
|
||||
self.uiDisk1SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB"))
|
||||
self.uiAutoDeleteCheckBox.setText(_translate("iosRouterConfigPageWidget", "Automatically delete NVRAM and disk files"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiMemoriesPageWidget), _translate("iosRouterConfigPageWidget", "Memories and disks"))
|
||||
self.uiAdaptersGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Adapters"))
|
||||
self.uiSlot0Label.setText(_translate("iosRouterConfigPageWidget", "slot 0:"))
|
||||
self.uiSlot1Label.setText(_translate("iosRouterConfigPageWidget", "slot 1:"))
|
||||
self.uiSlot2Label.setText(_translate("iosRouterConfigPageWidget", "slot 2:"))
|
||||
self.uiSlot3Label.setText(_translate("iosRouterConfigPageWidget", "slot 3:"))
|
||||
self.uiSlot4Label.setText(_translate("iosRouterConfigPageWidget", "slot 4:"))
|
||||
self.uiSlot5Label.setText(_translate("iosRouterConfigPageWidget", "slot 5:"))
|
||||
self.uiSlot6Label.setText(_translate("iosRouterConfigPageWidget", "slot 6:"))
|
||||
self.uiWicsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "WICs"))
|
||||
self.uiWic0Label.setText(_translate("iosRouterConfigPageWidget", "wic 0:"))
|
||||
self.uiWic1Label.setText(_translate("iosRouterConfigPageWidget", "wic 1:"))
|
||||
self.uiWic2Label.setText(_translate("iosRouterConfigPageWidget", "wic 2:"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiSlotsPageWidget), _translate("iosRouterConfigPageWidget", "Slots"))
|
||||
self.uiSystemGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "System"))
|
||||
self.label.setText(_translate("iosRouterConfigPageWidget", "System ID:"))
|
||||
self.uiBaseMacLabel.setText(_translate("iosRouterConfigPageWidget", "Base MAC:"))
|
||||
self.uiOptimizationsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Optimisations"))
|
||||
self.uiExecAreaLabel.setText(_translate("iosRouterConfigPageWidget", "Exec area:"))
|
||||
self.uiExecAreaSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " MiB"))
|
||||
self.uiSparseMemoryCheckBox.setText(_translate("iosRouterConfigPageWidget", "Enable sparse memory support"))
|
||||
self.uiIdlepcLabel.setText(_translate("iosRouterConfigPageWidget", "Idle-PC:"))
|
||||
self.uiIdlemaxLabel.setText(_translate("iosRouterConfigPageWidget", "Idlemax:"))
|
||||
self.uiIdlesleepLabel.setText(_translate("iosRouterConfigPageWidget", "Idlesleep:"))
|
||||
self.uiMmapCheckBox.setText(_translate("iosRouterConfigPageWidget", "Enable mmap support"))
|
||||
self.uiIdlesleepSpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " ms"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiAdvancedPageWidget), _translate("iosRouterConfigPageWidget", "Advanced"))
|
||||
self.uiPowerSuppliesGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Power supplies"))
|
||||
self.uiPowerSupply2Label.setText(_translate("iosRouterConfigPageWidget", "Power supply 2:"))
|
||||
self.uiPowerSupply1ComboBox.setItemText(0, _translate("iosRouterConfigPageWidget", "on"))
|
||||
self.uiPowerSupply1ComboBox.setItemText(1, _translate("iosRouterConfigPageWidget", "off"))
|
||||
self.uiPowerSupply1Label.setText(_translate("iosRouterConfigPageWidget", "Power supply 1:"))
|
||||
self.uiPowerSupply2ComboBox.setItemText(0, _translate("iosRouterConfigPageWidget", "on"))
|
||||
self.uiPowerSupply2ComboBox.setItemText(1, _translate("iosRouterConfigPageWidget", "off"))
|
||||
self.uiSensorsGroupBox.setTitle(_translate("iosRouterConfigPageWidget", "Temperature sensors"))
|
||||
self.uiSensor1Label.setText(_translate("iosRouterConfigPageWidget", "I/0 controller inlet:"))
|
||||
self.uiSensor1SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C"))
|
||||
self.uiSensor2Label.setText(_translate("iosRouterConfigPageWidget", "I/0 controller outlet:"))
|
||||
self.uiSensor2SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C"))
|
||||
self.uiSensor3Label.setText(_translate("iosRouterConfigPageWidget", "NPE inlet:"))
|
||||
self.uiSensor3SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C"))
|
||||
self.uiSensor4Label.setText(_translate("iosRouterConfigPageWidget", "NPE outlet:"))
|
||||
self.uiSensor4SpinBox.setSuffix(_translate("iosRouterConfigPageWidget", " C"))
|
||||
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiEnvironmentPageWidget), _translate("iosRouterConfigPageWidget", "Environment"))
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>560</width>
|
||||
<height>518</height>
|
||||
<width>505</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -38,6 +38,9 @@
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
|
||||
@@ -1,36 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/dynamips/ui/ios_router_preferences_page.ui'
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/modules/dynamips/ui/ios_router_preferences_page.ui'
|
||||
#
|
||||
# Created: Wed Mar 11 22:03:56 2015
|
||||
# by: PyQt4 UI code generator 4.10.4
|
||||
# Created: Wed Jul 15 12:22:33 2015
|
||||
# by: PyQt5 UI code generator 5.4
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_IOSRouterPreferencesPageWidget(object):
|
||||
def setupUi(self, IOSRouterPreferencesPageWidget):
|
||||
IOSRouterPreferencesPageWidget.setObjectName(_fromUtf8("IOSRouterPreferencesPageWidget"))
|
||||
IOSRouterPreferencesPageWidget.resize(560, 518)
|
||||
self.gridLayout = QtGui.QGridLayout(IOSRouterPreferencesPageWidget)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.uiIOSRoutersTreeWidget = QtGui.QTreeWidget(IOSRouterPreferencesPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
IOSRouterPreferencesPageWidget.setObjectName("IOSRouterPreferencesPageWidget")
|
||||
IOSRouterPreferencesPageWidget.resize(505, 350)
|
||||
self.gridLayout = QtWidgets.QGridLayout(IOSRouterPreferencesPageWidget)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiIOSRoutersTreeWidget = QtWidgets.QTreeWidget(IOSRouterPreferencesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiIOSRoutersTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
@@ -41,39 +27,40 @@ class Ui_IOSRouterPreferencesPageWidget(object):
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.uiIOSRoutersTreeWidget.setFont(font)
|
||||
self.uiIOSRoutersTreeWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.uiIOSRoutersTreeWidget.setIconSize(QtCore.QSize(32, 32))
|
||||
self.uiIOSRoutersTreeWidget.setRootIsDecorated(False)
|
||||
self.uiIOSRoutersTreeWidget.setObjectName(_fromUtf8("uiIOSRoutersTreeWidget"))
|
||||
self.uiIOSRoutersTreeWidget.headerItem().setText(0, _fromUtf8("1"))
|
||||
self.uiIOSRoutersTreeWidget.setObjectName("uiIOSRoutersTreeWidget")
|
||||
self.uiIOSRoutersTreeWidget.headerItem().setText(0, "1")
|
||||
self.uiIOSRoutersTreeWidget.header().setVisible(False)
|
||||
self.gridLayout.addWidget(self.uiIOSRoutersTreeWidget, 0, 0, 2, 1)
|
||||
self.uiIOSRouterInfoTreeWidget = QtGui.QTreeWidget(IOSRouterPreferencesPageWidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding)
|
||||
self.uiIOSRouterInfoTreeWidget = QtWidgets.QTreeWidget(IOSRouterPreferencesPageWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.uiIOSRouterInfoTreeWidget.sizePolicy().hasHeightForWidth())
|
||||
self.uiIOSRouterInfoTreeWidget.setSizePolicy(sizePolicy)
|
||||
self.uiIOSRouterInfoTreeWidget.setIndentation(10)
|
||||
self.uiIOSRouterInfoTreeWidget.setAllColumnsShowFocus(True)
|
||||
self.uiIOSRouterInfoTreeWidget.setObjectName(_fromUtf8("uiIOSRouterInfoTreeWidget"))
|
||||
self.uiIOSRouterInfoTreeWidget.setObjectName("uiIOSRouterInfoTreeWidget")
|
||||
self.uiIOSRouterInfoTreeWidget.header().setVisible(False)
|
||||
self.gridLayout.addWidget(self.uiIOSRouterInfoTreeWidget, 0, 1, 1, 1)
|
||||
self.horizontalLayout_6 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6"))
|
||||
self.uiNewIOSRouterPushButton = QtGui.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiNewIOSRouterPushButton.setObjectName(_fromUtf8("uiNewIOSRouterPushButton"))
|
||||
self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
|
||||
self.uiNewIOSRouterPushButton = QtWidgets.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiNewIOSRouterPushButton.setObjectName("uiNewIOSRouterPushButton")
|
||||
self.horizontalLayout_6.addWidget(self.uiNewIOSRouterPushButton)
|
||||
self.uiDecompressIOSPushButton = QtGui.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiDecompressIOSPushButton = QtWidgets.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiDecompressIOSPushButton.setEnabled(False)
|
||||
self.uiDecompressIOSPushButton.setObjectName(_fromUtf8("uiDecompressIOSPushButton"))
|
||||
self.uiDecompressIOSPushButton.setObjectName("uiDecompressIOSPushButton")
|
||||
self.horizontalLayout_6.addWidget(self.uiDecompressIOSPushButton)
|
||||
self.uiEditIOSRouterPushButton = QtGui.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiEditIOSRouterPushButton = QtWidgets.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiEditIOSRouterPushButton.setEnabled(False)
|
||||
self.uiEditIOSRouterPushButton.setObjectName(_fromUtf8("uiEditIOSRouterPushButton"))
|
||||
self.uiEditIOSRouterPushButton.setObjectName("uiEditIOSRouterPushButton")
|
||||
self.horizontalLayout_6.addWidget(self.uiEditIOSRouterPushButton)
|
||||
self.uiDeleteIOSRouterPushButton = QtGui.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiDeleteIOSRouterPushButton = QtWidgets.QPushButton(IOSRouterPreferencesPageWidget)
|
||||
self.uiDeleteIOSRouterPushButton.setEnabled(False)
|
||||
self.uiDeleteIOSRouterPushButton.setObjectName(_fromUtf8("uiDeleteIOSRouterPushButton"))
|
||||
self.uiDeleteIOSRouterPushButton.setObjectName("uiDeleteIOSRouterPushButton")
|
||||
self.horizontalLayout_6.addWidget(self.uiDeleteIOSRouterPushButton)
|
||||
self.gridLayout.addLayout(self.horizontalLayout_6, 1, 1, 1, 1)
|
||||
|
||||
@@ -81,12 +68,13 @@ class Ui_IOSRouterPreferencesPageWidget(object):
|
||||
QtCore.QMetaObject.connectSlotsByName(IOSRouterPreferencesPageWidget)
|
||||
|
||||
def retranslateUi(self, IOSRouterPreferencesPageWidget):
|
||||
IOSRouterPreferencesPageWidget.setWindowTitle(_translate("IOSRouterPreferencesPageWidget", "IOS routers", None))
|
||||
IOSRouterPreferencesPageWidget.setAccessibleName(_translate("IOSRouterPreferencesPageWidget", "IOS router templates", None))
|
||||
self.uiIOSRouterInfoTreeWidget.headerItem().setText(0, _translate("IOSRouterPreferencesPageWidget", "1", None))
|
||||
self.uiIOSRouterInfoTreeWidget.headerItem().setText(1, _translate("IOSRouterPreferencesPageWidget", "2", None))
|
||||
self.uiNewIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&New", None))
|
||||
self.uiDecompressIOSPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Decompress", None))
|
||||
self.uiEditIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Edit", None))
|
||||
self.uiDeleteIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Delete", None))
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
IOSRouterPreferencesPageWidget.setWindowTitle(_translate("IOSRouterPreferencesPageWidget", "IOS routers"))
|
||||
IOSRouterPreferencesPageWidget.setAccessibleName(_translate("IOSRouterPreferencesPageWidget", "IOS router templates"))
|
||||
self.uiIOSRouterInfoTreeWidget.headerItem().setText(0, _translate("IOSRouterPreferencesPageWidget", "1"))
|
||||
self.uiIOSRouterInfoTreeWidget.headerItem().setText(1, _translate("IOSRouterPreferencesPageWidget", "2"))
|
||||
self.uiNewIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&New"))
|
||||
self.uiDecompressIOSPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Decompress"))
|
||||
self.uiEditIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Edit"))
|
||||
self.uiDeleteIOSRouterPushButton.setText(_translate("IOSRouterPreferencesPageWidget", "&Delete"))
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="uiCloudRadioButton">
|
||||
<widget class="QRadioButton" name="uiVMRadioButton">
|
||||
<property name="text">
|
||||
<string>Cloud</string>
|
||||
<string>GNS3 VM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -118,9 +118,63 @@
|
||||
<property name="subTitle">
|
||||
<string>Please choose an IOS image.</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="uiIOSExistingImageRadioButton">
|
||||
<property name="text">
|
||||
<string>Existing image</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="uiIOSNewImageRadioButton">
|
||||
<property name="text">
|
||||
<string>New Image</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="uiIOSImageLabel">
|
||||
<property name="text">
|
||||
<string>IOS image:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QComboBox" name="uiIOSImageListComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiIOSImageLineEdit"/>
|
||||
</item>
|
||||
@@ -136,13 +190,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiIOSImageLabel">
|
||||
<property name="text">
|
||||
<string>IOS image:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="uiNamePlatformWizardPage">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user