|
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2011-2013, Marten de Vries
# Copyright 2011, Milan Boers
#
# This file is part of OpenTeacher.
#
# OpenTeacher 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.
#
# OpenTeacher 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 OpenTeacher. If not, see <http://www.gnu.org/licenses/>.
import weakref
import copy
import platform
def installQtClasses():
global CategoryTab, SettingsDialog
class CategoryTab(QtWidgets.QWidget):
"""A category tab. It consists out of subcategory group boxes,
which contain the actual settings.
"""
def __init__(self, byKey, widgets, name, inCategory, *args, **kwargs):
super().__init__(*args, **kwargs)
self.byKey = byKey
self._widgets = widgets
self.setWindowTitle(name)
vbox = QtWidgets.QVBoxLayout()
categories = self.byKey("subcategory", inCategory)
for name in sorted(categories.keys()):
w = self.createSubcategoryGroupBox(name, categories[name])
vbox.addWidget(w)
vbox.addStretch()
self.setLayout(vbox)
def createSubcategoryGroupBox(self, name, inSubcategory):
groupBox = QtWidgets.QGroupBox(name)
groupBoxLayout = QtWidgets.QFormLayout()
for setting in sorted(inSubcategory, key=lambda s: s["name"]):
try:
createWidget = self._widgets[setting["type"]]
except KeyError:
continue
try:
groupBoxLayout.addRow(
setting["name"],
createWidget(setting)
)
except KeyError:
continue
groupBox.setLayout(groupBoxLayout)
return groupBox
def retranslate(self):
pass
class SettingsDialog(QtWidgets.QTabWidget):
"""The actual settings dialog. It consists of category tabs."""
def __init__(self, byKey, settings, widgets, *args, **kwargs):
super().__init__(*args, **kwargs)
self.settings = settings
self.byKey = byKey
self.widgets = widgets
#Setup widget
self.setTabPosition(QtWidgets.QTabWidget.South)
89 if platform.system() != "Darwin":
#Document mode, south tabs & a corner button gives
#misdrawings in Mac OS X.
self.setDocumentMode(True)
self.advancedButton = QtWidgets.QPushButton()
self.advancedButton.clicked.connect(self.advanced)
self.simpleButton = QtWidgets.QPushButton()
self.simpleButton.clicked.connect(self.simple)
# Go to simple mode
self.simple()
#Used to track if the widget needs to be updated because of
#retranslation. We can't do that directly, because then the
#language box in which the language is selected is also updated
#immediately, rendering it unusable. Instead, we do it when the
#widget is hidden (see the eventFilter method.)
self._updateNeeded = False
#so the focus can be tracked
self.installEventFilter(self)
def retranslate(self):
self.setWindowTitle(_("Settings"))
self.simpleButton.setText(_("Simple mode"))
self.advancedButton.setText(_("Advanced mode"))
self._updateNeeded = True
def createCategoryTab(self, *args, **kwargs):
tab = CategoryTab(self.byKey, *args, **kwargs)
self.addTab(tab, tab.windowTitle())
def eventFilter(self, object, event, *args, **kwargs):
120 if event.type() == QtCore.QEvent.Hide and self._updateNeeded:
tabIndex = self.currentIndex()
self.update()
self._updateNeeded = False
#Reset the index
self.setCurrentIndex(tabIndex)
return True
else:
return False
def update(self):
# Copy settings
settings = copy.copy(self.settings)
137 if self.simpleMode:
for setting in self.settings:
if "advanced" in setting and setting["advanced"]:
settings.remove(setting)
self.clear()
categories = self.byKey("category", settings)
for name in sorted(categories.keys()):
self.createCategoryTab(self.widgets, name, categories[name])
def advanced(self):
self.setCornerWidget(
self.simpleButton,
QtCore.Qt.BottomRightCorner
)
self.simpleMode = False
self.update()
self.simpleButton.show()
def simple(self):
self.setCornerWidget(
self.advancedButton,
QtCore.Qt.BottomRightCorner
)
self.simpleMode = True
self.update()
self.advancedButton.show()
class SettingsDialogModule:
"""The settings dialog, which shows all registered settings in the
UI.
"""
def __init__(self, moduleManager, *args, **kwargs):
super().__init__(*args, **kwargs)
self._mm = moduleManager
self.type = "settingsDialog"
self.uses = (
self._mm.mods(type="translator"),
)
self.requires = (
self._mm.mods(type="ui"),
self._mm.mods(type="settings"),
self._mm.mods(type="settingsWidgets"),
self._mm.mods(type="settingsFilterer"),
)
self.filesWithTranslations = ("settings.py",)
def enable(self):
global QtCore, QtWidgets
try:
from PyQt5 import QtCore, QtWidgets
except ImportError:
#remain inactive
return
installQtClasses()
self._modules = set(self._mm.mods(type="modules")).pop()
self._uiModule = self._modules.default("active", type="ui")
self._settings = self._modules.default(type="settings")
self._settingsWidgets = self._modules.default("active", type="settingsWidgets")
self._settingsFilterer = self._modules.default("active", type="settingsFilterer")
self._activeDialogs = set()
#install translator
try:
translator = self._modules.default("active", type="translator")
except IndexError:
pass
else:
translator.languageChanged.handle(self._retranslate)
#so text of settings is also updated.
translator.languageChangeDone.handle(self._retranslate)
self._retranslate()
self.active = True
def _retranslate(self):
#Translations
global _
global ngettext
try:
translator = self._modules.default("active", type="translator")
except IndexError:
exit _, ngettext = str, lambda a, b, n: a if n == 1 else b
else:
_, ngettext = translator.gettextFunctions(
self._mm.resourcePath("translations")
)
for ref in self._activeDialogs:
dialog = ref()
230 if dialog is not None:
dialog.retranslate()
dialog.tab.title = dialog.windowTitle()
def disable(self):
self.active = False
del self._modules
del self._uiModule
del self._settings
del self._settingsWidgets
del self._settingsFilterer
del self._activeDialogs
def show(self):
"""Shows the settings dialog. Normally there's no need to call
this manually, but it's possible.
"""
dialog = SettingsDialog(
self._settingsFilterer.byKey,
self._settings.registeredSettings,
self._settingsWidgets.widgets
)
self._activeDialogs.add(weakref.ref(dialog))
self.tab = self._uiModule.addCustomTab(dialog)
dialog.tab = self.tab
self.tab.closeRequested.handle(self.tab.close)
self._retranslate()
def init(moduleManager):
return SettingsDialogModule(moduleManager)
|