mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-17 00:46:01 +03:00
240 lines
8.9 KiB
Python
240 lines
8.9 KiB
Python
# -*- 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/>.
|
|
|
|
"""
|
|
Dialog to load module and built-in preference pages.
|
|
"""
|
|
|
|
from ..qt import QtGui, 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.packet_capture_preferences_page import PacketCapturePreferencesPage
|
|
from ..pages.gns3_vm_preferences_page import GNS3VMPreferencesPage
|
|
from ..modules import MODULES
|
|
|
|
import logging
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog):
|
|
|
|
"""
|
|
Preferences dialog implementation.
|
|
|
|
:param parent: parent widget
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
|
|
super().__init__(parent)
|
|
|
|
self.setupUi(self)
|
|
self._modified_pages = set()
|
|
|
|
# We adapt the max size to the screen resolution
|
|
# We need to manually do that otherwise on small screen the windows
|
|
# could be bigger than the screen instead of displaying scrollbars
|
|
geometry = QtGui.QGuiApplication.primaryScreen().geometry()
|
|
height = geometry.height() - 100
|
|
width = geometry.width() - 100
|
|
|
|
# 980 is the default width
|
|
if self.width() > width:
|
|
self.resize(width, self.height())
|
|
# 680 is the default height
|
|
if self.height() > height:
|
|
self.resize(self.width(), height)
|
|
|
|
self.uiTreeWidget.currentItemChanged.connect(self._showPreferencesPageSlot)
|
|
self._applyButton = self.uiButtonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Apply)
|
|
self._applyButton.clicked.connect(self._applyPreferences)
|
|
self._applyButton.setEnabled(False)
|
|
self._applyButton.setStyleSheet("QPushButton:disabled {color: gray}")
|
|
self._items = []
|
|
self._loadPreferencePages()
|
|
|
|
# select the first available page
|
|
self.uiTreeWidget.setCurrentItem(self._items[0])
|
|
|
|
# set the maximum width based on the content of column 0
|
|
self.uiTreeWidget.setMaximumWidth(self.uiTreeWidget.sizeHintForColumn(0) + 10)
|
|
|
|
# Something has changed?
|
|
self._modified_pages = set()
|
|
|
|
def _loadPreferencePages(self):
|
|
"""
|
|
Loads all preference pages (built-ins and from modules).
|
|
"""
|
|
|
|
# load built-in preference pages
|
|
pages = [
|
|
GeneralPreferencesPage,
|
|
ServerPreferencesPage,
|
|
GNS3VMPreferencesPage,
|
|
PacketCapturePreferencesPage,
|
|
]
|
|
|
|
for page in pages:
|
|
preferences_page = page(self)
|
|
preferences_page.loadPreferences()
|
|
name = preferences_page.windowTitle()
|
|
item = QtWidgets.QTreeWidgetItem(self.uiTreeWidget)
|
|
item.setText(0, name)
|
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, preferences_page)
|
|
self.uiStackedWidget.addWidget(preferences_page)
|
|
self._items.append(item)
|
|
self._watchForChanges(preferences_page)
|
|
|
|
# load module preference pages
|
|
for module in MODULES:
|
|
preference_pages = module.preferencePages()
|
|
parent = self.uiTreeWidget
|
|
for cls in preference_pages:
|
|
preferences_page = cls()
|
|
preferences_page.setParent(self)
|
|
preferences_page.loadPreferences()
|
|
name = preferences_page.windowTitle()
|
|
item = QtWidgets.QTreeWidgetItem(parent)
|
|
item.setText(0, name)
|
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, preferences_page)
|
|
self.uiStackedWidget.addWidget(preferences_page)
|
|
self._items.append(item)
|
|
if cls is preference_pages[0]:
|
|
parent = item
|
|
self._watchForChanges(preferences_page)
|
|
|
|
# expand all items by default
|
|
self.uiTreeWidget.expandAll()
|
|
|
|
def _watchForChanges(self, preferences_page):
|
|
"""
|
|
Connect all the widget of a page to check if something has change
|
|
"""
|
|
|
|
# Class name, changed signal
|
|
widget_to_watch = {
|
|
QtWidgets.QLineEdit: "textChanged",
|
|
QtWidgets.QPlainTextEdit: "textChanged",
|
|
# QtWidgets.QTreeWidget: "itemChanged",
|
|
QtWidgets.QTreeWidget: "itemDoubleClicked",
|
|
QtWidgets.QComboBox: "currentIndexChanged",
|
|
QtWidgets.QSpinBox: "valueChanged",
|
|
QtWidgets.QAbstractButton: "pressed"
|
|
}
|
|
|
|
for widget, signal in widget_to_watch.items():
|
|
for children in preferences_page.findChildren(widget):
|
|
getattr(children, signal).connect(self._preferenceChangeSlot)
|
|
|
|
def _preferenceChangeSlot(self, *args):
|
|
"""
|
|
Called when something change in the preference dialog
|
|
"""
|
|
|
|
# Found the page with the change
|
|
widget = sender = self.sender()
|
|
while widget.parent() != self.uiStackedWidget:
|
|
widget = widget.parent()
|
|
|
|
if self.addModifiedPage(widget):
|
|
log.debug("%s value has changed", sender.objectName())
|
|
|
|
def addModifiedPage(self, widget):
|
|
"""
|
|
:returns: True is the page is initialized and element added
|
|
"""
|
|
# The widget can trigger signal before the end of init due to async api call
|
|
if not hasattr(widget, 'pageInitialized') or widget.pageInitialized():
|
|
self._applyButton.setEnabled(True)
|
|
self._modified_pages.add(widget)
|
|
return True
|
|
return False
|
|
|
|
def _showPreferencesPageSlot(self, current, previous):
|
|
"""
|
|
Shows a preference page in the current dialog.
|
|
|
|
:param current: current preference page widget
|
|
:param previous: ignored
|
|
"""
|
|
|
|
if current is None:
|
|
current = previous
|
|
|
|
preferences_page = current.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
|
accessible_name = preferences_page.accessibleName()
|
|
if accessible_name:
|
|
self.uiTitleLabel.setText(accessible_name)
|
|
else:
|
|
name = preferences_page.windowTitle()
|
|
self.uiTitleLabel.setText("{} preferences".format(name))
|
|
index = self.uiStackedWidget.indexOf(preferences_page)
|
|
widget = self.uiStackedWidget.widget(index)
|
|
#self.uiStackedWidget.setMinimumSize(widget.size()) # FIXME: this seems to not work on Windows and OSX
|
|
#self.uiStackedWidget.resize(widget.size())
|
|
self.uiStackedWidget.setCurrentIndex(index)
|
|
|
|
for index in range(0, self.uiStackedWidget.count()):
|
|
page = self.uiStackedWidget.widget(index)
|
|
if self.uiStackedWidget.currentIndex() == index:
|
|
page.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
|
|
else:
|
|
page.setSizePolicy(QtWidgets.QSizePolicy.Policy.Ignored, QtWidgets.QSizePolicy.Policy.Ignored)
|
|
|
|
def _applyPreferences(self):
|
|
"""
|
|
Saves all the preferences.
|
|
"""
|
|
|
|
success = True
|
|
for preferences_page in list(self._modified_pages):
|
|
ok = preferences_page.savePreferences()
|
|
# if page.savePreferences() returns None, assume success
|
|
if ok is not None and not ok:
|
|
success = False
|
|
if success:
|
|
self._applyButton.setEnabled(False)
|
|
self._modified_pages = set()
|
|
return success
|
|
|
|
def reject(self):
|
|
"""
|
|
Closes this dialog.
|
|
"""
|
|
|
|
if len(self._modified_pages) > 0:
|
|
# Get the title of pages with modifications
|
|
pages_title = ', '.join([page.windowTitle() for page in self._modified_pages])
|
|
reply = QtWidgets.QMessageBox.warning(self,
|
|
"Preferences",
|
|
"You have unsaved preferences in {}.\n\nContinue without saving?".format(pages_title),
|
|
QtWidgets.QMessageBox.StandardButton.Yes,
|
|
QtWidgets.QMessageBox.StandardButton.No)
|
|
if reply == QtWidgets.QMessageBox.StandardButton.No:
|
|
return
|
|
QtWidgets.QDialog.reject(self)
|
|
|
|
def accept(self):
|
|
"""
|
|
Saves the preferences and closes this dialog.
|
|
"""
|
|
|
|
if self._applyPreferences():
|
|
QtWidgets.QDialog.accept(self)
|