eric6/Preferences/ConfigurationDialog.py

branch
maintenance
changeset 6989
8b8cadf8d7e9
parent 6826
c6dda2cbe081
parent 6942
2602857055c5
child 7214
f434af227a41
equal deleted inserted replaced
6938:7926553b7509 6989:8b8cadf8d7e9
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog for the configuration of eric6.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13 import types
14
15 from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt, QMetaObject, \
16 QRect
17 from PyQt5.QtGui import QPixmap
18 from PyQt5.QtWidgets import QSizePolicy, QSpacerItem, QWidget, QTreeWidget, \
19 QStackedWidget, QDialog, QSplitter, QScrollArea, QApplication, \
20 QDialogButtonBox, QFrame, QVBoxLayout, QTreeWidgetItem, QLabel
21
22 from E5Gui.E5Application import e5App
23 from E5Gui.E5LineEdit import E5ClearableLineEdit
24 from E5Gui import E5MessageBox
25 from E5Gui.E5MainWindow import E5MainWindow
26
27 from Globals import isMacPlatform, qVersionTuple, getWebBrowserSupport
28
29 import Preferences
30
31 import UI.PixmapCache
32
33 from eric6config import getConfig
34
35
36 class ConfigurationPageItem(QTreeWidgetItem):
37 """
38 Class implementing a QTreeWidgetItem holding the configuration page data.
39 """
40 def __init__(self, parent, text, pageName, iconFile):
41 """
42 Constructor
43
44 @param parent parent widget of the item (QTreeWidget or
45 QTreeWidgetItem)
46 @param text text to be displayed (string)
47 @param pageName name of the configuration page (string)
48 @param iconFile file name of the icon to be shown (string)
49 """
50 super(ConfigurationPageItem, self).__init__(parent, [text])
51 self.setIcon(0, UI.PixmapCache.getIcon(iconFile))
52
53 self.__pageName = pageName
54
55 def getPageName(self):
56 """
57 Public method to get the name of the associated configuration page.
58
59 @return name of the configuration page (string)
60 """
61 return self.__pageName
62
63
64 class ConfigurationWidget(QWidget):
65 """
66 Class implementing a dialog for the configuration of eric6.
67
68 @signal preferencesChanged() emitted after settings have been changed
69 @signal masterPasswordChanged(str, str) emitted after the master
70 password has been changed with the old and the new password
71 @signal accepted() emitted to indicate acceptance of the changes
72 @signal rejected() emitted to indicate rejection of the changes
73 """
74 preferencesChanged = pyqtSignal()
75 masterPasswordChanged = pyqtSignal(str, str)
76 accepted = pyqtSignal()
77 rejected = pyqtSignal()
78
79 DefaultMode = 0
80 HelpBrowserMode = 1
81 TrayStarterMode = 2
82 HexEditorMode = 3
83 WebBrowserMode = 4
84
85 def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode,
86 expandedEntries=None):
87 """
88 Constructor
89
90 @param parent The parent widget of this dialog. (QWidget)
91 @keyparam fromEric flag indicating a dialog generation from within the
92 eric6 ide (boolean)
93 @keyparam displayMode mode of the configuration dialog
94 (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode,
95 WebBrowserMode)
96 @exception RuntimeError raised to indicate an invalid dialog mode
97 @keyparam expandedEntries list of entries to be shown expanded
98 (list of strings)
99 """
100 assert displayMode in (
101 ConfigurationWidget.DefaultMode,
102 ConfigurationWidget.HelpBrowserMode,
103 ConfigurationWidget.TrayStarterMode,
104 ConfigurationWidget.HexEditorMode,
105 ConfigurationWidget.WebBrowserMode,
106 )
107
108 super(ConfigurationWidget, self).__init__(parent)
109 self.fromEric = fromEric
110 self.displayMode = displayMode
111 self.__webEngine = getWebBrowserSupport() == "QtWebEngine"
112 expandedEntries = [] if expandedEntries is None else expandedEntries[:]
113
114 self.__setupUi()
115
116 self.itmDict = {}
117
118 if not fromEric:
119 from PluginManager.PluginManager import PluginManager
120 try:
121 self.pluginManager = e5App().getObject("PluginManager")
122 except KeyError:
123 self.pluginManager = PluginManager(self)
124 e5App().registerObject("PluginManager", self.pluginManager)
125
126 from VirtualEnv.VirtualenvManager import VirtualenvManager
127 try:
128 self.virtualenvManager = e5App().getObject("VirtualEnvManager")
129 except KeyError:
130 self.virtualenvManager = VirtualenvManager(self)
131 e5App().registerObject("VirtualEnvManager",
132 self.virtualenvManager)
133
134 if displayMode == ConfigurationWidget.DefaultMode:
135 self.configItems = {
136 # key : [display string, pixmap name, dialog module name or
137 # page creation function, parent key,
138 # reference to configuration page (must always be last)]
139 # The dialog module must have the module function 'create' to
140 # create the configuration page. This must have the method
141 # 'save' to save the settings.
142 "applicationPage":
143 [self.tr("Application"), "preferences-application.png",
144 "ApplicationPage", None, None],
145 "condaPage":
146 [self.tr("Conda"), "miniconda.png",
147 "CondaPage", None, None],
148 "cooperationPage":
149 [self.tr("Cooperation"), "preferences-cooperation.png",
150 "CooperationPage", None, None],
151 "corbaPage":
152 [self.tr("CORBA"), "preferences-orbit.png",
153 "CorbaPage", None, None],
154 "diffPage":
155 [self.tr("Diff"), "diffFiles.png",
156 "DiffColoursPage", None, None],
157 "emailPage":
158 [self.tr("Email"), "preferences-mail_generic.png",
159 "EmailPage", None, None],
160 "graphicsPage":
161 [self.tr("Graphics"), "preferences-graphics.png",
162 "GraphicsPage", None, None],
163 "hexEditorPage":
164 [self.tr("Hex Editor"), "hexEditor.png",
165 "HexEditorPage", None, None],
166 "iconsPage":
167 [self.tr("Icons"), "preferences-icons.png",
168 "IconsPage", None, None],
169 "ircPage":
170 [self.tr("IRC"), "irc.png",
171 "IrcPage", None, None],
172 "logViewerPage":
173 [self.tr("Log-Viewer"), "preferences-logviewer.png",
174 "LogViewerPage", None, None],
175 "mimeTypesPage":
176 [self.tr("Mimetypes"), "preferences-mimetypes.png",
177 "MimeTypesPage", None, None],
178 "networkPage":
179 [self.tr("Network"), "preferences-network.png",
180 "NetworkPage", None, None],
181 "notificationsPage":
182 [self.tr("Notifications"),
183 "preferences-notifications.png",
184 "NotificationsPage", None, None],
185 "pipPage":
186 [self.tr("Python Package Management"), "pypi.png",
187 "PipPage", None, None],
188 "pluginManagerPage":
189 [self.tr("Plugin Manager"),
190 "preferences-pluginmanager.png",
191 "PluginManagerPage", None, None],
192 "printerPage":
193 [self.tr("Printer"), "preferences-printer.png",
194 "PrinterPage", None, None],
195 "protobufPage":
196 [self.tr("Protobuf"), "protobuf.png",
197 "ProtobufPage", None, None],
198 "pythonPage":
199 [self.tr("Python"), "preferences-python.png",
200 "PythonPage", None, None],
201 "qtPage":
202 [self.tr("Qt"), "preferences-qtlogo.png",
203 "QtPage", None, None],
204 "securityPage":
205 [self.tr("Security"), "preferences-security.png",
206 "SecurityPage", None, None],
207 "shellPage":
208 [self.tr("Shell"), "preferences-shell.png",
209 "ShellPage", None, None],
210 "tasksPage":
211 [self.tr("Tasks"), "task.png",
212 "TasksPage", None, None],
213 "templatesPage":
214 [self.tr("Templates"), "preferences-template.png",
215 "TemplatesPage", None, None],
216 "trayStarterPage":
217 [self.tr("Tray Starter"), "erict.png",
218 "TrayStarterPage", None, None],
219 "vcsPage":
220 [self.tr("Version Control Systems"),
221 "preferences-vcs.png",
222 "VcsPage", None, None],
223
224 "0debuggerPage":
225 [self.tr("Debugger"), "preferences-debugger.png",
226 None, None, None],
227 "debuggerGeneralPage":
228 [self.tr("General"), "preferences-debugger.png",
229 "DebuggerGeneralPage", "0debuggerPage", None],
230 "debuggerPython2Page":
231 [self.tr("Python2"), "preferences-pyDebugger.png",
232 "DebuggerPython2Page", "0debuggerPage", None],
233 "debuggerPython3Page":
234 [self.tr("Python3"), "preferences-pyDebugger.png",
235 "DebuggerPython3Page", "0debuggerPage", None],
236
237 "0editorPage":
238 [self.tr("Editor"), "preferences-editor.png",
239 None, None, None],
240 "editorAPIsPage":
241 [self.tr("APIs"), "preferences-api.png",
242 "EditorAPIsPage", "0editorPage", None],
243 "editorAutocompletionPage":
244 [self.tr("Autocompletion"),
245 "preferences-autocompletion.png",
246 "EditorAutocompletionPage", "0editorPage", None],
247 "editorAutocompletionQScintillaPage":
248 [self.tr("QScintilla"), "qscintilla.png",
249 "EditorAutocompletionQScintillaPage",
250 "editorAutocompletionPage", None],
251 "editorCalltipsPage":
252 [self.tr("Calltips"), "preferences-calltips.png",
253 "EditorCalltipsPage", "0editorPage", None],
254 "editorCalltipsQScintillaPage":
255 [self.tr("QScintilla"), "qscintilla.png",
256 "EditorCalltipsQScintillaPage", "editorCalltipsPage", None],
257 "editorDocViewerPage":
258 [self.tr("Documentation Viewer"), "codeDocuViewer.png",
259 "EditorDocViewerPage", "0editorPage", None],
260 "editorGeneralPage":
261 [self.tr("General"), "preferences-general.png",
262 "EditorGeneralPage", "0editorPage", None],
263 "editorFilePage":
264 [self.tr("Filehandling"),
265 "preferences-filehandling.png",
266 "EditorFilePage", "0editorPage", None],
267 "editorSearchPage":
268 [self.tr("Searching"), "preferences-search.png",
269 "EditorSearchPage", "0editorPage", None],
270 "editorSpellCheckingPage":
271 [self.tr("Spell checking"),
272 "preferences-spellchecking.png",
273 "EditorSpellCheckingPage", "0editorPage", None],
274 "editorStylesPage":
275 [self.tr("Style"), "preferences-styles.png",
276 "EditorStylesPage", "0editorPage", None],
277 "editorSyntaxPage":
278 [self.tr("Code Checkers"), "preferences-debugger.png",
279 "EditorSyntaxPage", "0editorPage", None],
280 "editorTypingPage":
281 [self.tr("Typing"), "preferences-typing.png",
282 "EditorTypingPage", "0editorPage", None],
283 "editorExportersPage":
284 [self.tr("Exporters"), "preferences-exporters.png",
285 "EditorExportersPage", "0editorPage", None],
286
287 "1editorLexerPage":
288 [self.tr("Highlighters"),
289 "preferences-highlighting-styles.png",
290 None, "0editorPage", None],
291 "editorHighlightersPage":
292 [self.tr("Filetype Associations"),
293 "preferences-highlighter-association.png",
294 "EditorHighlightersPage", "1editorLexerPage", None],
295 "editorHighlightingStylesPage":
296 [self.tr("Styles"),
297 "preferences-highlighting-styles.png",
298 "EditorHighlightingStylesPage", "1editorLexerPage", None],
299 "editorKeywordsPage":
300 [self.tr("Keywords"), "preferences-keywords.png",
301 "EditorKeywordsPage", "1editorLexerPage", None],
302 "editorPropertiesPage":
303 [self.tr("Properties"), "preferences-properties.png",
304 "EditorPropertiesPage", "1editorLexerPage", None],
305
306 "1editorMouseClickHandlers":
307 [self.tr("Mouse Click Handlers"),
308 "preferences-mouse-click-handler.png",
309 "EditorMouseClickHandlerPage", "0editorPage", None],
310
311 "0helpPage":
312 [self.tr("Help"), "preferences-help.png",
313 None, None, None],
314 "helpDocumentationPage":
315 [self.tr("Help Documentation"),
316 "preferences-helpdocumentation.png",
317 "HelpDocumentationPage", "0helpPage", None],
318 "helpViewersPage":
319 [self.tr("Help Viewers"),
320 "preferences-helpviewers.png",
321 "HelpViewersPage", "0helpPage", None],
322
323 "0projectPage":
324 [self.tr("Project"), "preferences-project.png",
325 None, None, None],
326 "projectBrowserPage":
327 [self.tr("Project Viewer"), "preferences-project.png",
328 "ProjectBrowserPage", "0projectPage", None],
329 "projectPage":
330 [self.tr("Project"), "preferences-project.png",
331 "ProjectPage", "0projectPage", None],
332 "multiProjectPage":
333 [self.tr("Multiproject"),
334 "preferences-multiproject.png",
335 "MultiProjectPage", "0projectPage", None],
336
337 "0interfacePage":
338 [self.tr("Interface"), "preferences-interface.png",
339 None, None, None],
340 "interfacePage":
341 [self.tr("Interface"), "preferences-interface.png",
342 "InterfacePage", "0interfacePage", None],
343 "viewmanagerPage":
344 [self.tr("Viewmanager"), "preferences-viewmanager.png",
345 "ViewmanagerPage", "0interfacePage", None],
346 }
347 if self.__webEngine:
348 self.configItems.update({
349 "0webBrowserPage":
350 [self.tr("Web Browser"), "ericWeb.png",
351 None, None, None],
352 "webBrowserAppearancePage":
353 [self.tr("Appearance"), "preferences-styles.png",
354 "WebBrowserAppearancePage", "0webBrowserPage", None],
355 "webBrowserPage":
356 [self.tr("eric6 Web Browser"), "ericWeb.png",
357 "WebBrowserPage", "0webBrowserPage", None],
358 "helpFlashCookieManagerPage":
359 [self.tr("Flash Cookie Manager"),
360 "flashCookie16.png",
361 "HelpFlashCookieManagerPage", "0webBrowserPage", None],
362 "webBrowserVirusTotalPage":
363 [self.tr("VirusTotal Interface"), "virustotal.png",
364 "WebBrowserVirusTotalPage", "0webBrowserPage", None],
365 })
366 if qVersionTuple() >= (5, 8, 0) and PYQT_VERSION >= 0x50800:
367 self.configItems.update({
368 "webBrowserSpellCheckingPage":
369 [self.tr("Spell checking"),
370 "preferences-spellchecking.png",
371 "WebBrowserSpellCheckingPage", "0webBrowserPage",
372 None],
373 })
374 else:
375 try:
376 from PyQt5 import QtWebKit # __IGNORE_WARNING__
377 self.configItems.update({
378 "0helpBrowserPage":
379 [self.tr("Web Browser"), "ericWeb.png",
380 None, None, None],
381 "helpAppearancePage":
382 [self.tr("Appearance"), "preferences-styles.png",
383 "HelpAppearancePage", "0helpBrowserPage", None],
384 "helpWebBrowserPage":
385 [self.tr("eric6 Web Browser"), "ericWeb.png",
386 "HelpWebBrowserPage", "0helpBrowserPage", None],
387 "helpFlashCookieManagerPage":
388 [self.tr("Flash Cookie Manager"),
389 "flashCookie16.png",
390 "HelpFlashCookieManagerPage", "0helpBrowserPage",
391 None],
392 "helpVirusTotalPage":
393 [self.tr("VirusTotal Interface"), "virustotal.png",
394 "HelpVirusTotalPage", "0helpBrowserPage", None],
395 })
396 except ImportError:
397 pass
398
399 self.configItems.update(
400 e5App().getObject("PluginManager").getPluginConfigData())
401
402 elif displayMode == ConfigurationWidget.HelpBrowserMode:
403 self.configItems = {
404 # key : [display string, pixmap name, dialog module name or
405 # page creation function, parent key,
406 # reference to configuration page (must always be last)]
407 # The dialog module must have the module function 'create' to
408 # create the configuration page. This must have the method
409 # 'save' to save the settings.
410 "interfacePage":
411 [self.tr("Interface"), "preferences-interface.png",
412 "HelpInterfacePage", None, None],
413 "networkPage":
414 [self.tr("Network"), "preferences-network.png",
415 "NetworkPage", None, None],
416 "printerPage":
417 [self.tr("Printer"), "preferences-printer.png",
418 "PrinterPage", None, None],
419 "securityPage":
420 [self.tr("Security"), "preferences-security.png",
421 "SecurityPage", None, None],
422
423 "helpDocumentationPage":
424 [self.tr("Help Documentation"),
425 "preferences-helpdocumentation.png",
426 "HelpDocumentationPage", None, None],
427 }
428 try:
429 from PyQt5 import QtWebKit # __IGNORE_WARNING__
430 self.configItems.update({
431 "helpAppearancePage":
432 [self.tr("Appearance"), "preferences-styles.png",
433 "HelpAppearancePage", None, None],
434 "helpFlashCookieManagerPage":
435 [self.tr("Flash Cookie Manager"),
436 "flashCookie16.png",
437 "HelpFlashCookieManagerPage", None, None],
438 "helpVirusTotalPage":
439 [self.tr("VirusTotal Interface"), "virustotal.png",
440 "HelpVirusTotalPage", None, None],
441 "helpWebBrowserPage":
442 [self.tr("eric6 Web Browser"), "ericWeb.png",
443 "HelpWebBrowserPage", None, None],
444 })
445 except ImportError:
446 pass
447
448 elif displayMode == ConfigurationWidget.WebBrowserMode:
449 self.configItems = {
450 # key : [display string, pixmap name, dialog module name or
451 # page creation function, parent key,
452 # reference to configuration page (must always be last)]
453 # The dialog module must have the module function 'create' to
454 # create the configuration page. This must have the method
455 # 'save' to save the settings.
456 "interfacePage":
457 [self.tr("Interface"), "preferences-interface.png",
458 "HelpInterfacePage", None, None],
459 "networkPage":
460 [self.tr("Network"), "preferences-network.png",
461 "NetworkPage", None, None],
462 "printerPage":
463 [self.tr("Printer"), "preferences-printer.png",
464 "PrinterPage", None, None],
465 "securityPage":
466 [self.tr("Security"), "preferences-security.png",
467 "SecurityPage", None, None],
468
469 "helpDocumentationPage":
470 [self.tr("Help Documentation"),
471 "preferences-helpdocumentation.png",
472 "HelpDocumentationPage", None, None],
473
474 "webBrowserAppearancePage":
475 [self.tr("Appearance"), "preferences-styles.png",
476 "WebBrowserAppearancePage", None, None],
477 "webBrowserPage":
478 [self.tr("eric6 Web Browser"), "ericWeb.png",
479 "WebBrowserPage", None, None],
480
481 "helpFlashCookieManagerPage":
482 [self.tr("Flash Cookie Manager"),
483 "flashCookie16.png",
484 "HelpFlashCookieManagerPage", None, None],
485 "webBrowserVirusTotalPage":
486 [self.tr("VirusTotal Interface"), "virustotal.png",
487 "WebBrowserVirusTotalPage", None, None],
488 }
489
490 if qVersionTuple() >= (5, 8, 0) and PYQT_VERSION >= 0x50800:
491 self.configItems.update({
492 "webBrowserSpellCheckingPage":
493 [self.tr("Spell checking"),
494 "preferences-spellchecking.png",
495 "WebBrowserSpellCheckingPage", None, None],
496 })
497
498 elif displayMode == ConfigurationWidget.TrayStarterMode:
499 self.configItems = {
500 # key : [display string, pixmap name, dialog module name or
501 # page creation function, parent key,
502 # reference to configuration page (must always be last)]
503 # The dialog module must have the module function 'create' to
504 # create the configuration page. This must have the method
505 # 'save' to save the settings.
506 "trayStarterPage":
507 [self.tr("Tray Starter"), "erict.png",
508 "TrayStarterPage", None, None],
509 }
510
511 elif displayMode == ConfigurationWidget.HexEditorMode:
512 self.configItems = {
513 # key : [display string, pixmap name, dialog module name or
514 # page creation function, parent key,
515 # reference to configuration page (must always be last)]
516 # The dialog module must have the module function 'create' to
517 # create the configuration page. This must have the method
518 # 'save' to save the settings.
519 "hexEditorPage":
520 [self.tr("Hex Editor"), "hexEditor.png",
521 "HexEditorPage", None, None],
522 }
523
524 else:
525 raise RuntimeError("Illegal mode value: {0}".format(displayMode))
526
527 # generate the list entries
528 self.__expandedEntries = []
529 for key in sorted(self.configItems.keys()):
530 pageData = self.configItems[key]
531 if pageData[3]:
532 if pageData[3] in self.itmDict:
533 pitm = self.itmDict[pageData[3]] # get the parent item
534 else:
535 continue
536 else:
537 pitm = self.configList
538 self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key,
539 pageData[1])
540 self.itmDict[key].setData(0, Qt.UserRole, key)
541 if (not self.fromEric or
542 displayMode != ConfigurationWidget.DefaultMode or
543 key in expandedEntries):
544 self.itmDict[key].setExpanded(True)
545 self.configList.sortByColumn(0, Qt.AscendingOrder)
546
547 # set the initial size of the splitter
548 self.configSplitter.setSizes([200, 600])
549
550 self.configList.itemActivated.connect(self.__showConfigurationPage)
551 self.configList.itemClicked.connect(self.__showConfigurationPage)
552 self.buttonBox.accepted.connect(self.accept)
553 self.buttonBox.rejected.connect(self.rejected)
554
555 if displayMode in [ConfigurationWidget.HelpBrowserMode,
556 ConfigurationWidget.TrayStarterMode,
557 ConfigurationWidget.HexEditorMode,
558 ConfigurationWidget.WebBrowserMode]:
559 self.configListSearch.hide()
560
561 if displayMode not in [ConfigurationWidget.TrayStarterMode,
562 ConfigurationWidget.HexEditorMode]:
563 self.__initLexers()
564
565 def accept(self):
566 """
567 Public slot to accept the buttonBox accept signal.
568 """
569 if not isMacPlatform():
570 wdg = self.focusWidget()
571 if wdg == self.configList:
572 return
573
574 self.accepted.emit()
575
576 def __setupUi(self):
577 """
578 Private method to perform the general setup of the configuration
579 widget.
580 """
581 self.setObjectName("ConfigurationDialog")
582 self.resize(900, 650)
583 self.verticalLayout_2 = QVBoxLayout(self)
584 self.verticalLayout_2.setSpacing(6)
585 self.verticalLayout_2.setContentsMargins(6, 6, 6, 6)
586 self.verticalLayout_2.setObjectName("verticalLayout_2")
587
588 self.configSplitter = QSplitter(self)
589 self.configSplitter.setOrientation(Qt.Horizontal)
590 self.configSplitter.setObjectName("configSplitter")
591
592 self.configListWidget = QWidget(self.configSplitter)
593 self.leftVBoxLayout = QVBoxLayout(self.configListWidget)
594 self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0)
595 self.leftVBoxLayout.setSpacing(0)
596 self.leftVBoxLayout.setObjectName("leftVBoxLayout")
597 self.configListSearch = E5ClearableLineEdit(
598 self, self.tr("Enter search text..."))
599 self.configListSearch.setObjectName("configListSearch")
600 self.leftVBoxLayout.addWidget(self.configListSearch)
601 self.configList = QTreeWidget()
602 self.configList.setObjectName("configList")
603 self.leftVBoxLayout.addWidget(self.configList)
604 self.configListSearch.textChanged.connect(self.__searchTextChanged)
605
606 self.scrollArea = QScrollArea(self.configSplitter)
607 self.scrollArea.setFrameShape(QFrame.NoFrame)
608 self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
609 self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
610 self.scrollArea.setWidgetResizable(False)
611 self.scrollArea.setObjectName("scrollArea")
612
613 self.configStack = QStackedWidget()
614 self.configStack.setFrameShape(QFrame.Box)
615 self.configStack.setFrameShadow(QFrame.Sunken)
616 self.configStack.setObjectName("configStack")
617 self.scrollArea.setWidget(self.configStack)
618
619 self.emptyPage = QWidget()
620 self.emptyPage.setGeometry(QRect(0, 0, 372, 591))
621 self.emptyPage.setObjectName("emptyPage")
622 self.vboxlayout = QVBoxLayout(self.emptyPage)
623 self.vboxlayout.setSpacing(6)
624 self.vboxlayout.setContentsMargins(6, 6, 6, 6)
625 self.vboxlayout.setObjectName("vboxlayout")
626 spacerItem = QSpacerItem(
627 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
628 self.vboxlayout.addItem(spacerItem)
629 self.emptyPagePixmap = QLabel(self.emptyPage)
630 self.emptyPagePixmap.setAlignment(Qt.AlignCenter)
631 self.emptyPagePixmap.setObjectName("emptyPagePixmap")
632 self.emptyPagePixmap.setPixmap(
633 QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png')))
634 self.vboxlayout.addWidget(self.emptyPagePixmap)
635 self.textLabel1 = QLabel(self.emptyPage)
636 self.textLabel1.setAlignment(Qt.AlignCenter)
637 self.textLabel1.setObjectName("textLabel1")
638 self.vboxlayout.addWidget(self.textLabel1)
639 spacerItem1 = QSpacerItem(
640 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
641 self.vboxlayout.addItem(spacerItem1)
642 self.configStack.addWidget(self.emptyPage)
643
644 self.verticalLayout_2.addWidget(self.configSplitter)
645
646 self.buttonBox = QDialogButtonBox(self)
647 self.buttonBox.setOrientation(Qt.Horizontal)
648 self.buttonBox.setStandardButtons(
649 QDialogButtonBox.Apply | QDialogButtonBox.Cancel |
650 QDialogButtonBox.Ok | QDialogButtonBox.Reset)
651 self.buttonBox.setObjectName("buttonBox")
652 if not self.fromEric and \
653 self.displayMode == ConfigurationWidget.DefaultMode:
654 self.buttonBox.button(QDialogButtonBox.Apply).hide()
655 self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
656 self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
657 self.verticalLayout_2.addWidget(self.buttonBox)
658
659 self.setWindowTitle(self.tr("Preferences"))
660
661 self.configList.header().hide()
662 self.configList.header().setSortIndicator(0, Qt.AscendingOrder)
663 self.configList.setSortingEnabled(True)
664 self.textLabel1.setText(
665 self.tr("Please select an entry of the list \n"
666 "to display the configuration page."))
667
668 QMetaObject.connectSlotsByName(self)
669 self.setTabOrder(self.configList, self.configStack)
670
671 self.configStack.setCurrentWidget(self.emptyPage)
672
673 self.configList.setFocus()
674
675 def __searchTextChanged(self, text):
676 """
677 Private slot to handle a change of the search text.
678
679 @param text text to search for (string)
680 """
681 self.__searchChildItems(self.configList.invisibleRootItem(), text)
682
683 def __searchChildItems(self, parent, text):
684 """
685 Private method to enable child items based on a search string.
686
687 @param parent reference to the parent item (QTreeWidgetItem)
688 @param text text to search for (string)
689 @return flag indicating an enabled child item (boolean)
690 """
691 childEnabled = False
692 text = text.lower()
693 for index in range(parent.childCount()):
694 itm = parent.child(index)
695 if itm.childCount() > 0:
696 enable = self.__searchChildItems(itm, text) or \
697 text == "" or text in itm.text(0).lower()
698 else:
699 enable = text == "" or text in itm.text(0).lower()
700 if enable:
701 childEnabled = True
702 itm.setDisabled(not enable)
703
704 return childEnabled
705
706 def __initLexers(self):
707 """
708 Private method to initialize the dictionary of preferences lexers.
709 """
710 import QScintilla.Lexers
711 from .PreferencesLexer import PreferencesLexer, \
712 PreferencesLexerLanguageError
713
714 self.lexers = {}
715 for language in QScintilla.Lexers.getSupportedLanguages():
716 if language not in self.lexers:
717 try:
718 self.lexers[language] = PreferencesLexer(language, self)
719 except PreferencesLexerLanguageError:
720 pass
721
722 def __importConfigurationPage(self, name):
723 """
724 Private method to import a configuration page module.
725
726 @param name name of the configuration page module (string)
727 @return reference to the configuration page module
728 """
729 modName = "Preferences.ConfigurationPages.{0}".format(name)
730 try:
731 mod = __import__(modName)
732 components = modName.split('.')
733 for comp in components[1:]:
734 mod = getattr(mod, comp)
735 return mod
736 except ImportError:
737 E5MessageBox.critical(
738 self,
739 self.tr("Configuration Page Error"),
740 self.tr("""<p>The configuration page <b>{0}</b>"""
741 """ could not be loaded.</p>""").format(name))
742 return None
743
744 def __showConfigurationPage(self, itm, column):
745 """
746 Private slot to show a selected configuration page.
747
748 @param itm reference to the selected item (QTreeWidgetItem)
749 @param column column that was selected (integer) (ignored)
750 """
751 pageName = itm.getPageName()
752 self.showConfigurationPageByName(pageName, setCurrent=False)
753
754 def __initPage(self, pageData):
755 """
756 Private method to initialize a configuration page.
757
758 @param pageData data structure for the page to initialize
759 @return reference to the initialized page
760 """
761 page = None
762 if isinstance(pageData[2], types.FunctionType):
763 page = pageData[2](self)
764 else:
765 mod = self.__importConfigurationPage(pageData[2])
766 if mod:
767 page = mod.create(self)
768 if page is not None:
769 self.configStack.addWidget(page)
770 pageData[-1] = page
771 try:
772 page.setMode(self.displayMode)
773 except AttributeError:
774 pass
775 return page
776
777 def showConfigurationPageByName(self, pageName, setCurrent=True):
778 """
779 Public slot to show a named configuration page.
780
781 @param pageName name of the configuration page to show (string)
782 @param setCurrent flag indicating to set the current item (boolean)
783 """
784 if pageName == "empty" or pageName not in self.configItems:
785 page = self.emptyPage
786 else:
787 pageData = self.configItems[pageName]
788 if pageData[-1] is None and pageData[2] is not None:
789 # the page was not loaded yet, create it
790 page = self.__initPage(pageData)
791 else:
792 page = pageData[-1]
793 if page is None:
794 page = self.emptyPage
795 elif setCurrent:
796 items = self.configList.findItems(
797 pageData[0],
798 Qt.MatchFixedString | Qt.MatchRecursive)
799 for item in items:
800 if item.data(0, Qt.UserRole) == pageName:
801 self.configList.setCurrentItem(item)
802 self.configStack.setCurrentWidget(page)
803 ssize = self.scrollArea.size()
804 if self.scrollArea.horizontalScrollBar():
805 ssize.setHeight(
806 ssize.height() -
807 self.scrollArea.horizontalScrollBar().height() - 2)
808 if self.scrollArea.verticalScrollBar():
809 ssize.setWidth(
810 ssize.width() -
811 self.scrollArea.verticalScrollBar().width() - 2)
812 psize = page.minimumSizeHint()
813 self.configStack.resize(max(ssize.width(), psize.width()),
814 max(ssize.height(), psize.height()))
815
816 if page != self.emptyPage:
817 page.polishPage()
818 self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True)
819 self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
820 else:
821 self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
822 self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
823
824 # reset scrollbars
825 for sb in [self.scrollArea.horizontalScrollBar(),
826 self.scrollArea.verticalScrollBar()]:
827 if sb:
828 sb.setValue(0)
829
830 self.__currentConfigurationPageName = pageName
831
832 def getConfigurationPageName(self):
833 """
834 Public method to get the page name of the current page.
835
836 @return page name of the current page (string)
837 """
838 return self.__currentConfigurationPageName
839
840 def calledFromEric(self):
841 """
842 Public method to check, if invoked from within eric.
843
844 @return flag indicating invocation from within eric (boolean)
845 """
846 return self.fromEric
847
848 def getPage(self, pageName):
849 """
850 Public method to get a reference to the named page.
851
852 @param pageName name of the configuration page (string)
853 @return reference to the page or None, indicating page was
854 not loaded yet
855 """
856 return self.configItems[pageName][-1]
857
858 def getLexers(self):
859 """
860 Public method to get a reference to the lexers dictionary.
861
862 @return reference to the lexers dictionary
863 """
864 return self.lexers
865
866 def setPreferences(self):
867 """
868 Public method called to store the selected values into the preferences
869 storage.
870 """
871 for pageData in self.configItems.values():
872 if pageData[-1]:
873 pageData[-1].save()
874 # page was loaded (and possibly modified)
875 QApplication.processEvents() # ensure HMI is responsive
876
877 def on_buttonBox_clicked(self, button):
878 """
879 Private slot called by a button of the button box clicked.
880
881 @param button button that was clicked (QAbstractButton)
882 """
883 if button == self.buttonBox.button(QDialogButtonBox.Apply):
884 self.on_applyButton_clicked()
885 elif button == self.buttonBox.button(QDialogButtonBox.Reset):
886 self.on_resetButton_clicked()
887
888 @pyqtSlot()
889 def on_applyButton_clicked(self):
890 """
891 Private slot called to apply the settings of the current page.
892 """
893 if self.configStack.currentWidget() != self.emptyPage:
894 page = self.configStack.currentWidget()
895 savedState = page.saveState()
896 page.save()
897 self.preferencesChanged.emit()
898 if savedState is not None:
899 page.setState(savedState)
900 page.polishPage()
901
902 @pyqtSlot()
903 def on_resetButton_clicked(self):
904 """
905 Private slot called to reset the settings of the current page.
906 """
907 if self.configStack.currentWidget() != self.emptyPage:
908 currentPage = self.configStack.currentWidget()
909 savedState = currentPage.saveState()
910 pageName = self.configList.currentItem().getPageName()
911 self.configStack.removeWidget(currentPage)
912 if pageName == "editorHighlightingStylesPage":
913 self.__initLexers()
914 self.configItems[pageName][-1] = None
915
916 self.showConfigurationPageByName(pageName)
917 if savedState is not None:
918 self.configStack.currentWidget().setState(savedState)
919
920 def getExpandedEntries(self):
921 """
922 Public method to get a list of expanded entries.
923
924 @return list of expanded entries (list of string)
925 """
926 return self.__expandedEntries
927
928 @pyqtSlot(QTreeWidgetItem)
929 def on_configList_itemCollapsed(self, item):
930 """
931 Private slot handling a list entry being collapsed.
932
933 @param item reference to the collapsed item (QTreeWidgetItem)
934 """
935 pageName = item.data(0, Qt.UserRole)
936 if pageName in self.__expandedEntries:
937 self.__expandedEntries.remove(pageName)
938
939 @pyqtSlot(QTreeWidgetItem)
940 def on_configList_itemExpanded(self, item):
941 """
942 Private slot handling a list entry being expanded.
943
944 @param item reference to the expanded item (QTreeWidgetItem)
945 """
946 pageName = item.data(0, Qt.UserRole)
947 if pageName not in self.__expandedEntries:
948 self.__expandedEntries.append(pageName)
949
950 def isUsingWebEngine(self):
951 """
952 Public method to get an indication, if QtWebEngine is being used.
953
954 @return flag indicating the use of QtWebEngine
955 @rtype bool
956 """
957 return self.__webEngine or \
958 self.displayMode == ConfigurationWidget.WebBrowserMode
959
960
961 class ConfigurationDialog(QDialog):
962 """
963 Class for the dialog variant.
964
965 @signal preferencesChanged() emitted after settings have been changed
966 @signal masterPasswordChanged(str, str) emitted after the master
967 password has been changed with the old and the new password
968 """
969 preferencesChanged = pyqtSignal()
970 masterPasswordChanged = pyqtSignal(str, str)
971
972 DefaultMode = ConfigurationWidget.DefaultMode
973 HelpBrowserMode = ConfigurationWidget.HelpBrowserMode
974 TrayStarterMode = ConfigurationWidget.TrayStarterMode
975 HexEditorMode = ConfigurationWidget.HexEditorMode
976 WebBrowserMode = ConfigurationWidget.WebBrowserMode
977
978 def __init__(self, parent=None, name=None, modal=False,
979 fromEric=True, displayMode=ConfigurationWidget.DefaultMode,
980 expandedEntries=None):
981 """
982 Constructor
983
984 @param parent The parent widget of this dialog. (QWidget)
985 @param name The name of this dialog. string
986 @param modal Flag indicating a modal dialog. (boolean)
987 @keyparam fromEric flag indicating a dialog generation from within the
988 eric6 ide (boolean)
989 @keyparam displayMode mode of the configuration dialog
990 (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode,
991 WebBrowserMode)
992 @keyparam expandedEntries list of entries to be shown expanded
993 (list of strings)
994 """
995 super(ConfigurationDialog, self).__init__(parent)
996 if name:
997 self.setObjectName(name)
998 self.setModal(modal)
999 self.setWindowFlags(Qt.Window)
1000
1001 self.layout = QVBoxLayout(self)
1002 self.layout.setContentsMargins(0, 0, 0, 0)
1003 self.layout.setSpacing(0)
1004
1005 self.cw = ConfigurationWidget(self, fromEric=fromEric,
1006 displayMode=displayMode,
1007 expandedEntries=expandedEntries)
1008 size = self.cw.size()
1009 self.layout.addWidget(self.cw)
1010 self.resize(size)
1011 self.setWindowTitle(self.cw.windowTitle())
1012
1013 self.cw.accepted.connect(self.accept)
1014 self.cw.rejected.connect(self.reject)
1015 self.cw.preferencesChanged.connect(self.__preferencesChanged)
1016 self.cw.masterPasswordChanged.connect(self.__masterPasswordChanged)
1017
1018 def __preferencesChanged(self):
1019 """
1020 Private slot to handle a change of the preferences.
1021 """
1022 self.preferencesChanged.emit()
1023
1024 def __masterPasswordChanged(self, oldPassword, newPassword):
1025 """
1026 Private slot to handle the change of the master password.
1027
1028 @param oldPassword current master password (string)
1029 @param newPassword new master password (string)
1030 """
1031 self.masterPasswordChanged.emit(oldPassword, newPassword)
1032
1033 def showConfigurationPageByName(self, pageName):
1034 """
1035 Public slot to show a named configuration page.
1036
1037 @param pageName name of the configuration page to show (string)
1038 """
1039 self.cw.showConfigurationPageByName(pageName)
1040
1041 def getConfigurationPageName(self):
1042 """
1043 Public method to get the page name of the current page.
1044
1045 @return page name of the current page (string)
1046 """
1047 return self.cw.getConfigurationPageName()
1048
1049 def getExpandedEntries(self):
1050 """
1051 Public method to get a list of expanded entries.
1052
1053 @return list of expanded entries (list of string)
1054 """
1055 return self.cw.getExpandedEntries()
1056
1057 def setPreferences(self):
1058 """
1059 Public method called to store the selected values into the preferences
1060 storage.
1061 """
1062 self.cw.setPreferences()
1063
1064 def accept(self):
1065 """
1066 Public method to accept the dialog.
1067 """
1068 super(ConfigurationDialog, self).accept()
1069
1070
1071 class ConfigurationWindow(E5MainWindow):
1072 """
1073 Main window class for the standalone dialog.
1074 """
1075 def __init__(self, parent=None):
1076 """
1077 Constructor
1078
1079 @param parent reference to the parent widget (QWidget)
1080 """
1081 super(ConfigurationWindow, self).__init__(parent)
1082
1083 self.cw = ConfigurationWidget(self, fromEric=False)
1084 size = self.cw.size()
1085 self.setCentralWidget(self.cw)
1086 self.resize(size)
1087 self.setWindowTitle(self.cw.windowTitle())
1088
1089 self.setStyle(Preferences.getUI("Style"),
1090 Preferences.getUI("StyleSheet"))
1091
1092 self.cw.accepted.connect(self.accept)
1093 self.cw.rejected.connect(self.close)
1094
1095 def showConfigurationPageByName(self, pageName):
1096 """
1097 Public slot to show a named configuration page.
1098
1099 @param pageName name of the configuration page to show (string)
1100 """
1101 self.cw.showConfigurationPageByName(pageName)
1102
1103 def accept(self):
1104 """
1105 Public slot called by the Ok button.
1106 """
1107 self.cw.setPreferences()
1108 Preferences.saveResetLayout()
1109 Preferences.syncPreferences()
1110 self.close()

eric ide

mercurial