mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-29 15:00:31 +03:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aab0c99cc6 | ||
|
|
a6a987d74c | ||
|
|
9c58b18c20 | ||
|
|
8bc499c68f | ||
|
|
bd5eb288b7 | ||
|
|
465a289568 | ||
|
|
d240ba3056 | ||
|
|
3cedfd3649 | ||
|
|
276d7abdd9 | ||
|
|
927e38bd6d | ||
|
|
376cc29995 | ||
|
|
1f8ebeb084 | ||
|
|
0212755c78 | ||
|
|
2f7d75eae9 | ||
|
|
fc1c060922 | ||
|
|
0ea72ce782 | ||
|
|
3de2d2eda2 | ||
|
|
c08262f8af | ||
|
|
9ae70bf2fe | ||
|
|
fa6d250602 | ||
|
|
0668840a2b | ||
|
|
8b25d1b06c | ||
|
|
58c3ba0755 | ||
|
|
5a91c9aaf8 | ||
|
|
0fc3f4ef16 | ||
|
|
d3d9e1e8ae | ||
|
|
05f8df345a | ||
|
|
3e212fc629 | ||
|
|
25e41dc0f1 | ||
|
|
c58c7774c4 | ||
|
|
bd2bc8265c | ||
|
|
f2209a2780 | ||
|
|
5dc2c77806 |
18
CHANGELOG
18
CHANGELOG
@@ -1,5 +1,23 @@
|
||||
# Change Log
|
||||
|
||||
## 2.2.18 16/02/2021
|
||||
|
||||
* SSL support.
|
||||
* Remove the useless file "zoom-in (copy).svg". Fixes #3114
|
||||
* Use HDD disk image as startup QEMU config disk
|
||||
* Edit only text mode config files
|
||||
* Hide config import/export when configFiles attribute is empty
|
||||
* Qemu disk interfaces must be set to "none" by default. Ref #3035
|
||||
* Do not allow image to be configured on Qemu VM secondary slave disk if create config disk option is enabled.
|
||||
* Add explicit option to automatically create or not the config disk. Off by default.
|
||||
* QEMU config disk support
|
||||
|
||||
## 2.2.17 04/12/2020
|
||||
|
||||
* Remove "-nographic" option by default for Qemu VM. Fixes #3094
|
||||
* Fix app cannot start on macOS Big Sur. Ref #3037
|
||||
* Require confirmation before stopping all devices.
|
||||
|
||||
## 2.2.16 05/11/2020
|
||||
|
||||
* Fix packets capture stops after some time. Fixes #3067
|
||||
|
||||
@@ -130,7 +130,7 @@ class Controller(QtCore.QObject):
|
||||
|
||||
self._connected = False
|
||||
self._connecting = True
|
||||
self.get('/version', self._versionGetSlot)
|
||||
self.httpClient().getSynchronous('/version', self._versionGetSlot, timeout=60)
|
||||
|
||||
def _httpClientDisconnectedSlot(self):
|
||||
if self._connected:
|
||||
@@ -423,6 +423,7 @@ class Controller(QtCore.QObject):
|
||||
self._notification_stream = self._http_client.connectWebSocket(self._websocket, "/notifications/ws")
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
|
||||
def stopListenNotifications(self):
|
||||
if self._notification_stream:
|
||||
@@ -447,6 +448,11 @@ class Controller(QtCore.QObject):
|
||||
self._notification_stream = None
|
||||
self._startListenNotifications()
|
||||
|
||||
@qslot
|
||||
def _sslErrorsSlot(self, ssl_errors):
|
||||
|
||||
self._http_client.handleSslError(self._notification_stream, ssl_errors)
|
||||
|
||||
@qslot
|
||||
def _websocket_event_received(self, event):
|
||||
try:
|
||||
|
||||
@@ -51,7 +51,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://7327ec4a849d436dba47b2fea9e2420e:efa92865e9534a22afab21a47692de8e@o19455.ingest.sentry.io/38506"
|
||||
DSN = "https://4983a844616742629f6ff91f8cc2eb59:9a3f497bcd12445cb7769fda00921937@o19455.ingest.sentry.io/38506"
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -41,6 +41,9 @@ class EditComputeDialog(QtWidgets.QDialog, Ui_EditComputeDialog):
|
||||
self.uiServerHostLineEdit.setText(self._compute.host())
|
||||
self.uiServerPortSpinBox.setValue(self._compute.port())
|
||||
|
||||
index = self.uiServerProtocolComboBox.findText(self._compute.protocol().upper())
|
||||
self.uiServerProtocolComboBox.setCurrentIndex(index)
|
||||
|
||||
if self._compute.user():
|
||||
self.uiEnableAuthenticationCheckBox.setChecked(True)
|
||||
self.uiServerUserLineEdit.setText(self._compute.user())
|
||||
@@ -78,7 +81,7 @@ class EditComputeDialog(QtWidgets.QDialog, Ui_EditComputeDialog):
|
||||
|
||||
host = self.uiServerHostLineEdit.text().strip()
|
||||
name = self.uiServerNameLineEdit.text().strip()
|
||||
protocol = "http"
|
||||
protocol = self.uiServerProtocolComboBox.currentText().lower()
|
||||
port = self.uiServerPortSpinBox.value()
|
||||
user = self.uiServerUserLineEdit.text().strip()
|
||||
password = self.uiServerPasswordLineEdit.text().strip()
|
||||
|
||||
@@ -861,19 +861,19 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
bring_to_front_action.triggered.connect(self.bringToFrontSlot)
|
||||
menu.addAction(bring_to_front_action)
|
||||
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "configFiles"), items)):
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and bool(item.node().configFiles()), items)):
|
||||
import_config_action = QtWidgets.QAction("Import config", menu)
|
||||
import_config_action.setIcon(get_icon("import.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(), "configFiles"), items)):
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and bool(item.node().configFiles()), items)):
|
||||
export_config_action = QtWidgets.QAction("Export config", menu)
|
||||
export_config_action.setIcon(get_icon("export.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(), "configFiles"), items)):
|
||||
if True in list(map(lambda item: isinstance(item, NodeItem) and bool(item.node().configTextFiles()), items)):
|
||||
export_config_action = QtWidgets.QAction("Edit config", menu)
|
||||
export_config_action.setIcon(get_icon("edit.svg"))
|
||||
export_config_action.triggered.connect(self.editConfigActionSlot)
|
||||
@@ -1226,7 +1226,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
|
||||
items = []
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "configFiles") and item.node().initialized():
|
||||
if isinstance(item, NodeItem) and item.node().configFiles() and item.node().initialized():
|
||||
items.append(item)
|
||||
|
||||
if not items:
|
||||
@@ -1257,17 +1257,17 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
|
||||
items = []
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "configFiles") and item.node().initialized():
|
||||
if isinstance(item, NodeItem) and item.node().configTextFiles() and item.node().initialized():
|
||||
items.append(item)
|
||||
|
||||
if not items:
|
||||
return
|
||||
|
||||
for item in items:
|
||||
if len(item.node().configFiles()) == 1:
|
||||
config_file = item.node().configFiles()[0]
|
||||
if len(item.node().configTextFiles()) == 1:
|
||||
config_file = item.node().configTextFiles()[0]
|
||||
else:
|
||||
config_file, ok = QtWidgets.QInputDialog.getItem(self, "Edit file", "File to edit?", item.node().configFiles(), 0, False)
|
||||
config_file, ok = QtWidgets.QInputDialog.getItem(self, "Edit file", "File to edit?", item.node().configTextFiles(), 0, False)
|
||||
if not ok:
|
||||
continue
|
||||
dialog = FileEditorDialog(item.node(), config_file, parent=self)
|
||||
@@ -1282,7 +1282,7 @@ class GraphicsView(QtWidgets.QGraphicsView):
|
||||
|
||||
items = []
|
||||
for item in self.scene().selectedItems():
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "configFiles") and item.node().initialized():
|
||||
if isinstance(item, NodeItem) and item.node().configFiles() and item.node().initialized():
|
||||
items.append(item)
|
||||
|
||||
if not items:
|
||||
|
||||
@@ -18,18 +18,15 @@
|
||||
from .qt import sip
|
||||
import json
|
||||
import copy
|
||||
import http
|
||||
import uuid
|
||||
import pathlib
|
||||
import base64
|
||||
import datetime
|
||||
import ipaddress
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
|
||||
|
||||
from .version import __version__, __version_info__
|
||||
from .qt import QtCore, QtNetwork, qpartial, sip_is_deleted
|
||||
from .qt import QtCore, QtNetwork, QtWidgets, qpartial, sip_is_deleted
|
||||
from .utils import parse_version
|
||||
|
||||
import logging
|
||||
@@ -79,6 +76,18 @@ class HTTPClient(QtCore.QObject):
|
||||
self._shutdown = False # Shutdown in progress
|
||||
self._accept_insecure_certificate = settings.get("accept_insecure_certificate", None)
|
||||
|
||||
# Add custom CA
|
||||
# ssl_config = QtNetwork.QSslConfiguration.defaultConfiguration()
|
||||
# if ssl_config.addCaCertificates("/path/to/rootCA.crt"):
|
||||
# log.debug("CA certificate added")
|
||||
# QtNetwork.QSslConfiguration.setDefaultConfiguration(ssl_config)
|
||||
|
||||
if self._protocol == "https":
|
||||
if not QtNetwork.QSslSocket.supportsSsl():
|
||||
log.error("SSL is not supported")
|
||||
else:
|
||||
log.debug(f"SSL is supported, version: {QtNetwork.QSslSocket().sslLibraryBuildVersionString()}")
|
||||
|
||||
# In order to detect computer hibernation we detect the date of the last
|
||||
# query and disconnect if time is too long between two query
|
||||
self._last_query_timestamp = None
|
||||
@@ -93,6 +102,12 @@ class HTTPClient(QtCore.QObject):
|
||||
# List of query waiting for the connection
|
||||
self._query_waiting_connections = []
|
||||
|
||||
# To catch SSL errors
|
||||
self._network_manager.sslErrors.connect(self._sslErrorsSlot)
|
||||
|
||||
# Store SSL error exceptions
|
||||
self._ssl_exceptions = {}
|
||||
|
||||
def setMaxTimeDifferenceBetweenQueries(self, value):
|
||||
self._max_time_difference_between_queries = value
|
||||
|
||||
@@ -470,7 +485,14 @@ class HTTPClient(QtCore.QObject):
|
||||
"""
|
||||
host = self._getHostForQuery()
|
||||
request = websocket.request()
|
||||
ws_url = "ws://{host}:{port}{prefix}{path}".format(host=host, port=self._port, path=path, prefix=prefix)
|
||||
ws_protocol = "ws"
|
||||
if self._protocol == "https":
|
||||
ws_protocol = "wss"
|
||||
ws_url = "{protocol}://{host}:{port}{prefix}{path}".format(protocol=ws_protocol,
|
||||
host=host,
|
||||
port=self._port,
|
||||
path=path,
|
||||
prefix=prefix)
|
||||
log.debug("Connecting to WebSocket endpoint: {}".format(ws_url))
|
||||
request.setUrl(QtCore.QUrl(ws_url))
|
||||
self._addAuth(request)
|
||||
@@ -776,6 +798,55 @@ class HTTPClient(QtCore.QObject):
|
||||
return status, json_data
|
||||
return status, None
|
||||
|
||||
def _sslErrorsSlot(self, response, ssl_errors):
|
||||
|
||||
self.handleSslError(response, ssl_errors)
|
||||
|
||||
def handleSslError(self, response, ssl_errors):
|
||||
|
||||
if self._accept_insecure_certificate:
|
||||
response.ignoreSslErrors()
|
||||
return
|
||||
|
||||
url = response.request().url()
|
||||
host_port_key = f"{url.host()}:{url.port()}"
|
||||
|
||||
# get the certificate digest
|
||||
ssl_config = response.sslConfiguration()
|
||||
peer_cert = ssl_config.peerCertificate()
|
||||
digest = peer_cert.digest()
|
||||
|
||||
if host_port_key in self._ssl_exceptions:
|
||||
|
||||
if self._ssl_exceptions[host_port_key] == digest:
|
||||
response.ignoreSslErrors()
|
||||
return
|
||||
|
||||
from gns3.main_window import MainWindow
|
||||
main_window = MainWindow.instance()
|
||||
|
||||
msgbox = QtWidgets.QMessageBox(main_window)
|
||||
msgbox.setWindowTitle("SSL error detected")
|
||||
msgbox.setText(f"This server could not prove that it is {url.host()}:{url.port()}. Please carefully examine the certificate to make sure the server can be trusted.")
|
||||
msgbox.setInformativeText(f"{ssl_errors[0].errorString()}")
|
||||
msgbox.setDetailedText(peer_cert.toText())
|
||||
msgbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
connect_button = QtWidgets.QPushButton(f"&Connect to {url.host()}:{url.port()}", msgbox)
|
||||
msgbox.addButton(connect_button, QtWidgets.QMessageBox.YesRole)
|
||||
abort_button = QtWidgets.QPushButton("&Abort", msgbox)
|
||||
msgbox.addButton(abort_button, QtWidgets.QMessageBox.RejectRole)
|
||||
msgbox.setDefaultButton(abort_button)
|
||||
msgbox.setIcon(QtWidgets.QMessageBox.Critical)
|
||||
msgbox.exec_()
|
||||
|
||||
if msgbox.clickedButton() == connect_button:
|
||||
self._ssl_exceptions[host_port_key] = digest
|
||||
response.ignoreSslErrors()
|
||||
else:
|
||||
for error in ssl_errors:
|
||||
log.error(f"SSL error detected: {error.errorString()}")
|
||||
main_window.close()
|
||||
|
||||
@classmethod
|
||||
def fromUrl(cls, url, network_manager=None, base_settings=None):
|
||||
"""
|
||||
|
||||
@@ -118,6 +118,9 @@ def main():
|
||||
# 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_")]
|
||||
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.15.2"):
|
||||
# Fixes issue on macOS Big Sur: https://github.com/GNS3/gns3-gui/issues/3037
|
||||
os.environ["QT_MAC_WANTS_LAYER"] = "1"
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?")
|
||||
|
||||
@@ -810,6 +810,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
Slot called when starting all the nodes.
|
||||
"""
|
||||
|
||||
reply = QtWidgets.QMessageBox.question(self, "Confirm Start All", "Are you sure you want to start all devices?",
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
project = Topology.instance().project()
|
||||
if project is not None:
|
||||
project.start_all_nodes()
|
||||
@@ -819,6 +826,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
Slot called when suspending all the nodes.
|
||||
"""
|
||||
|
||||
reply = QtWidgets.QMessageBox.question(self, "Confirm Suspend All", "Are you sure you want to suspend all devices?",
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
project = Topology.instance().project()
|
||||
if project is not None:
|
||||
project.suspend_all_nodes()
|
||||
@@ -828,6 +841,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
Slot called when stopping all the nodes.
|
||||
"""
|
||||
|
||||
reply = QtWidgets.QMessageBox.question(self, "Confirm Stop All", "Are you sure you want to stop all devices?",
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
project = Topology.instance().project()
|
||||
if project is not None:
|
||||
project.stop_all_nodes()
|
||||
@@ -837,6 +856,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
Slot called when reloading all the nodes.
|
||||
"""
|
||||
|
||||
reply = QtWidgets.QMessageBox.question(self, "Confirm Reload All", "Are you sure you want to reload all devices?",
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
||||
|
||||
if reply == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
project = Topology.instance().project()
|
||||
if project is not None:
|
||||
project.reload_all_nodes()
|
||||
|
||||
@@ -177,8 +177,6 @@ class QemuVMWizard(VMWithImagesWizard, Ui_QemuVMWizard):
|
||||
(sys.platform.startswith("darwin") and "GNS3.app" in qemu_path):
|
||||
settings["options"] += " -vga none -vnc none"
|
||||
settings["legacy_networking"] = True
|
||||
else:
|
||||
settings["options"] += " -nographic"
|
||||
settings["options"] = settings["options"].strip()
|
||||
|
||||
return settings
|
||||
|
||||
@@ -90,6 +90,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
|
||||
self.uiActivateCPUThrottlingCheckBox.stateChanged.connect(self._cpuThrottlingChangedSlot)
|
||||
self.uiLegacyNetworkingCheckBox.stateChanged.connect(self._legacyNetworkingChangedSlot)
|
||||
self.uiCustomAdaptersConfigurationPushButton.clicked.connect(self._customAdaptersConfigurationSlot)
|
||||
self.uiCreateConfigDiskCheckBox.stateChanged.connect(self._createConfigDiskChangedSlot)
|
||||
|
||||
# add the categories
|
||||
for name, category in Node.defaultCategories().items():
|
||||
@@ -366,6 +367,19 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
|
||||
else:
|
||||
self._refreshQemuNetworkDevices()
|
||||
|
||||
def _createConfigDiskChangedSlot(self, state):
|
||||
"""
|
||||
Slot to allow or not HDD disk to be configured based on the state of the config disk option.
|
||||
"""
|
||||
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
if state:
|
||||
self.uiHddDiskImageLabel.setText(_translate("QemuVMConfigPageWidget", "Startup-cfg:"))
|
||||
else:
|
||||
self.uiHddDiskImageLabel.setText(_translate("QemuVMConfigPageWidget", "Disk image:"))
|
||||
self.uiHddDiskImageCreateToolButton.setEnabled(not state)
|
||||
self.uiHddDiskImageResizeToolButton.setEnabled(not state)
|
||||
|
||||
def _customAdaptersConfigurationSlot(self):
|
||||
"""
|
||||
Slot to open the custom adapters configuration dialog
|
||||
@@ -453,6 +467,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
|
||||
self.uiHdbDiskInterfaceComboBox.setCurrentIndex(self.uiHdbDiskInterfaceComboBox.findText(settings["hdb_disk_interface"]))
|
||||
self.uiHdcDiskInterfaceComboBox.setCurrentIndex(self.uiHdcDiskInterfaceComboBox.findText(settings["hdc_disk_interface"]))
|
||||
self.uiHddDiskInterfaceComboBox.setCurrentIndex(self.uiHddDiskInterfaceComboBox.findText(settings["hdd_disk_interface"]))
|
||||
self.uiCreateConfigDiskCheckBox.setChecked(settings["create_config_disk"])
|
||||
self.uiCdromImageLineEdit.setText(settings["cdrom_image"])
|
||||
self.uiBiosImageLineEdit.setText(settings["bios_image"])
|
||||
self.uiInitrdLineEdit.setText(settings["initrd"])
|
||||
@@ -588,6 +603,7 @@ class QemuVMConfigurationPage(QtWidgets.QWidget, Ui_QemuVMConfigPageWidget):
|
||||
settings["hdb_disk_interface"] = self.uiHdbDiskInterfaceComboBox.currentText()
|
||||
settings["hdc_disk_interface"] = self.uiHdcDiskInterfaceComboBox.currentText()
|
||||
settings["hdd_disk_interface"] = self.uiHddDiskInterfaceComboBox.currentText()
|
||||
settings["create_config_disk"] = self.uiCreateConfigDiskCheckBox.isChecked()
|
||||
settings["cdrom_image"] = self.uiCdromImageLineEdit.text().strip()
|
||||
settings["bios_image"] = self.uiBiosImageLineEdit.text().strip()
|
||||
settings["initrd"] = self.uiInitrdLineEdit.text().strip()
|
||||
|
||||
@@ -72,6 +72,7 @@ class QemuVM(Node):
|
||||
"mac_address": QEMU_VM_SETTINGS["mac_address"],
|
||||
"legacy_networking": QEMU_VM_SETTINGS["legacy_networking"],
|
||||
"replicate_network_connection_state": QEMU_VM_SETTINGS["replicate_network_connection_state"],
|
||||
"create_config_disk": QEMU_VM_SETTINGS["create_config_disk"],
|
||||
"platform": QEMU_VM_SETTINGS["platform"],
|
||||
"on_close": QEMU_VM_SETTINGS["on_close"],
|
||||
"cpu_throttling": QEMU_VM_SETTINGS["cpu_throttling"],
|
||||
@@ -134,6 +135,24 @@ class QemuVM(Node):
|
||||
usage = "\n" + self._settings.get("usage")
|
||||
return info + port_info + usage
|
||||
|
||||
def configFiles(self):
|
||||
"""
|
||||
Name of the configuration files
|
||||
"""
|
||||
|
||||
if self._settings.get("create_config_disk"):
|
||||
return ["config.zip"]
|
||||
return None
|
||||
|
||||
def configTextFiles(self):
|
||||
"""
|
||||
Name of the configuration files, which are plain text files
|
||||
|
||||
:returns: List of configuration files, False if no files
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
def configPage(self):
|
||||
"""
|
||||
Returns the configuration page widget to be used by the node properties dialog.
|
||||
|
||||
@@ -41,10 +41,10 @@ QEMU_VM_SETTINGS = {
|
||||
"hdb_disk_image": "",
|
||||
"hdc_disk_image": "",
|
||||
"hdd_disk_image": "",
|
||||
"hda_disk_interface": "ide",
|
||||
"hdb_disk_interface": "ide",
|
||||
"hdc_disk_interface": "ide",
|
||||
"hdd_disk_interface": "ide",
|
||||
"hda_disk_interface": "none",
|
||||
"hdb_disk_interface": "none",
|
||||
"hdc_disk_interface": "none",
|
||||
"hdd_disk_interface": "none",
|
||||
"cdrom_image": "",
|
||||
"bios_image": "",
|
||||
"boot_priority": "c",
|
||||
@@ -57,6 +57,7 @@ QEMU_VM_SETTINGS = {
|
||||
"mac_address": "",
|
||||
"legacy_networking": False,
|
||||
"replicate_network_connection_state": True,
|
||||
"create_config_disk": False,
|
||||
"on_close": "power_off",
|
||||
"platform": "",
|
||||
"cpu_throttling": 0,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>941</width>
|
||||
<height>877</height>
|
||||
<height>939</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -399,14 +399,21 @@
|
||||
<string>HDD (Secondary Slave)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="uiCreateConfigDiskCheckBox">
|
||||
<property name="text">
|
||||
<string>Automatically create a config disk on HDD</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiHddDiskImageLabel">
|
||||
<property name="text">
|
||||
<string>Disk image:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uiHddDiskImageLineEdit"/>
|
||||
@@ -437,7 +444,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uiHddDiskInterfaceLabel">
|
||||
<property name="text">
|
||||
<string>Disk interface:</string>
|
||||
@@ -470,7 +477,16 @@
|
||||
<string>CD/DVD</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
|
||||
@@ -13,7 +13,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_QemuVMConfigPageWidget(object):
|
||||
def setupUi(self, QemuVMConfigPageWidget):
|
||||
QemuVMConfigPageWidget.setObjectName("QemuVMConfigPageWidget")
|
||||
QemuVMConfigPageWidget.resize(941, 877)
|
||||
QemuVMConfigPageWidget.resize(941, 939)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(QemuVMConfigPageWidget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.uiQemutabWidget = QtWidgets.QTabWidget(QemuVMConfigPageWidget)
|
||||
@@ -211,9 +211,12 @@ class Ui_QemuVMConfigPageWidget(object):
|
||||
self.uiHddGroupBox.setObjectName("uiHddGroupBox")
|
||||
self.gridLayout_9 = QtWidgets.QGridLayout(self.uiHddGroupBox)
|
||||
self.gridLayout_9.setObjectName("gridLayout_9")
|
||||
self.uiCreateConfigDiskCheckBox = QtWidgets.QCheckBox(self.uiHddGroupBox)
|
||||
self.uiCreateConfigDiskCheckBox.setObjectName("uiCreateConfigDiskCheckBox")
|
||||
self.gridLayout_9.addWidget(self.uiCreateConfigDiskCheckBox, 0, 0, 1, 2)
|
||||
self.uiHddDiskImageLabel = QtWidgets.QLabel(self.uiHddGroupBox)
|
||||
self.uiHddDiskImageLabel.setObjectName("uiHddDiskImageLabel")
|
||||
self.gridLayout_9.addWidget(self.uiHddDiskImageLabel, 0, 0, 1, 1)
|
||||
self.gridLayout_9.addWidget(self.uiHddDiskImageLabel, 1, 0, 1, 1)
|
||||
self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
|
||||
self.uiHddDiskImageLineEdit = QtWidgets.QLineEdit(self.uiHddGroupBox)
|
||||
@@ -229,10 +232,10 @@ class Ui_QemuVMConfigPageWidget(object):
|
||||
self.uiHddDiskImageResizeToolButton = QtWidgets.QToolButton(self.uiHddGroupBox)
|
||||
self.uiHddDiskImageResizeToolButton.setObjectName("uiHddDiskImageResizeToolButton")
|
||||
self.horizontalLayout_10.addWidget(self.uiHddDiskImageResizeToolButton)
|
||||
self.gridLayout_9.addLayout(self.horizontalLayout_10, 0, 1, 2, 1)
|
||||
self.gridLayout_9.addLayout(self.horizontalLayout_10, 1, 1, 1, 1)
|
||||
self.uiHddDiskInterfaceLabel = QtWidgets.QLabel(self.uiHddGroupBox)
|
||||
self.uiHddDiskInterfaceLabel.setObjectName("uiHddDiskInterfaceLabel")
|
||||
self.gridLayout_9.addWidget(self.uiHddDiskInterfaceLabel, 1, 0, 2, 1)
|
||||
self.gridLayout_9.addWidget(self.uiHddDiskInterfaceLabel, 2, 0, 1, 1)
|
||||
self.uiHddDiskInterfaceComboBox = QtWidgets.QComboBox(self.uiHddGroupBox)
|
||||
self.uiHddDiskInterfaceComboBox.setObjectName("uiHddDiskInterfaceComboBox")
|
||||
self.gridLayout_9.addWidget(self.uiHddDiskInterfaceComboBox, 2, 1, 1, 1)
|
||||
@@ -497,6 +500,7 @@ class Ui_QemuVMConfigPageWidget(object):
|
||||
self.uiHdcDiskImageResizeToolButton.setText(_translate("QemuVMConfigPageWidget", "Resize..."))
|
||||
self.uiHdcDiskInterfaceLabel.setText(_translate("QemuVMConfigPageWidget", "Disk interface:"))
|
||||
self.uiHddGroupBox.setTitle(_translate("QemuVMConfigPageWidget", "HDD (Secondary Slave)"))
|
||||
self.uiCreateConfigDiskCheckBox.setText(_translate("QemuVMConfigPageWidget", "Automatically create a config disk on HDD"))
|
||||
self.uiHddDiskImageLabel.setText(_translate("QemuVMConfigPageWidget", "Disk image:"))
|
||||
self.uiHddDiskImageToolButton.setText(_translate("QemuVMConfigPageWidget", "&Browse..."))
|
||||
self.uiHddDiskImageCreateToolButton.setText(_translate("QemuVMConfigPageWidget", "Create..."))
|
||||
|
||||
24
gns3/node.py
24
gns3/node.py
@@ -199,6 +199,26 @@ class Node(BaseNode):
|
||||
|
||||
return self._always_on
|
||||
|
||||
def configFiles(self):
|
||||
"""
|
||||
Name of the configuration files
|
||||
|
||||
This method should be overridden in derived classes
|
||||
|
||||
:returns: List of configuration files, False if no files
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
def configTextFiles(self):
|
||||
"""
|
||||
Name of the configuration files, which are plain text files
|
||||
|
||||
:returns: List of configuration files, False if no files
|
||||
"""
|
||||
|
||||
return self.configFiles()
|
||||
|
||||
def get(self, path, *args, **kwargs):
|
||||
"""
|
||||
GET on current server / project
|
||||
@@ -774,7 +794,7 @@ class Node(BaseNode):
|
||||
:param directory: destination directory path
|
||||
"""
|
||||
|
||||
if not hasattr(self, "configFiles"):
|
||||
if not self.configFiles():
|
||||
return False
|
||||
for file in self.configFiles():
|
||||
self.get("/files/{file}".format(file=file),
|
||||
@@ -813,7 +833,7 @@ class Node(BaseNode):
|
||||
:param directory: source directory path
|
||||
"""
|
||||
|
||||
if not hasattr(self, "configFiles"):
|
||||
if not self.configFiles():
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
@@ -191,6 +191,7 @@ class ServerPreferencesPage(QtWidgets.QWidget, Ui_ServerPreferencesPageWidget):
|
||||
|
||||
self.uiRemoteMainServerHostLineEdit.setText(servers_settings["host"])
|
||||
self.uiRemoteMainServerPortSpinBox.setValue(servers_settings["port"])
|
||||
self.uiRemoteMainServerProtocolComboBox.setCurrentText(servers_settings["protocol"].upper())
|
||||
self.uiRemoteMainServerUserLineEdit.setText(servers_settings["user"])
|
||||
self.uiRemoteMainServerPasswordLineEdit.setText(servers_settings["password"])
|
||||
self.uiRemoteMainServerAuthCheckBox.setChecked(servers_settings["auth"])
|
||||
@@ -285,7 +286,7 @@ class ServerPreferencesPage(QtWidgets.QWidget, Ui_ServerPreferencesPageWidget):
|
||||
else:
|
||||
new_local_server_settings["host"] = self.uiRemoteMainServerHostLineEdit.text()
|
||||
new_local_server_settings["port"] = self.uiRemoteMainServerPortSpinBox.value()
|
||||
new_local_server_settings["protocol"] = "http"
|
||||
new_local_server_settings["protocol"] = self.uiRemoteMainServerProtocolComboBox.currentText().lower()
|
||||
new_local_server_settings["user"] = self.uiRemoteMainServerUserLineEdit.text()
|
||||
new_local_server_settings["password"] = self.uiRemoteMainServerPasswordLineEdit.text()
|
||||
new_local_server_settings["auth"] = self.uiRemoteMainServerAuthCheckBox.isChecked()
|
||||
|
||||
@@ -632,6 +632,7 @@ class Project(QtCore.QObject):
|
||||
self._notification_stream = Controller.instance().httpClient().connectWebSocket(self._websocket, path)
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
|
||||
def _endListenNotificationCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
@@ -648,6 +649,11 @@ class Project(QtCore.QObject):
|
||||
self._notification_stream = None
|
||||
self._startListenNotifications()
|
||||
|
||||
@qslot
|
||||
def _sslErrorsSlot(self, ssl_errors):
|
||||
|
||||
Controller.instance().httpClient().handleSslError(self._notification_stream, ssl_errors)
|
||||
|
||||
@qslot
|
||||
def _websocket_event_received(self, event):
|
||||
try:
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>579</width>
|
||||
<height>374</height>
|
||||
<width>585</width>
|
||||
<height>353</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -23,10 +23,31 @@
|
||||
<string>Server settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="uiServerPortLabel">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="uiServerNameLineEdit"/>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="uiServerHostLineEdit">
|
||||
<property name="text">
|
||||
<string>192.168.56.101</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uiServerHostLabel">
|
||||
<property name="text">
|
||||
<string>Host:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QSpinBox" name="uiServerPortSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -52,25 +73,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="uiServerHostLineEdit">
|
||||
<property name="text">
|
||||
<string>192.168.56.101</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="uiServerHostLabel">
|
||||
<widget class="QLabel" name="uiServerProtocolLabel">
|
||||
<property name="text">
|
||||
<string>Host:</string>
|
||||
<string>Protocol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="uiServerPortLabel">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="uiServerProtocolComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HTTP</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HTTPS</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -1,29 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/Users/noplay/code/gns3/gns3-gui/gns3/ui/edit_compute_dialog.ui'
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/edit_compute_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.8
|
||||
# Created by: PyQt5 UI code generator 5.15.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_EditComputeDialog(object):
|
||||
|
||||
def setupUi(self, EditComputeDialog):
|
||||
EditComputeDialog.setObjectName("EditComputeDialog")
|
||||
EditComputeDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||
EditComputeDialog.resize(579, 374)
|
||||
EditComputeDialog.resize(585, 353)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(EditComputeDialog)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.groupBox = QtWidgets.QGroupBox(EditComputeDialog)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.uiServerPortLabel = QtWidgets.QLabel(self.groupBox)
|
||||
self.uiServerPortLabel.setObjectName("uiServerPortLabel")
|
||||
self.gridLayout.addWidget(self.uiServerPortLabel, 3, 0, 1, 1)
|
||||
self.uiServerNameLineEdit = QtWidgets.QLineEdit(self.groupBox)
|
||||
self.uiServerNameLineEdit.setObjectName("uiServerNameLineEdit")
|
||||
self.gridLayout.addWidget(self.uiServerNameLineEdit, 0, 1, 1, 1)
|
||||
self.uiServerHostLineEdit = QtWidgets.QLineEdit(self.groupBox)
|
||||
self.uiServerHostLineEdit.setObjectName("uiServerHostLineEdit")
|
||||
self.gridLayout.addWidget(self.uiServerHostLineEdit, 2, 1, 1, 2)
|
||||
self.uiServerHostLabel = QtWidgets.QLabel(self.groupBox)
|
||||
self.uiServerHostLabel.setObjectName("uiServerHostLabel")
|
||||
self.gridLayout.addWidget(self.uiServerHostLabel, 2, 0, 1, 1)
|
||||
self.uiServerPortSpinBox = QtWidgets.QSpinBox(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@@ -34,19 +44,18 @@ class Ui_EditComputeDialog(object):
|
||||
self.uiServerPortSpinBox.setMaximum(65535)
|
||||
self.uiServerPortSpinBox.setProperty("value", 3080)
|
||||
self.uiServerPortSpinBox.setObjectName("uiServerPortSpinBox")
|
||||
self.gridLayout.addWidget(self.uiServerPortSpinBox, 2, 1, 1, 2)
|
||||
self.gridLayout.addWidget(self.uiServerPortSpinBox, 3, 1, 1, 2)
|
||||
self.label = QtWidgets.QLabel(self.groupBox)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
|
||||
self.uiServerHostLineEdit = QtWidgets.QLineEdit(self.groupBox)
|
||||
self.uiServerHostLineEdit.setObjectName("uiServerHostLineEdit")
|
||||
self.gridLayout.addWidget(self.uiServerHostLineEdit, 1, 1, 1, 2)
|
||||
self.uiServerHostLabel = QtWidgets.QLabel(self.groupBox)
|
||||
self.uiServerHostLabel.setObjectName("uiServerHostLabel")
|
||||
self.gridLayout.addWidget(self.uiServerHostLabel, 1, 0, 1, 1)
|
||||
self.uiServerPortLabel = QtWidgets.QLabel(self.groupBox)
|
||||
self.uiServerPortLabel.setObjectName("uiServerPortLabel")
|
||||
self.gridLayout.addWidget(self.uiServerPortLabel, 2, 0, 1, 1)
|
||||
self.uiServerProtocolLabel = QtWidgets.QLabel(self.groupBox)
|
||||
self.uiServerProtocolLabel.setObjectName("uiServerProtocolLabel")
|
||||
self.gridLayout.addWidget(self.uiServerProtocolLabel, 1, 0, 1, 1)
|
||||
self.uiServerProtocolComboBox = QtWidgets.QComboBox(self.groupBox)
|
||||
self.uiServerProtocolComboBox.setObjectName("uiServerProtocolComboBox")
|
||||
self.uiServerProtocolComboBox.addItem("")
|
||||
self.uiServerProtocolComboBox.addItem("")
|
||||
self.gridLayout.addWidget(self.uiServerProtocolComboBox, 1, 1, 1, 1)
|
||||
self.verticalLayout.addWidget(self.groupBox)
|
||||
self.uiEnableAuthenticationCheckBox = QtWidgets.QGroupBox(EditComputeDialog)
|
||||
self.uiEnableAuthenticationCheckBox.setCheckable(True)
|
||||
@@ -67,7 +76,7 @@ class Ui_EditComputeDialog(object):
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.uiServerPasswordLabel)
|
||||
self.uiServerPasswordLineEdit = QtWidgets.QLineEdit(self.uiEnableAuthenticationCheckBox)
|
||||
self.uiServerPasswordLineEdit.setEnabled(True)
|
||||
self.uiServerPasswordLineEdit.setInputMethodHints(QtCore.Qt.ImhHiddenText | QtCore.Qt.ImhNoAutoUppercase | QtCore.Qt.ImhNoPredictiveText | QtCore.Qt.ImhSensitiveData)
|
||||
self.uiServerPasswordLineEdit.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText|QtCore.Qt.ImhSensitiveData)
|
||||
self.uiServerPasswordLineEdit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||
self.uiServerPasswordLineEdit.setObjectName("uiServerPasswordLineEdit")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.uiServerPasswordLineEdit)
|
||||
@@ -80,7 +89,7 @@ class Ui_EditComputeDialog(object):
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(EditComputeDialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
||||
@@ -98,10 +107,13 @@ class Ui_EditComputeDialog(object):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
EditComputeDialog.setWindowTitle(_translate("EditComputeDialog", "Edit server settings"))
|
||||
self.groupBox.setTitle(_translate("EditComputeDialog", "Server settings"))
|
||||
self.label.setText(_translate("EditComputeDialog", "Name:"))
|
||||
self.uiServerPortLabel.setText(_translate("EditComputeDialog", "Port:"))
|
||||
self.uiServerHostLineEdit.setText(_translate("EditComputeDialog", "192.168.56.101"))
|
||||
self.uiServerHostLabel.setText(_translate("EditComputeDialog", "Host:"))
|
||||
self.uiServerPortLabel.setText(_translate("EditComputeDialog", "Port:"))
|
||||
self.label.setText(_translate("EditComputeDialog", "Name:"))
|
||||
self.uiServerProtocolLabel.setText(_translate("EditComputeDialog", "Protocol:"))
|
||||
self.uiServerProtocolComboBox.setItemText(0, _translate("EditComputeDialog", "HTTP"))
|
||||
self.uiServerProtocolComboBox.setItemText(1, _translate("EditComputeDialog", "HTTPS"))
|
||||
self.uiEnableAuthenticationCheckBox.setTitle(_translate("EditComputeDialog", "Enable authentication"))
|
||||
self.uiServerUserLabel.setText(_translate("EditComputeDialog", "User:"))
|
||||
self.uiServerPasswordLabel.setText(_translate("EditComputeDialog", "Password:"))
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1273</width>
|
||||
<height>1097</height>
|
||||
<width>681</width>
|
||||
<height>843</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -295,24 +295,14 @@
|
||||
<string>Remote main server</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Host:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerHostLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QSpinBox" name="uiRemoteMainServerPortSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
@@ -331,44 +321,75 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Auth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QCheckBox" name="uiRemoteMainServerAuthCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerUserLineEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>User:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerUserLineEdit"/>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerPasswordLineEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerHostLineEdit"/>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="uiRemoteMainServerPasswordLineEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="uiRemoteMainServerAuthCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uiRemoteMainServerProtocolLabel">
|
||||
<property name="text">
|
||||
<string>Protocol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="uiRemoteMainServerProtocolComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HTTP</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HTTPS</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -404,7 +425,16 @@
|
||||
<string>Remote servers</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
|
||||
@@ -2,16 +2,19 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/server_preferences_page.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.9
|
||||
# Created by: PyQt5 UI code generator 5.15.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_ServerPreferencesPageWidget(object):
|
||||
def setupUi(self, ServerPreferencesPageWidget):
|
||||
ServerPreferencesPageWidget.setObjectName("ServerPreferencesPageWidget")
|
||||
ServerPreferencesPageWidget.resize(1273, 1097)
|
||||
ServerPreferencesPageWidget.resize(681, 843)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@@ -149,13 +152,7 @@ class Ui_ServerPreferencesPageWidget(object):
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.label_2 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_4.addWidget(self.label_2, 0, 0, 1, 1)
|
||||
self.uiRemoteMainServerHostLineEdit = QtWidgets.QLineEdit(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerHostLineEdit.setObjectName("uiRemoteMainServerHostLineEdit")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerHostLineEdit, 0, 1, 1, 2)
|
||||
self.label_3 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_4.addWidget(self.label_3, 1, 0, 1, 1)
|
||||
self.gridLayout_4.addWidget(self.label_2, 1, 0, 1, 1)
|
||||
self.uiRemoteMainServerPortSpinBox = QtWidgets.QSpinBox(self.uiRemoteMainServerGroupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@@ -165,27 +162,41 @@ class Ui_ServerPreferencesPageWidget(object):
|
||||
self.uiRemoteMainServerPortSpinBox.setMaximum(65535)
|
||||
self.uiRemoteMainServerPortSpinBox.setProperty("value", 3080)
|
||||
self.uiRemoteMainServerPortSpinBox.setObjectName("uiRemoteMainServerPortSpinBox")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerPortSpinBox, 1, 1, 1, 2)
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerPortSpinBox, 2, 1, 1, 2)
|
||||
self.label = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout_4.addWidget(self.label, 2, 0, 1, 1)
|
||||
self.uiRemoteMainServerAuthCheckBox = QtWidgets.QCheckBox(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerAuthCheckBox.setText("")
|
||||
self.uiRemoteMainServerAuthCheckBox.setObjectName("uiRemoteMainServerAuthCheckBox")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerAuthCheckBox, 2, 2, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_4.addWidget(self.label_4, 3, 0, 1, 1)
|
||||
self.gridLayout_4.addWidget(self.label, 3, 0, 1, 1)
|
||||
self.uiRemoteMainServerUserLineEdit = QtWidgets.QLineEdit(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerUserLineEdit.setObjectName("uiRemoteMainServerUserLineEdit")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerUserLineEdit, 3, 2, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout_4.addWidget(self.label_5, 4, 0, 1, 2)
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerUserLineEdit, 4, 2, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_4.addWidget(self.label_4, 4, 0, 1, 1)
|
||||
self.uiRemoteMainServerPasswordLineEdit = QtWidgets.QLineEdit(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerPasswordLineEdit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||
self.uiRemoteMainServerPasswordLineEdit.setObjectName("uiRemoteMainServerPasswordLineEdit")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerPasswordLineEdit, 4, 2, 1, 1)
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerPasswordLineEdit, 5, 2, 1, 1)
|
||||
self.label_3 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_4.addWidget(self.label_3, 2, 0, 1, 1)
|
||||
self.uiRemoteMainServerHostLineEdit = QtWidgets.QLineEdit(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerHostLineEdit.setObjectName("uiRemoteMainServerHostLineEdit")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerHostLineEdit, 1, 1, 1, 2)
|
||||
self.label_5 = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout_4.addWidget(self.label_5, 5, 0, 1, 2)
|
||||
self.uiRemoteMainServerAuthCheckBox = QtWidgets.QCheckBox(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerAuthCheckBox.setText("")
|
||||
self.uiRemoteMainServerAuthCheckBox.setObjectName("uiRemoteMainServerAuthCheckBox")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerAuthCheckBox, 3, 2, 1, 1)
|
||||
self.uiRemoteMainServerProtocolLabel = QtWidgets.QLabel(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerProtocolLabel.setObjectName("uiRemoteMainServerProtocolLabel")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerProtocolLabel, 0, 0, 1, 1)
|
||||
self.uiRemoteMainServerProtocolComboBox = QtWidgets.QComboBox(self.uiRemoteMainServerGroupBox)
|
||||
self.uiRemoteMainServerProtocolComboBox.setObjectName("uiRemoteMainServerProtocolComboBox")
|
||||
self.uiRemoteMainServerProtocolComboBox.addItem("")
|
||||
self.uiRemoteMainServerProtocolComboBox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.uiRemoteMainServerProtocolComboBox, 0, 1, 1, 2)
|
||||
self.verticalLayout.addWidget(self.uiRemoteMainServerGroupBox)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem2)
|
||||
@@ -290,11 +301,14 @@ class Ui_ServerPreferencesPageWidget(object):
|
||||
self.uiUDPPortRangeLabel.setText(_translate("ServerPreferencesPageWidget", "to"))
|
||||
self.uiRemoteMainServerGroupBox.setTitle(_translate("ServerPreferencesPageWidget", "Remote main server"))
|
||||
self.label_2.setText(_translate("ServerPreferencesPageWidget", "Host:"))
|
||||
self.label_3.setText(_translate("ServerPreferencesPageWidget", "Port:"))
|
||||
self.uiRemoteMainServerPortSpinBox.setSuffix(_translate("ServerPreferencesPageWidget", " TCP"))
|
||||
self.label.setText(_translate("ServerPreferencesPageWidget", "Auth:"))
|
||||
self.label_4.setText(_translate("ServerPreferencesPageWidget", "User:"))
|
||||
self.label_3.setText(_translate("ServerPreferencesPageWidget", "Port:"))
|
||||
self.label_5.setText(_translate("ServerPreferencesPageWidget", "Password:"))
|
||||
self.uiRemoteMainServerProtocolLabel.setText(_translate("ServerPreferencesPageWidget", "Protocol:"))
|
||||
self.uiRemoteMainServerProtocolComboBox.setItemText(0, _translate("ServerPreferencesPageWidget", "HTTP"))
|
||||
self.uiRemoteMainServerProtocolComboBox.setItemText(1, _translate("ServerPreferencesPageWidget", "HTTPS"))
|
||||
self.uiServerPreferenceTabWidget.setTabText(self.uiServerPreferenceTabWidget.indexOf(self.uiLocalTabWidget), _translate("ServerPreferencesPageWidget", "Main server"))
|
||||
self.uiRemoteServersTreeWidget.headerItem().setText(0, _translate("ServerPreferencesPageWidget", "Name"))
|
||||
self.uiRemoteServersTreeWidget.headerItem().setText(4, _translate("ServerPreferencesPageWidget", "User"))
|
||||
@@ -304,4 +318,3 @@ class Ui_ServerPreferencesPageWidget(object):
|
||||
self.label_7.setText(_translate("ServerPreferencesPageWidget", "Note: Changes are not visible in other part of the settings or application until you apply them."))
|
||||
self.uiServerPreferenceTabWidget.setTabText(self.uiServerPreferenceTabWidget.indexOf(self.uiRemoteTabWidget), _translate("ServerPreferencesPageWidget", "Remote servers"))
|
||||
self.uiRestoreDefaultsPushButton.setText(_translate("ServerPreferencesPageWidget", "Restore defaults"))
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.16"
|
||||
__version_info__ = (2, 2, 16, 0)
|
||||
__version__ = "2.2.18"
|
||||
__version_info__ = (2, 2, 18, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1"
|
||||
id="svg7631" xmlns:cc="http://creativecommons.org/ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" sodipodi:docname="camera-photo.svg" sodipodi:version="0.32" inkscape:version="0.48.3.1 r9886" inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 48 48"
|
||||
enable-background="new 0 0 48 48" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#231F20" d="M42.8,38.4l-7.4-9c1.6-2.6,2.5-5.6,2.5-8.8c0-9.3-7.5-16.8-16.8-16.8S4.3,11.3,4.3,20.6
|
||||
c0,9.3,7.5,16.8,16.8,16.8c3.7,0,7.1-1.2,9.9-3.2l6.8,8.3c0.6,0.7,1.5,0.8,2.2,0.2l2.5-2.1C43.2,40.1,43.3,39.1,42.8,38.4z
|
||||
M9,20.6c0-6.7,5.4-12.1,12.1-12.1s12.1,5.4,12.1,12.1c0,6.7-5.4,12.1-12.1,12.1S9,27.3,9,20.6z"/>
|
||||
<polygon fill="#231F20" points="27.6,19 23.2,19 23.2,14.4 19,14.4 19,19 14.5,19 14.5,23.2 19,23.2 19,27.8 23.2,27.8 23.2,23.2
|
||||
27.6,23.2 "/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#CDCDCD" d="M42.6,40l-7.4-9c1.6-2.6,2.5-5.6,2.5-8.8C37.7,13,30.2,5.4,21,5.4S4.2,13,4.2,22.2C4.2,31.5,11.7,39,21,39
|
||||
c3.7,0,7.1-1.2,9.9-3.2l6.8,8.3c0.6,0.7,1.5,0.8,2.2,0.2l2.5-2.1C43.1,41.7,43.2,40.7,42.6,40z M8.9,22.2
|
||||
c0-6.7,5.4-12.1,12.1-12.1S33,15.6,33,22.2c0,6.7-5.4,12.1-12.1,12.1S8.9,28.9,8.9,22.2z"/>
|
||||
<polygon fill="#CDCDCD" points="27.8,20.6 23.2,20.6 23.2,16 18.9,16 18.9,20.6 14.4,20.6 14.4,24.9 18.9,24.9 18.9,29.4
|
||||
23.2,29.4 23.2,24.9 27.8,24.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
Reference in New Issue
Block a user