1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Package implementing the preferences interface.
8
9The preferences interface consists of a class, which defines the default
10values for all configuration items and stores the actual values. These
11values are read and written to the eric6 preferences file by module
12functions. The data is stored in a file in a subdirectory of the users home
13directory. The individual configuration data is accessed by accessor functions
14defined on the module level. The module is simply imported wherever it is
15needed with the statement 'import Preferences'. Do not use
16'from Preferences import *' to import it.
17"""
18
19import ast
20import os
21import fnmatch
22import shutil
23import json
24import sys
25import contextlib
26
27from PyQt5.QtCore import (
28    QDir, QPoint, QLocale, QSettings, QFileInfo, QCoreApplication, QByteArray,
29    QSize, QUrl, Qt, QLibraryInfo, QDateTime
30)
31from PyQt5.QtGui import QColor, QFont, QPalette
32from PyQt5.QtWidgets import QApplication
33try:
34    from PyQt5.QtWebEngineWidgets import QWebEngineSettings
35except ImportError:
36    QWebEngineSettings = None
37from PyQt5.Qsci import QsciScintilla, QsciLexerPython
38
39from E5Gui import E5FileDialog
40
41from E5Network.E5Ftp import E5FtpProxyType
42
43import Globals
44
45from Project.ProjectBrowserFlags import (
46    SourcesBrowserFlag, FormsBrowserFlag, ResourcesBrowserFlag,
47    TranslationsBrowserFlag, InterfacesBrowserFlag, OthersBrowserFlag,
48    ProtocolsBrowserFlag, AllBrowsersFlag
49)
50
51from QScintilla.Shell import ShellHistoryStyle
52
53
54class Prefs:
55    """
56    A class to hold all configuration items for the application.
57    """
58    # defaults for the variables window
59    varDefaults = {
60        "LocalsFilter": "[]",
61        "GlobalsFilter": "[]"
62    }
63
64    # defaults for the debugger
65    debuggerDefaults = {
66        "RemoteDbgEnabled": False,
67        "RemoteHost": "",
68        "RemoteExecution": "",
69        "PassiveDbgEnabled": False,
70        "PassiveDbgPort": 42424,
71        "PassiveDbgType": "Python",
72        "AutomaticReset": False,
73        "Autosave": True,
74        "ThreeStateBreakPoints": False,
75        "RecentNumber": 9,
76        # max. number of file names to be remembered for the add breakpoint
77        # dialog
78        "BreakAlways": False,
79        "ShowExceptionInShell": True,
80        "Python3VirtualEnv": "",
81        "RubyInterpreter": "",
82        "DebugClientType3": "standard",
83        # supported "standard", "custom"
84        "DebugClient3": "",
85        "DebugEnvironmentReplace": False,
86        "DebugEnvironment": "",
87        "PythonRedirect": True,
88        "PythonNoEncoding": False,
89        "Python3Redirect": True,
90        "Python3NoEncoding": False,
91        "RubyRedirect": True,
92        "ConsoleDbgEnabled": False,
93        "ConsoleDbgCommand": "",
94        "PathTranslation": False,
95        "PathTranslationRemote": "",
96        "PathTranslationLocal": "",
97        "NetworkInterface": "127.0.0.1",
98        "AutoViewSourceCode": False,
99        "MaxVariableSize": 0,     # Bytes, 0 = no limit
100        "BgColorNew": QColor("#28FFEEAA"),
101        "BgColorChanged": QColor("#2870FF66"),
102        "AllowedHosts": ["127.0.0.1", "::1%0"],
103        # space separated list of Python3 extensions
104        "Python3Extensions": ".py .pyw .py3 .pyw3",
105        # Global Multiprocess Debugging Support
106        "MultiProcessEnabled": True,
107    }
108
109    # defaults for the UI settings
110    uiDefaults = {
111        "KeyboardInputInterval": 0,         # 0 = use system default
112        "BackgroundServiceProcesses": 0,    # 0 = max. CPUs minus one
113        "Language": "System",
114        "Style": "System",
115        "StyleSheet": "",
116        "ViewManager": "tabview",
117        "LayoutType": "Sidebars",           # "Toolboxes" or "Sidebars"
118        "ShellPosition": "bottom",          # "left", "right" or "bottom"
119        "SidebarDelay": 200,
120        "BrowsersListFoldersFirst": True,
121        "BrowsersHideNonPublic": False,
122        "BrowsersListContentsByOccurrence": False,
123        "BrowsersListHiddenFiles": False,
124        "BrowsersFileFilters": "*.py[co];*.so;*.dll",
125        "BrowserShowCoding": True,
126        "LogViewerAutoRaise": True,
127        "LogViewerStdoutFilter": [],
128        "LogViewerStderrFilter": [],
129        "LogViewerStdxxxFilter": [],
130        "SingleApplicationMode": False,
131        "CaptionShowsFilename": True,
132        "CaptionFilenameLength": 100,
133        "RecentNumber": 9,
134        "TabViewManagerFilenameLength": 40,
135        "TabViewManagerFilenameOnly": True,
136        "ShowFilePreview": True,
137        "ShowFilePreviewJS": True,
138        "ShowFilePreviewSSI": True,
139        "ShowTemplateViewer": True,             # left side
140        "ShowFileBrowser": True,                # left side
141        "ShowSymbolsViewer": True,              # left side
142        "ShowCodeDocumentationViewer": True,    # right side
143        "ShowPyPIPackageManager": True,         # right side
144        "ShowCondaPackageManager": True,        # right side
145        "ShowCooperation": True,                # right side
146        "ShowIrc": True,                        # right side
147        "ShowMicroPython": True,                # right side
148        "ShowNumbersViewer": True,              # bottom side
149        "ViewProfiles2": {
150            "edit": [
151                # saved state main window with toolbox windows (0)
152                QByteArray(),
153                # visibility of the toolboxes/sidebars (1)
154                # left, bottom, right
155                [True, True, True],
156                # saved states of the splitters and sidebars of the
157                # sidebars layout (2)
158                # left splitter, vertical splitter, left sidebar,
159                # bottom sidebar, right splitter, right sidebar
160                [QByteArray(), QByteArray(), QByteArray(),
161                 QByteArray(), QByteArray(), QByteArray()],
162            ],
163            "debug": [
164                # saved state main window with toolbox windows (0)
165                QByteArray(),
166                # visibility of the toolboxes/sidebars (1)
167                # left, bottom, right
168                [False, True, True],
169                # saved states of the splitters and sidebars of the
170                # sidebars layout (2)
171                # left splitter, vertical splitter, left sidebar,
172                # bottom sidebar, right splitter, right sidebar
173                [QByteArray(), QByteArray(), QByteArray(),
174                 QByteArray(), QByteArray(), QByteArray()],
175            ],
176        },
177        "ToolbarManagerState": QByteArray(),
178        "PreviewSplitterState": QByteArray(),
179        "ShowSplash": True,
180        "SplitOrientationVertical": False,
181        "UseNativeMenuBar": True,
182
183        "PerformVersionCheck": 3,
184        # 0 = off
185        # 1 = at startup
186        # 2 = daily
187        # 3 = weekly
188        # 4 = monthly
189        "UseProxy": False,
190        "UseSystemProxy": True,
191        "UseHttpProxyForAll": False,
192        "ProxyHost/Http": "",
193        "ProxyHost/Https": "",
194        "ProxyHost/Ftp": "",
195        "ProxyPort/Http": 80,
196        "ProxyPort/Https": 443,
197        "ProxyPort/Ftp": 21,
198        "ProxyUser/Http": "",
199        "ProxyUser/Https": "",
200        "ProxyUser/Ftp": "",
201        "ProxyPassword/Http": "",
202        "ProxyPassword/Https": "",
203        "ProxyPassword/Ftp": "",
204        "ProxyType/Ftp": E5FtpProxyType.NO_PROXY,
205        "ProxyAccount/Ftp": "",
206        "ProxyExceptions": "localhost,127.0.0.,::1",
207
208        "PluginRepositoryUrl6":
209        "https://eric-ide.python-projects.org/plugins6/repository.xml",
210        "VersionsUrls6": [
211            "https://eric-ide.python-projects.org/versions/versions6",
212            "https://die-offenbachs.homelinux.org/eric/versions/"
213            "versions6",
214        ],
215
216        "OpenOnStartup": 0,        # 0 = nothing
217                                   # 1 = last file
218                                   # 2 = last project
219                                   # 3 = last multiproject
220                                   # 4 = last global session
221        "OpenCrashSessionOnStartup": True,
222        "CrashSessionEnabled": True,
223
224        "DownloadPath": "",
225        "RequestDownloadFilename": True,
226        "CheckErrorLog": True,
227        "MinimumMessageTypeSeverity": 2,    # 0 = QtDebugMsg
228                                            # 1 = QtWarningMsg
229                                            # 2 = QtCriticalMsg, QtSystemMsg
230                                            # 3 = QtFatalMsg
231
232        "LogStdErrColour": QColor(Qt.GlobalColor.red),
233        "NotificationTimeout": 5,       # time in seconds the notification
234                                        # is shown
235        "NotificationPosition": QPoint(10, 10),
236        "NotificationWarningForeground": "#606000",
237        "NotificationWarningBackground": "#ffffd0",
238        "NotificationCriticalForeground": "#600000",
239        "NotificationCriticalBackground": "#ffd0d0",
240        "TextMimeTypes": [
241            "application/bookmarks.xbel",
242            "application/x-xbel",
243            "application/opensearchdescription+xml",
244            "application/x-actionscript",
245            "application/x-actionscript3",
246            "application/x-awk",
247            "application/x-sh",
248            "application/x-shellscript",
249            "application/x-shell-session",
250            "application/x-dos-batch",
251            "application/x-befunge",
252            "application/x-brainfuck",
253            "application/x-javascript+cheetah",
254            "application/x-javascript+spitfire",
255            "application/x-cheetah",
256            "application/x-spitfire",
257            "application/xml+cheetah",
258            "application/xml+spitfire",
259            "application/x-clojure",
260            "application/x-coldfusion",
261            "application/x-cython",
262            "application/x-django-templating",
263            "application/x-jinja",
264            "application/xml-dtd",
265            "application/x-ecl",
266            "application/x-ruby-templating",
267            "application/x-evoque",
268            "application/xml+evoque",
269            "application/x-fantom",
270            "application/x-genshi",
271            "application/x-kid",
272            "application/x-genshi-text",
273            "application/x-gettext",
274            "application/x-troff",
275            "application/xhtml+xml",
276            "application/x-php",
277            "application/x-httpd-php",
278            "application/x-httpd-php3",
279            "application/x-httpd-php4",
280            "application/x-httpd-php5",
281            "application/x-hybris",
282            "application/x-javascript+django",
283            "application/x-javascript+jinja",
284            "application/x-javascript+ruby",
285            "application/x-javascript+genshi",
286            "application/javascript",
287            "application/x-javascript",
288            "application/x-javascript+php",
289            "application/x-javascript+smarty",
290            "application/json",
291            "application/x-jsp",
292            "application/x-julia",
293            "application/x-httpd-lasso",
294            "application/x-httpd-lasso[89]",
295            "application/x-httpd-lasso8",
296            "application/x-httpd-lasso9",
297            "application/x-javascript+lasso",
298            "application/xml+lasso",
299            "application/x-lua",
300            "application/x-javascript+mako",
301            "application/x-mako",
302            "application/xml+mako",
303            "application/x-gooddata-maql",
304            "application/x-mason",
305            "application/x-moonscript",
306            "application/x-javascript+myghty",
307            "application/x-myghty",
308            "application/xml+myghty",
309            "application/x-newlisp",
310            "application/x-openedge",
311            "application/x-perl",
312            "application/postscript",
313            "application/x-pypylog",
314            "application/x-python3",
315            "application/x-python",
316            "application/x-qml",
317            "application/x-racket",
318            "application/x-pygments-tokens",
319            "application/x-ruby",
320            "application/x-standardml",
321            "application/x-scheme",
322            "application/x-sh-session",
323            "application/x-smarty",
324            "application/x-ssp",
325            "application/x-tcl",
326            "application/x-csh",
327            "application/x-urbiscript",
328            "application/xml+velocity",
329            "application/xquery",
330            "application/xml+django",
331            "application/xml+jinja",
332            "application/xml+ruby",
333            "application/xml",
334            "application/rss+xml",
335            "application/atom+xml",
336            "application/xml+php",
337            "application/xml+smarty",
338            "application/xsl+xml",
339            "application/xslt+xml",
340            "application/x-desktop",
341
342            "image/svg+xml",
343        ],
344    }
345
346    iconsDefaults = {
347        "Path": [],
348        "DefaultIconsPath": "automatic",
349        # automatic, breeze-dark, breeze-light, oxygen
350    }
351
352    # defaults for the cooperation settings
353    cooperationDefaults = {
354        "ServerPort": 42000,
355        "AutoStartServer": False,
356        "TryOtherPorts": True,
357        "MaxPortsToTry": 100,
358        "AutoAcceptConnections": False,
359        "BannedUsers": [],
360    }
361
362    # defaults for the editor settings
363    editorDefaults = {
364        "AutosaveInterval": 0,
365        "TabWidth": 4,
366        "IndentWidth": 4,
367        "TabIndentOverride": "{}",      # JSON formatted dictionary
368        "IndentationGuides": True,
369        "LinenoMargin": True,
370        "FoldingMargin": True,
371        "FoldingStyle": 1,
372        "TabForIndentation": False,
373        "TabIndents": True,
374        "ConvertTabsOnLoad": False,
375        "AutomaticEOLConversion": True,
376        "ShowWhitespace": False,
377        "WhitespaceSize": 1,
378        "ShowEOL": False,
379        "UseMonospacedFont": False,
380        "WrapLongLinesMode": QsciScintilla.WrapMode.WrapNone,
381        "WrapVisualFlag": QsciScintilla.WrapVisualFlag.WrapFlagNone,
382        "WrapIndentMode": QsciScintilla.WrapIndentMode.WrapIndentFixed,
383        "WrapStartIndent": 0,
384        "WarnFilesize": 512,
385        "ClearBreaksOnClose": True,
386        "StripTrailingWhitespace": False,
387        "InsertFinalNewline": True,
388        "CommentColumn0": True,
389        "OverrideEditAreaColours": False,
390
391        "EdgeMode": QsciScintilla.EdgeMode.EdgeNone,
392        "EdgeColumn": 80,
393
394        "AutoIndentation": True,
395        "BraceHighlighting": True,
396        "CreateBackupFile": False,
397        "CaretLineVisible": False,
398        "CaretLineAlwaysVisible": False,
399        "CaretWidth": 1,
400        "CaretLineFrameWidth": 0,
401        "ColourizeSelText": False,
402        "CustomSelectionColours": False,
403        "ExtendSelectionToEol": False,
404        "LineMarkersBackground": True,
405
406        "AutoPrepareAPIs": False,
407
408        "AutoCompletionEnabled": False,
409        "AutoCompletionCaseSensitivity": True,
410        "AutoCompletionReplaceWord": False,
411        "AutoCompletionShowSingle": False,
412        "AutoCompletionSource": QsciScintilla.AutoCompletionSource.AcsDocument,
413        "AutoCompletionThreshold": 2,
414        # timeout in ms before auto-completion is started
415        "AutoCompletionTimeout": 200,
416        "AutoCompletionFillups": False,
417        # show QScintilla completions, if plug-in fails
418        "AutoCompletionScintillaOnFail": False,
419        "AutoCompletionReversedList": False,
420        "AutoCompletionCacheEnabled": True,
421        "AutoCompletionCacheSize": 100,
422        "AutoCompletionCacheTime": 300,     # 5 minutes
423        "AutoCompletionWatchdogTime": 3000,     # ms
424        "AutoCompletionMaxLines": 5,
425        "AutoCompletionMaxChars": 40,
426
427        "CallTipsEnabled": False,
428        "CallTipsVisible": 0,
429        "CallTipsStyle": QsciScintilla.CallTipsStyle.CallTipsNoContext,
430        # show QScintilla calltips, if plug-in fails
431        "CallTipsScintillaOnFail": False,
432
433        "AutoCheckSyntax": True,
434        "OnlineSyntaxCheck": True,
435        "OnlineSyntaxCheckInterval": 5,
436
437        "OnlineChangeTrace": True,
438        "OnlineChangeTraceInterval": 500,      # 1000 milliseconds
439
440        "AutoReopen": False,
441
442        "AnnotationsEnabled": True,
443
444        "MiniContextMenu": False,
445        "HideFormatButtons": True,
446
447        "SearchMarkersEnabled": True,
448        "QuickSearchMarkersEnabled": True,
449        "MarkOccurrencesEnabled": True,
450        "MarkOccurrencesTimeout": 500,     # 500 milliseconds
451        "SearchRegexpMode": 0,             # 0: POSIX mode, 1: CXX11 mode
452        "AdvancedEncodingDetection": True,
453
454        "SpellCheckingEnabled": True,
455        "AutoSpellCheckingEnabled": True,
456        "AutoSpellCheckChunkSize": 30,
457        "SpellCheckStringsOnly": True,
458        "SpellCheckingMinWordSize": 3,
459        "SpellCheckingDefaultLanguage": "en_US",
460        "SpellCheckingPersonalWordList": "",
461        "SpellCheckingPersonalExcludeList": "",
462        "FullSpellCheckExtensions": ["md", "markdown", "rst", "txt"],
463        "FullSpellCheckUnknown": False,
464
465        "DefaultEncoding": "utf-8",
466        "DefaultOpenFilter": QCoreApplication.translate(
467            'Lexers', 'Python Files (*.py *.py3)'),
468        "DefaultSaveFilter": QCoreApplication.translate(
469            'Lexers', "Python3 Files (*.py)"),
470        "AdditionalOpenFilters": [],
471        "AdditionalSaveFilters": [],
472
473        "ZoomFactor": 0,
474
475        "PreviewRefreshWaitTimer": 500,     # wait time in milliseconds
476        "PreviewHtmlFileNameExtensions": ["html", "htm", "svg", "asp", "kid"],
477        "PreviewMarkdownFileNameExtensions": ["md", "markdown"],
478        "PreviewRestFileNameExtensions": ["rst"],
479        "PreviewQssFileNameExtensions": ["qss"],
480        "PreviewRestUseSphinx": False,
481        "PreviewMarkdownNLtoBR": False,
482        "PreviewMarkdownUsePyMdownExtensions": True,
483        "PreviewMarkdownMathJax": True,
484        "PreviewMarkdownMermaid": True,
485        "PreviewMarkdownHTMLFormat": "HTML5",  # XHTML1, HTML4, HTML5
486        "PreviewRestDocutilsHTMLFormat": "HTML5",   # HTML4, HTML5
487
488        "VirtualSpaceOptions": QsciScintilla.SCVS_NONE,
489
490        "MouseClickHandlersEnabled": True,
491
492        "ShowMarkerMapOnRight": True,
493        "ShowMarkerChanges": True,
494        "ShowMarkerCoverage": True,
495        "ShowMarkerSearch": True,
496
497        "ShowSourceOutline": True,
498        "SourceOutlineWidth": 200,
499        "SourceOutlineStepSize": 50,
500        "SourceOutlineShowCoding": True,
501
502        "DocstringType": "ericdoc",
503        "DocstringAutoGenerate": True,
504
505        # All (most) lexers
506        "AllFoldCompact": True,
507
508        # Bash specifics
509        "BashFoldComment": True,
510
511        # CMake specifics
512        "CMakeFoldAtElse": False,
513
514        # C++ specifics
515        "CppCaseInsensitiveKeywords": False,
516        "CppFoldComment": True,
517        "CppFoldPreprocessor": False,
518        "CppFoldAtElse": False,
519        "CppIndentOpeningBrace": False,
520        "CppIndentClosingBrace": False,
521        "CppDollarsAllowed": True,
522        "CppStylePreprocessor": False,
523        "CppHighlightTripleQuotedStrings": False,
524        "CppHighlightHashQuotedStrings": False,
525        "CppHighlightBackQuotedStrings": False,
526        "CppHighlightEscapeSequences": False,
527        "CppVerbatimStringEscapeSequencesAllowed": False,
528
529        # CoffeeScript specifics
530        "CoffeScriptFoldComment": False,
531        "CoffeeScriptDollarsAllowed": True,
532        "CoffeeScriptStylePreprocessor": False,
533
534        # CSS specifics
535        "CssFoldComment": True,
536        "CssHssSupport": False,
537        "CssLessSupport": False,
538        "CssSassySupport": False,
539
540        # D specifics
541        "DFoldComment": True,
542        "DFoldAtElse": False,
543        "DIndentOpeningBrace": False,
544        "DIndentClosingBrace": False,
545
546        # Gettext specifics
547        "PoFoldComment": False,
548
549        # HTML specifics
550        "HtmlFoldPreprocessor": False,
551        "HtmlFoldScriptComments": False,
552        "HtmlFoldScriptHeredocs": False,
553        "HtmlCaseSensitiveTags": False,
554        "HtmlDjangoTemplates": False,
555        "HtmlMakoTemplates": False,
556
557        # JSON specifics
558        "JSONHightlightComments": True,
559        "JSONHighlightEscapeSequences": True,
560
561        # Pascal specifics
562        "PascalFoldComment": True,
563        "PascalFoldPreprocessor": False,
564        "PascalSmartHighlighting": True,
565
566        # Perl specifics
567        "PerlFoldComment": True,
568        "PerlFoldPackages": True,
569        "PerlFoldPODBlocks": True,
570        "PerlFoldAtElse": False,
571
572        # PostScript specifics
573        "PostScriptTokenize": False,
574        "PostScriptLevel": 3,
575        "PostScriptFoldAtElse": False,
576
577        # Povray specifics
578        "PovFoldComment": True,
579        "PovFoldDirectives": False,
580
581        # Properties specifics
582        "PropertiesInitialSpaces": True,
583
584        # Python specifics
585        "PythonBadIndentation": (
586            QsciLexerPython.IndentationWarning.Inconsistent
587        ),
588        "PythonFoldComment": True,
589        "PythonFoldString": True,
590        "PythonAutoIndent": True,
591        "PythonAllowV2Unicode": True,
592        "PythonAllowV3Binary": True,
593        "PythonAllowV3Bytes": True,
594        "PythonFoldQuotes": False,
595        "PythonStringsOverNewLineAllowed": False,
596        "PythonHighlightSubidentifier": True,
597
598        # Ruby specifics
599        "RubyFoldComment": False,
600
601        # SQL specifics
602        "SqlFoldComment": True,
603        "SqlBackslashEscapes": False,
604        "SqlDottedWords": False,
605        "SqlFoldAtElse": False,
606        "SqlFoldOnlyBegin": False,
607        "SqlHashComments": False,
608        "SqlQuotedIdentifiers": False,
609
610        # TCL specifics
611        "TclFoldComment": False,
612
613        # TeX specifics
614        "TexFoldComment": False,
615        "TexProcessComments": False,
616        "TexProcessIf": True,
617
618        # VHDL specifics
619        "VHDLFoldComment": True,
620        "VHDLFoldAtElse": True,
621        "VHDLFoldAtBegin": True,
622        "VHDLFoldAtParenthesis": True,
623
624        # XML specifics
625        "XMLStyleScripts": True,
626
627        # YAML specifics
628        "YAMLFoldComment": False,
629    }
630
631    if Globals.isWindowsPlatform():
632        editorDefaults["EOLMode"] = QsciScintilla.EolMode.EolWindows
633    else:
634        editorDefaults["EOLMode"] = QsciScintilla.EolMode.EolUnix
635
636    try:
637        # since QScintilla 2.7.0
638        editorDefaults["CallTipsPosition"] = (
639            QsciScintilla.CallTipsPosition.CallTipsBelowText
640        )
641    except AttributeError:
642        editorDefaults["CallTipsPosition"] = 0
643
644    editorColourDefaults = {
645        "CurrentMarker": QColor(Qt.GlobalColor.yellow),
646        "ErrorMarker": QColor(Qt.GlobalColor.red),
647        "MatchingBrace": QColor(Qt.GlobalColor.green),
648        "MatchingBraceBack": QColor(Qt.GlobalColor.white),
649        "NonmatchingBrace": QColor(Qt.GlobalColor.red),
650        "NonmatchingBraceBack": QColor(Qt.GlobalColor.white),
651        "CallTipsBackground": QColor(Qt.GlobalColor.white),
652        "CallTipsForeground": QColor("#7f7f7f"),
653        "CallTipsHighlight": QColor("#00007f"),
654        "CaretForeground": QColor(Qt.GlobalColor.black),
655        "CaretLineBackground": QColor(Qt.GlobalColor.white),
656        "Edge": QColor(Qt.GlobalColor.lightGray),
657        "SelectionBackground": QColor(Qt.GlobalColor.black),
658        "SelectionForeground": QColor(Qt.GlobalColor.white),
659        "SearchMarkers": QColor(Qt.GlobalColor.blue),
660        "MarginsBackground": QColor(Qt.GlobalColor.lightGray),
661        "MarginsForeground": QColor(Qt.GlobalColor.black),
662        "FoldmarginBackground": QColor("#e6e6e6"),
663        "FoldMarkersForeground": QColor(Qt.GlobalColor.white),
664        "FoldMarkersBackground": QColor(Qt.GlobalColor.black),
665        "SpellingMarkers": QColor(Qt.GlobalColor.red),
666        "AnnotationsWarningForeground": QColor("#606000"),
667        "AnnotationsWarningBackground": QColor("#ffffd0"),
668        "AnnotationsErrorForeground": QColor("#600000"),
669        "AnnotationsErrorBackground": QColor("#ffd0d0"),
670        "AnnotationsStyleForeground": QColor("#000060"),
671        "AnnotationsStyleBackground": QColor("#d0d0ff"),
672        "WhitespaceForeground": QColor(Qt.GlobalColor.darkGray),
673        "WhitespaceBackground": QColor(Qt.GlobalColor.white),
674        "OnlineChangeTraceMarkerUnsaved": QColor("#ff8888"),
675        "OnlineChangeTraceMarkerSaved": QColor("#88ff88"),
676        "IndentationGuidesBackground": QColor(Qt.GlobalColor.white),
677        "IndentationGuidesForeground": QColor(Qt.GlobalColor.black),
678        "HighlightMarker": QColor("#200000FF"),     # ARGB format
679        # colors for the marker map
680        "BookmarksMap": QColor("#f8c700"),
681        "ErrorsMap": QColor("#dd0000"),
682        "WarningsMap": QColor("#606000"),
683        "BreakpointsMap": QColor("#f55c07"),
684        "TasksMap": QColor("#2278f8"),
685        "CoverageMap": QColor("#ad3636"),
686        "ChangesMap": QColor("#00b000"),
687        "CurrentMap": QColor("#000000"),
688        "SearchMarkersMap": QColor(Qt.GlobalColor.blue),
689        "VcsConflictMarkersMap": QColor("#dd00dd"),
690        "MarkerMapBackground": QColor("#e7e7e7"),
691    }
692
693    editorOtherFontsDefaults = {
694        "MarginsFont": "Sans Serif,10,-1,5,50,0,0,0,0,0",
695        "DefaultFont": "Sans Serif,10,-1,5,50,0,0,0,0,0",
696        "MonospacedFont": "Courier,10,-1,5,50,0,0,0,0,0",
697    }
698
699    editorTypingDefaults = {
700        "Python/EnabledTypingAids": True,
701        "Python/InsertClosingBrace": True,
702        "Python/IndentBrace": False,
703        "Python/SkipBrace": True,
704        "Python/InsertQuote": True,
705        "Python/DedentElse": True,
706        "Python/DedentExcept": True,
707        "Python/InsertImport": True,
708        "Python/ImportBraceType": False,
709        "Python/InsertSelf": True,
710        "Python/InsertBlank": True,
711        "Python/ColonDetection": True,
712        "Python/DedentDef": False,
713
714        "Ruby/EnabledTypingAids": True,
715        "Ruby/InsertClosingBrace": True,
716        "Ruby/IndentBrace": True,
717        "Ruby/SkipBrace": True,
718        "Ruby/InsertQuote": True,
719        "Ruby/InsertBlank": True,
720        "Ruby/InsertHereDoc": True,
721        "Ruby/InsertInlineDoc": True,
722
723        "Yaml/EnabledTypingAids": True,
724        "Yaml/InsertClosingBrace": True,
725        "Yaml/SkipBrace": True,
726        "Yaml/InsertQuote": True,
727        "Yaml/AutoIndentation": True,
728        "Yaml/ColonDetection": True,
729        "Yaml/InsertBlankDash": True,
730        "Yaml/InsertBlankColon": True,
731        "Yaml/InsertBlankQuestion": True,
732        "Yaml/InsertBlankComma": True,
733    }
734
735    editorExporterDefaults = {
736        "HTML/WYSIWYG": True,
737        "HTML/Folding": False,
738        "HTML/OnlyStylesUsed": False,
739        "HTML/FullPathAsTitle": False,
740        "HTML/UseTabs": False,
741
742        "RTF/WYSIWYG": True,
743        "RTF/UseTabs": False,
744        "RTF/Font": "Courier New,10,-1,5,50,0,0,0,0,0",
745
746        "PDF/Magnification": 0,
747        "PDF/Font": "Helvetica",  # must be Courier, Helvetica or Times
748        "PDF/PageSize": "A4",         # must be A4 or Letter
749        "PDF/MarginLeft": 36,
750        "PDF/MarginRight": 36,
751        "PDF/MarginTop": 36,
752        "PDF/MarginBottom": 36,
753
754        "TeX/OnlyStylesUsed": False,
755        "TeX/FullPathAsTitle": False,
756
757        "ODT/WYSIWYG": True,
758        "ODT/OnlyStylesUsed": False,
759        "ODT/UseTabs": False,
760    }
761
762    # defaults for the printer settings
763    printerDefaults = {
764        "PrinterName": "",
765        "ColorMode": True,
766        "FirstPageFirst": True,
767        "Magnification": -3,
768        "Orientation": 0,
769        "PageSize": 0,
770        "HeaderFont": "Serif,10,-1,5,50,0,0,0,0,0",
771        "LeftMargin": 1.0,
772        "RightMargin": 1.0,
773        "TopMargin": 1.0,
774        "BottomMargin": 1.0,
775        "Resolution": 150,      # printer resolution in DPI
776    }
777
778    # defaults for the project settings
779    projectDefaults = {
780        "SearchNewFiles": False,
781        "SearchNewFilesRecursively": False,
782        "AutoIncludeNewFiles": False,
783        "AutoLoadSession": False,
784        "AutoSaveSession": False,
785        "SessionAllBreakpoints": False,
786        "TimestampFile": True,
787        "AutoCompileForms": False,
788        "AutoCompileResources": False,
789        "AutoExecuteMake": False,
790        "AutoLoadDbgProperties": False,
791        "AutoSaveDbgProperties": False,
792        "HideGeneratedForms": False,
793        "FollowEditor": True,
794        "FollowCursorLine": True,
795        "AutoPopulateItems": True,
796        "RecentNumber": 9,
797        "DeterminePyFromProject": True,
798        "TasksProjectAutoSave": True,
799        "TasksProjectRescanOnOpen": True,
800        "DebugClientsHistory": [],
801        "DebuggerInterpreterHistory": [],
802        "RestartShellForProject": True,
803        "BrowsersListHiddenFiles": False,
804    }
805
806    # defaults for the multi project settings
807    multiProjectDefaults = {
808        "OpenMasterAutomatically": True,
809        "TimestampFile": True,
810        "RecentNumber": 9,
811        "Workspace": "",
812    }
813
814    # defaults for the project browser flags settings
815    projectBrowserFlagsDefaults = {
816        "PyQt5": (
817            SourcesBrowserFlag |
818            FormsBrowserFlag |
819            ResourcesBrowserFlag |
820            TranslationsBrowserFlag |
821            InterfacesBrowserFlag |
822            OthersBrowserFlag |
823            ProtocolsBrowserFlag),
824        "PyQt5C": (
825            SourcesBrowserFlag |
826            ResourcesBrowserFlag |
827            TranslationsBrowserFlag |
828            InterfacesBrowserFlag |
829            OthersBrowserFlag |
830            ProtocolsBrowserFlag),
831        "PyQt6": (
832            SourcesBrowserFlag |
833            FormsBrowserFlag |
834            TranslationsBrowserFlag |
835            InterfacesBrowserFlag |
836            OthersBrowserFlag |
837            ProtocolsBrowserFlag),
838        "PyQt6C": (
839            SourcesBrowserFlag |
840            TranslationsBrowserFlag |
841            InterfacesBrowserFlag |
842            OthersBrowserFlag |
843            ProtocolsBrowserFlag),
844        "E6Plugin": (
845            SourcesBrowserFlag |
846            FormsBrowserFlag |
847            ResourcesBrowserFlag |
848            TranslationsBrowserFlag |
849            InterfacesBrowserFlag |
850            OthersBrowserFlag |
851            ProtocolsBrowserFlag),
852        "Console": (
853            SourcesBrowserFlag |
854            InterfacesBrowserFlag |
855            OthersBrowserFlag |
856            ProtocolsBrowserFlag),
857        "Other": (
858            SourcesBrowserFlag |
859            InterfacesBrowserFlag |
860            OthersBrowserFlag |
861            ProtocolsBrowserFlag),
862        "PySide2": (
863            SourcesBrowserFlag |
864            FormsBrowserFlag |
865            ResourcesBrowserFlag |
866            TranslationsBrowserFlag |
867            InterfacesBrowserFlag |
868            OthersBrowserFlag |
869            ProtocolsBrowserFlag),
870        "PySide2C": (
871            SourcesBrowserFlag |
872            ResourcesBrowserFlag |
873            TranslationsBrowserFlag |
874            InterfacesBrowserFlag |
875            OthersBrowserFlag |
876            ProtocolsBrowserFlag),
877        "PySide6": (
878            SourcesBrowserFlag |
879            FormsBrowserFlag |
880            ResourcesBrowserFlag |
881            TranslationsBrowserFlag |
882            InterfacesBrowserFlag |
883            OthersBrowserFlag |
884            ProtocolsBrowserFlag),
885        "PySide6C": (
886            SourcesBrowserFlag |
887            ResourcesBrowserFlag |
888            TranslationsBrowserFlag |
889            InterfacesBrowserFlag |
890            OthersBrowserFlag |
891            ProtocolsBrowserFlag),
892    }
893
894    # defaults for the project browser colour settings
895    projectBrowserColourDefaults = {
896        "Highlighted": QColor(Qt.GlobalColor.red),
897
898        "VcsAdded": QColor(Qt.GlobalColor.blue),
899        "VcsConflict": QColor(Qt.GlobalColor.red),
900        "VcsModified": QColor(Qt.GlobalColor.yellow),
901        "VcsReplaced": QColor(Qt.GlobalColor.cyan),
902        "VcsUpdate": QColor(Qt.GlobalColor.green),
903        "VcsRemoved": QColor(Qt.GlobalColor.magenta)
904    }
905
906    # defaults for the help settings
907    helpDefaults = {
908        "CustomViewer": "",
909        "PythonDocDir": "",
910        "Qt5DocDir": "",
911        "Qt6DocDir": "",
912        "PyQt5DocDir": "https://www.riverbankcomputing.com/static/Docs/PyQt5/",
913        "PyQt6DocDir": "",
914        "PySide2DocDir": "",
915        "PySide6DocDir": "",
916        "EricDocDir": "",
917    }
918
919    # defaults for the web browser settings
920    webBrowserDefaults = {
921        "SingleWebBrowserWindow": True,
922        "ShowToolbars": False,
923        "BookmarksToolBarVisible": True,
924        "MenuBarVisible": False,
925        "StatusBarVisible": True,
926        "SaveGeometry": True,
927        "WebBrowserState": QByteArray(),
928        "StartupBehavior": 2,       # show speed dial
929        # 0     open empty page
930        # 1     open home page
931        # 2     open speed dial
932        # 3     restore last session
933        # 4     ask user for session
934        "NewTabBehavior": 2,        # show speed dial
935        # 0     open empty page
936        # 1     open home page
937        # 2     open speed dial
938        "HomePage": "eric:home",
939        "LoadTabOnActivation": True,
940        "WarnOnMultipleClose": True,
941        "DefaultScheme": "https://",
942        "UserStyleSheet": "",
943        "ZoomValuesDB": "{}",       # empty JSON dictionary
944        "HistoryLimit": 30,
945        "WebSearchSuggestions": True,
946        "WebSearchEngine": "DuckDuckGo",
947        "WebSearchKeywords": [],    # array of two tuples (keyword,
948                                    # search engine name)
949        "SearchLanguage": QLocale().language(),
950        "ImageSearchEngine": "Google",
951        "RssFeeds": [],
952        "ShowPreview": True,
953        "DiskCacheEnabled": True,
954        "DiskCacheSize": 50,        # 50 MB
955        "SslExceptionsDB": "{}",    # empty JSON dictionary
956        "AlwaysRejectFaultyCertificates": False,
957        "DoNotTrack": False,
958        "RefererSendReferer": 2,        # send always
959        "RefererDefaultPolicy": 3,      # don't send a referer when downgrading
960        "RefererTrimmingPolicy": 0,     # send full URL (no trimming)
961        "SendRefererWhitelist": ["qt-apps.org", "kde-apps.org"],
962        "AcceptCookies": 2,         # CookieJar.AcceptOnlyFromSitesNavigatedTo
963        "KeepCookiesUntil": 0,      # CookieJar.KeepUntilExpire
964        "FilterTrackingCookies": True,
965        "SecureUrlColor": QColor(184, 248, 169),
966        "InsecureUrlColor": QColor(248, 227, 169),
967        "MaliciousUrlColor": QColor(255, 132, 140),
968        "PrivateModeUrlColor": QColor(220, 220, 220),
969        "UserAgent": "",
970        "AcceptQuotaRequest": 2,            # yes/no/ask (0, 1, 2)
971        "AcceptProtocolHandlerRequest": 2,  # yes/no/ask (0, 1, 2)
972        # Auto Scroller
973        "AutoScrollEnabled": True,
974        "AutoScrollDivider": 8.0,
975        # Tab Manager
976        "TabManagerGroupByType": 0,     # TabManagerWidget.GroupByWindow
977        # Grease Monkey
978        "GreaseMonkeyDisabledScripts": [],
979        # Downloads
980        "DownloadManagerRemovePolicy": 0,      # never delete downloads
981        "DownloadManagerSize": QSize(450, 600),
982        "DownloadManagerPosition": QPoint(),
983        "DownloadManagerDownloads": [],
984        "DownloadManagerAutoOpen": False,
985        "DownloadManagerAutoClose": False,
986        # Spell Checking
987        "SpellCheckEnabled": False,
988        "SpellCheckLanguages": [],
989        "SpellCheckDictionariesUrl":
990        ("https://eric-ide.python-projects.org/qwebengine_dictionaries/"
991         "dictionaries.xml"),
992        # Sync
993        "SyncEnabled": False,
994        "SyncBookmarks": True,
995        "SyncHistory": True,
996        "SyncPasswords": False,
997        "SyncUserAgents": True,
998        "SyncSpeedDial": True,
999        "SyncEncryptData": False,
1000        "SyncEncryptionKey": "",
1001        "SyncEncryptionKeyLength": 32,      # 16, 24 or 32
1002        "SyncEncryptPasswordsOnly": False,
1003        "SyncType": 0,
1004        "SyncFtpServer": "",
1005        "SyncFtpUser": "",
1006        "SyncFtpPassword": "",
1007        "SyncFtpPath": "",
1008        "SyncFtpPort": 21,
1009        "SyncFtpIdleTimeout": 30,
1010        "SyncDirectoryPath": "",
1011        # AdBlock
1012        "AdBlockEnabled": False,
1013        "AdBlockSubscriptions": [],
1014        "AdBlockUpdatePeriod": 1,
1015        "AdBlockExceptions": [],
1016        "AdBlockUseLimitedEasyList": True,
1017        # PIM:
1018        "PimFullName": "",
1019        "PimFirstName": "",
1020        "PimLastName": "",
1021        "PimEmail": "",
1022        "PimPhone": "",
1023        "PimMobile": "",
1024        "PimAddress": "",
1025        "PimCity": "",
1026        "PimZip": "",
1027        "PimState": "",
1028        "PimCountry": "",
1029        "PimHomePage": "",
1030        "PimSpecial1": "",
1031        "PimSpecial2": "",
1032        "PimSpecial3": "",
1033        "PimSpecial4": "",
1034        # VirusTotal:
1035        "VirusTotalEnabled": False,
1036        "VirusTotalServiceKey": "",
1037        "VirusTotalSecure": True,
1038        # Sessions
1039        "SessionAutoSave": True,
1040        "SessionAutoSaveInterval": 15,  # interval in seconds
1041        "SessionLastActivePath": "",
1042        # Google Safe Browsing
1043        "SafeBrowsingEnabled": True,
1044        "SafeBrowsingApiKey": "",       # API key
1045        "SafeBrowsingFilterPlatform": True,
1046        "SafeBrowsingAutoUpdate": False,
1047        "SafeBrowsingUpdateDateTime": QDateTime(),
1048        "SafeBrowsingUseLookupApi": False,
1049    }
1050    if QWebEngineSettings:
1051        webBrowserDefaults["HelpViewerType"] = 1      # eric browser
1052    else:
1053        webBrowserDefaults["HelpViewerType"] = 2      # Qt Assistant
1054
1055    @classmethod
1056    def initWebEngineSettingsDefaults(cls):
1057        """
1058        Class method to initialize the web engine settings related defaults.
1059        """
1060        if QWebEngineSettings is None:
1061            return
1062
1063        webEngineSettings = QWebEngineSettings.defaultSettings()
1064        cls.webBrowserDefaults.update({
1065            "StandardFontFamily": webEngineSettings.fontFamily(
1066                QWebEngineSettings.FontFamily.StandardFont),
1067            "FixedFontFamily": webEngineSettings.fontFamily(
1068                QWebEngineSettings.FontFamily.FixedFont),
1069            "SerifFontFamily": webEngineSettings.fontFamily(
1070                QWebEngineSettings.FontFamily.StandardFont),
1071            "SansSerifFontFamily": webEngineSettings.fontFamily(
1072                QWebEngineSettings.FontFamily.SansSerifFont),
1073            "CursiveFontFamily": webEngineSettings.fontFamily(
1074                QWebEngineSettings.FontFamily.CursiveFont),
1075            "FantasyFontFamily": webEngineSettings.fontFamily(
1076                QWebEngineSettings.FontFamily.FantasyFont),
1077            "DefaultFontSize": webEngineSettings.fontSize(
1078                QWebEngineSettings.FontSize.DefaultFontSize),
1079            "DefaultFixedFontSize": webEngineSettings.fontSize(
1080                QWebEngineSettings.FontSize.DefaultFixedFontSize),
1081            "MinimumFontSize": webEngineSettings.fontSize(
1082                QWebEngineSettings.FontSize.MinimumFontSize),
1083            "MinimumLogicalFontSize": webEngineSettings.fontSize(
1084                QWebEngineSettings.FontSize.MinimumLogicalFontSize),
1085            "AutoLoadImages": webEngineSettings.testAttribute(
1086                QWebEngineSettings.WebAttribute.AutoLoadImages),
1087            "JavaScriptEnabled": webEngineSettings.testAttribute(
1088                QWebEngineSettings.WebAttribute.JavascriptEnabled),
1089            "JavaScriptCanOpenWindows": webEngineSettings.testAttribute(
1090                QWebEngineSettings.WebAttribute.JavascriptCanOpenWindows),
1091            "JavaScriptCanAccessClipboard": webEngineSettings.testAttribute(
1092                QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard),
1093            "PluginsEnabled": webEngineSettings.testAttribute(
1094                QWebEngineSettings.WebAttribute.PluginsEnabled),
1095            "LocalStorageEnabled": webEngineSettings.testAttribute(
1096                QWebEngineSettings.WebAttribute.LocalStorageEnabled),
1097            "DefaultTextEncoding": webEngineSettings.defaultTextEncoding(),
1098            "SpatialNavigationEnabled": webEngineSettings.testAttribute(
1099                QWebEngineSettings.WebAttribute.SpatialNavigationEnabled),
1100            "LinksIncludedInFocusChain": webEngineSettings.testAttribute(
1101                QWebEngineSettings.WebAttribute.LinksIncludedInFocusChain),
1102            "LocalContentCanAccessRemoteUrls": webEngineSettings.testAttribute(
1103                QWebEngineSettings.WebAttribute
1104                .LocalContentCanAccessRemoteUrls),
1105            "LocalContentCanAccessFileUrls": webEngineSettings.testAttribute(
1106                QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls),
1107            "XSSAuditingEnabled": webEngineSettings.testAttribute(
1108                QWebEngineSettings.WebAttribute.XSSAuditingEnabled),
1109            "ScrollAnimatorEnabled": webEngineSettings.testAttribute(
1110                QWebEngineSettings.WebAttribute.ScrollAnimatorEnabled),
1111            "ErrorPageEnabled": webEngineSettings.testAttribute(
1112                QWebEngineSettings.WebAttribute.ErrorPageEnabled),
1113            "FullScreenSupportEnabled": webEngineSettings.testAttribute(
1114                QWebEngineSettings.WebAttribute.FullScreenSupportEnabled),
1115            "PictographFontFamily": webEngineSettings.fontFamily(
1116                QWebEngineSettings.FontFamily.PictographFont),
1117            "ScreenCaptureEnabled": webEngineSettings.testAttribute(
1118                QWebEngineSettings.WebAttribute.ScreenCaptureEnabled),
1119            "WebGLEnabled": webEngineSettings.testAttribute(
1120                QWebEngineSettings.WebAttribute.WebGLEnabled),
1121            "FocusOnNavigationEnabled": webEngineSettings.testAttribute(
1122                QWebEngineSettings.WebAttribute.FocusOnNavigationEnabled),
1123            "PrintElementBackgrounds": webEngineSettings.testAttribute(
1124                QWebEngineSettings.WebAttribute.PrintElementBackgrounds),
1125            "AllowRunningInsecureContent": webEngineSettings.testAttribute(
1126                QWebEngineSettings.WebAttribute.AllowRunningInsecureContent),
1127            "AllowGeolocationOnInsecureOrigins":
1128                webEngineSettings.testAttribute(
1129                    QWebEngineSettings.WebAttribute
1130                    .AllowGeolocationOnInsecureOrigins),
1131            "AllowWindowActivationFromJavaScript":
1132                webEngineSettings.testAttribute(
1133                    QWebEngineSettings.WebAttribute
1134                    .AllowWindowActivationFromJavaScript),
1135            "ShowScrollBars": webEngineSettings.testAttribute(
1136                QWebEngineSettings.WebAttribute.ShowScrollBars),
1137            "PlaybackRequiresUserGesture":
1138                webEngineSettings.testAttribute(
1139                    QWebEngineSettings.WebAttribute
1140                    .PlaybackRequiresUserGesture),
1141            "JavaScriptCanPaste":
1142                webEngineSettings.testAttribute(
1143                    QWebEngineSettings.WebAttribute.JavascriptCanPaste),
1144            "WebRTCPublicInterfacesOnly":
1145                webEngineSettings.testAttribute(
1146                    QWebEngineSettings.WebAttribute
1147                    .WebRTCPublicInterfacesOnly),
1148            "DnsPrefetchEnabled":
1149                webEngineSettings.testAttribute(
1150                    QWebEngineSettings.WebAttribute.DnsPrefetchEnabled),
1151        })
1152        with contextlib.suppress(AttributeError):
1153            # Qt 5.13
1154            cls.webBrowserDefaults.update({
1155                "PdfViewerEnabled":
1156                    webEngineSettings.testAttribute(
1157                        QWebEngineSettings.WebAttribute.PdfViewerEnabled),
1158            })
1159
1160        cls.webEngineSettingsIntitialized = True
1161
1162    webEngineSettingsIntitialized = False
1163
1164    # defaults for system settings
1165    sysDefaults = {
1166        "StringEncoding": "utf-8",
1167        "IOEncoding": "utf-8",
1168    }
1169
1170    # defaults for the shell settings
1171    shellDefaults = {
1172        "LinenoMargin": True,
1173        "AutoCompletionEnabled": True,
1174        "CallTipsEnabled": True,
1175        "WrapEnabled": True,
1176        "MaxHistoryEntries": 100,
1177        "HistoryStyle": ShellHistoryStyle.LINUXSTYLE,
1178        "HistoryWrap": False,
1179        "HistoryNavigateByCursor": False,
1180        "SyntaxHighlightingEnabled": True,
1181        "ShowStdOutErr": True,
1182        "UseMonospacedFont": False,
1183        "MonospacedFont": "Courier,10,-1,5,50,0,0,0,0,0",
1184        "MarginsFont": "Sans Serif,10,-1,5,50,0,0,0,0,0",
1185        "LastVirtualEnvironment": "",
1186        "StartWithMostRecentlyUsedEnvironment": True,
1187    }
1188
1189    # defaults for Qt related stuff
1190    qtDefaults = {
1191        "Qt5TranslationsDir": "",
1192        "QtToolsDir": "",
1193        "QtToolsPrefix": "",
1194        "QtToolsPostfix": "",
1195        "PyuicIndent": 4,
1196        "PyuicFromImports": False,
1197        "PyuicExecute": True,
1198        "PyQtVenvName": "",
1199        "PyQtToolsDir": "",
1200        "Pyuic6Indent": 4,
1201        "Pyuic6Execute": True,
1202        "PyQt6VenvName": "",
1203        "PyQt6ToolsDir": "",
1204        "PySide2FromImports": False,
1205        "PySide2VenvName": "",
1206        "PySide2ToolsDir": "",
1207        "PySide6FromImports": False,
1208        "PySide6VenvName": "",
1209        "PySide6ToolsDir": "",
1210    }
1211
1212    # defaults for corba related stuff
1213    corbaDefaults = {
1214        "omniidl": ""
1215    }
1216
1217    # defaults for protobuf related stuff
1218    protobufDefaults = {
1219        "protoc": "",
1220        "grpcPython": "",
1221    }
1222
1223    # defaults for user related stuff
1224    userDefaults = {
1225        "Email": "",
1226        "MailServer": "",
1227        "Signature": "",
1228        "MailServerAuthentication": False,
1229        "MailServerUser": "",
1230        "MailServerPassword": "",
1231        "MailServerEncryption": "No",   # valid values: No, SSL, TLS
1232        "MailServerPort": 25,
1233        "UseSystemEmailClient": False,
1234        "UseGoogleMailOAuth2": False,
1235        "MasterPassword": "",           # stores the password hash
1236        "UseMasterPassword": False,
1237        "SavePasswords": False,
1238    }
1239
1240    # defaults for vcs related stuff
1241    vcsDefaults = {
1242        "AutoClose": False,
1243        "AutoSaveFiles": True,
1244        "AutoSaveProject": True,
1245        "AutoUpdate": False,
1246        "StatusMonitorInterval": 30,
1247        "MonitorLocalStatus": False,
1248        "ShowVcsToolbar": True,
1249    }
1250
1251    # defaults for tasks related stuff
1252    tasksDefaults = {
1253        "TasksFixmeMarkers": "FIX" + "ME:",
1254        "TasksWarningMarkers": "WARN" + "ING:",
1255        "TasksTodoMarkers": "TO" + "DO:",
1256        "TasksNoteMarkers": "NO" + "TE:",
1257        "TasksTestMarkers": "TE" + "ST:",
1258        "TasksDocuMarkers": "DO" + "CU:",
1259        # needed to keep it from being recognized as a task
1260        "TasksFixmeColor": QColor("#FFA0A0"),
1261        "TasksWarningColor": QColor("#FFFFA0"),
1262        "TasksTodoColor": QColor("#A0FFA0"),
1263        "TasksNoteColor": QColor("#A0A0FF"),
1264        "TasksTestColor": QColor("#FFD000"),
1265        "TasksDocuColor": QColor("#FFA0FF"),
1266        "ClearOnFileClose": True,
1267    }
1268
1269    # defaults for templates related stuff
1270    templatesDefaults = {
1271        "AutoOpenGroups": True,
1272        "SingleDialog": False,
1273        "ShowTooltip": False,
1274        "SeparatorChar": "$",
1275        "EditorFont": "Monospace,9,-1,5,50,0,0,0,0,0",
1276    }
1277
1278    # defaults for plugin manager related stuff
1279    pluginManagerDefaults = {
1280        "ActivateExternal": True,
1281        "DownloadPath": "",
1282        "UpdatesCheckInterval": 3,
1283        # 0 = off
1284        # 1 = daily
1285        # 2 = weekly
1286        # 3 = monthly
1287        # 4 = always
1288        "CheckInstalledOnly": True,
1289        # list of plug-ins not to shown in the repo dialog
1290        "HiddenPlugins": [],
1291        # parameters for housekeeping
1292        "KeepGenerations": 2,
1293        "KeepHidden": False,
1294        "StartupCleanup": True,
1295    }
1296
1297    # defaults for the printer settings
1298    graphicsDefaults = {
1299        "Font": "SansSerif,10,-1,5,50,0,0,0,0,0",
1300        "DrawingMode": "automatic",
1301        # automatic - determine mode depending upon desktop scheme
1302        # black_white - black items on white background
1303        # white_black - white items on black background
1304    }
1305
1306    # defaults for the icon editor
1307    iconEditorDefaults = {
1308        "IconEditorState": QByteArray(),
1309    }
1310
1311    # defaults for pyflakes
1312    pyflakesDefaults = {
1313        "IncludeInSyntaxCheck": True,
1314        "IgnoreStarImportWarnings": True,
1315    }
1316
1317    # defaults for tray starter
1318    trayStarterDefaults = {
1319        "TrayStarterIcon": "erict",
1320        # valid values are: erict, erict-hc,
1321        #                   erict-bw, erict-bwi
1322    }
1323
1324    # defaults for geometry
1325    geometryDefaults = {
1326        "HelpViewerGeometry": QByteArray(),
1327        "HelpInspectorGeometry": QByteArray(),
1328        "WebBrowserGeometry": QByteArray(),
1329        "IconEditorGeometry": QByteArray(),
1330        "HexEditorGeometry": QByteArray(),
1331        "MainGeometry": QByteArray(),
1332        "MainMaximized": False,
1333        "WebInspectorGeometry": QByteArray(),
1334    }
1335
1336    # if true, revert layouts to factory defaults
1337    resetLayout = False
1338
1339    # defaults for IRC
1340    ircDefaults = {
1341        "ShowTimestamps": True,
1342        "TimestampIncludeDate": False,
1343        "TimeFormat": "hh:mm",
1344        "DateFormat": "yyyy-MM-dd",
1345
1346        "NetworkMessageColour": "#000055",
1347        "ServerMessageColour": "#91640A",
1348        "ErrorMessageColour": "#FF0000",
1349        "TimestampColour": "#709070",
1350        "HyperlinkColour": "#0000FF",
1351        "ChannelMessageColour": "#000000",
1352        "OwnNickColour": "#000000",
1353        "NickColour": "#18B33C",
1354        "JoinChannelColour": "#72D672",
1355        "LeaveChannelColour": "#B00000",
1356        "ChannelInfoColour": "#9E54B3",
1357
1358        "EnableIrcColours": True,
1359        "IrcColor0": "#FFFF00",
1360        "IrcColor1": "#000000",
1361        "IrcColor2": "#000080",
1362        "IrcColor3": "#008000",
1363        "IrcColor4": "#FF0000",
1364        "IrcColor5": "#A52A2A",
1365        "IrcColor6": "#800080",
1366        "IrcColor7": "#FF8000",
1367        "IrcColor8": "#808000",
1368        "IrcColor9": "#00FF00",
1369        "IrcColor10": "#008080",
1370        "IrcColor11": "#00FFFF",
1371        "IrcColor12": "#0000FF",
1372        "IrcColor13": "#FFC0CB",
1373        "IrcColor14": "#A0A0A0",
1374        "IrcColor15": "#C0C0C0",
1375
1376        "ShowNotifications": True,
1377        "NotifyJoinPart": True,
1378        "NotifyMessage": False,
1379        "NotifyNick": False,
1380
1381        "AutoUserInfoLookup": True,
1382        "AutoUserInfoMax": 200,
1383        "AutoUserInfoInterval": 90,
1384
1385        "MarkPositionWhenHidden": True,
1386        "MarkerLineForegroundColour": "#000000",    # Black on
1387        "MarkerLineBackgroundColour": "#ffff00",    # Yellow
1388
1389        "AskOnShutdown": True,
1390    }
1391
1392    # defaults for Hex Editor
1393    hexEditorDefaults = {
1394        "HexEditorState": QByteArray(),
1395        "AddressAreaWidth": 4,
1396        "ShowAddressArea": True,
1397        "ShowAsciiArea": True,
1398        "OpenInOverwriteMode": True,
1399        "OpenReadOnly": False,
1400        "HighlightChanges": True,
1401        "HighlightingBackGround": QColor(0xff, 0xff, 0x99, 0xff),
1402        "HighlightingForeGround": QColor(Qt.GlobalColor.black),
1403        "SelectionBackGround": QColor("#308cc6"),
1404        "SelectionForeGround": QColor(Qt.GlobalColor.white),
1405        "AddressAreaBackGround": QColor("#efedec"),
1406        "AddressAreaForeGround": QColor(Qt.GlobalColor.black),
1407        "RecentNumber": 9,
1408    }
1409    if Globals.isWindowsPlatform():
1410        hexEditorDefaults["Font"] = "Courier,10,-1,5,50,0,0,0,0,0"
1411    else:
1412        hexEditorDefaults["Font"] = "Monospace,10,-1,5,50,0,0,0,0,0"
1413
1414    # defaults for Diff colors
1415    diffColourDefaults = {
1416        "TextColor": QColor(0, 0, 0),
1417        "AddedColor": QColor(190, 237, 190),
1418        "RemovedColor": QColor(237, 190, 190),
1419        "ReplacedColor": QColor(190, 190, 237),
1420        "ContextColor": QColor(255, 220, 168),
1421        "HeaderColor": QColor(237, 237, 190),
1422        "BadWhitespaceColor": QColor(255, 0, 0, 192),
1423    }
1424
1425    # defaults for Code Documentation Viewer
1426    docuViewerDefaults = {
1427        "ShowInfoAsRichText": False,
1428        "Provider": "disabled",
1429        "ShowInfoOnOpenParenthesis": True,
1430    }
1431
1432    # defaults for conda
1433    condaDefaults = {
1434        "CondaExecutable": "",
1435    }
1436
1437    # defaults for pip
1438    pipDefaults = {
1439        "PipSearchIndex": "",               # used by the search command
1440        "ExcludeCondaEnvironments": True,
1441        # don't show conda environments in selector
1442    }
1443
1444    # defaults for MicroPython
1445    microPythonDefaults = {
1446        "MpyWorkspace": "",
1447        "SerialTimeout": 2000,          # timeout in milliseconds
1448        "ReplLineWrap": True,           # wrap the REPL lines
1449        "SyncTimeAfterConnect": True,
1450        "ShowHiddenLocal": True,
1451        "ShowHiddenDevice": True,
1452        "ChartColorTheme": -1,          # -1 = automatic,
1453                                        # QChart.ChartTheme otherwise
1454        "MpyCrossCompiler": "",         # path of the mpy-cross compiler
1455        "DfuUtilPath": "",              # path of the dfu-util flashing tool
1456        "IgnoredUnknownDevices": "[]",  # empty list encoded as JSON
1457        "ManualDevices": "[]",          # empty list encoded as JSON
1458
1459        # MicroPython URLs
1460        "MicroPythonDocuUrl":
1461            "https://docs.micropython.org/en/latest/",
1462        "MicroPythonFirmwareUrl":
1463            "http://micropython.org/download/",
1464
1465        # CircuitPython URLS
1466        "CircuitPythonDocuUrl":
1467            "https://circuitpython.readthedocs.io/en/latest/",
1468        "CircuitPythonFirmwareUrl":
1469            "https://circuitpython.org/downloads/",
1470        "CircuitPythonLibrariesUrl":
1471            "https://circuitpython.org/libraries",
1472
1473        # BBC micro:bit URLs
1474        "MicrobitDocuUrl":
1475            "https://microbit-micropython.readthedocs.io/en/latest/",
1476        "MicrobitFirmwareUrl":
1477            "https://microbit.org/guide/firmware/",
1478        "MicrobitMicroPythonUrl":
1479            "https://github.com/bbcmicrobit/micropython/releases/",
1480        "MicrobitV2MicroPythonUrl":
1481            "https://github.com/microbit-foundation/micropython-microbit-v2/"
1482            "releases/",
1483
1484        # calliope mini URLS
1485        "CalliopeDocuUrl":
1486            "https://github.com/calliope-mini/calliope-mini-micropython/",
1487        "CalliopeDAPLinkUrl":
1488            "https://github.com/calliope-mini/production-test/releases/",
1489        "CalliopeMicroPythonUrl":
1490            "https://github.com/calliope-mini/calliope-mini-micropython/",
1491    }
1492    if Globals.isWindowsPlatform():
1493        microPythonDefaults["ColorScheme"] = "Windows 10"
1494    elif Globals.isMacPlatform():
1495        microPythonDefaults["ColorScheme"] = "xterm"
1496    else:
1497        microPythonDefaults["ColorScheme"] = "Ubuntu"
1498
1499    # defaults for Python specific settings
1500    pythonDefaults = {
1501        "ASTViewerErrorColor": QColor(Qt.GlobalColor.darkRed),
1502
1503        "DisViewerErrorColor": QColor(Qt.GlobalColor.darkRed),
1504        "DisViewerCurrentColor": QColor(Qt.GlobalColor.darkMagenta),
1505        "DisViewerLabeledColor": QColor(Qt.GlobalColor.darkGreen),
1506        "DisViewerExpandCodeInfoDetails": False,
1507    }
1508
1509
1510def readToolGroups(prefClass=Prefs):
1511    """
1512    Module function to read the tool groups configuration.
1513
1514    @param prefClass preferences class used as the storage area
1515    @return list of tuples defing the tool groups
1516    """
1517    toolGroups = []
1518    groups = int(prefClass.settings.value("Toolgroups/Groups", 0))
1519    for groupIndex in range(groups):
1520        groupName = prefClass.settings.value(
1521            "Toolgroups/{0:02d}/Name".format(groupIndex))
1522        group = [groupName, []]
1523        items = int(prefClass.settings.value(
1524            "Toolgroups/{0:02d}/Items".format(groupIndex), 0))
1525        for ind in range(items):
1526            menutext = prefClass.settings.value(
1527                "Toolgroups/{0:02d}/{1:02d}/Menutext".format(groupIndex, ind))
1528            icon = prefClass.settings.value(
1529                "Toolgroups/{0:02d}/{1:02d}/Icon".format(groupIndex, ind))
1530            executable = prefClass.settings.value(
1531                "Toolgroups/{0:02d}/{1:02d}/Executable".format(
1532                    groupIndex, ind))
1533            arguments = prefClass.settings.value(
1534                "Toolgroups/{0:02d}/{1:02d}/Arguments".format(groupIndex, ind))
1535            redirect = prefClass.settings.value(
1536                "Toolgroups/{0:02d}/{1:02d}/Redirect".format(groupIndex, ind))
1537
1538            if menutext:
1539                if menutext == '--':
1540                    tool = {
1541                        'menutext': '--',
1542                        'icon': '',
1543                        'executable': '',
1544                        'arguments': '',
1545                        'redirect': 'no',
1546                    }
1547                    group[1].append(tool)
1548                elif executable:
1549                    tool = {
1550                        'menutext': menutext,
1551                        'icon': icon,
1552                        'executable': executable,
1553                        'arguments': arguments,
1554                        'redirect': redirect,
1555                    }
1556                    group[1].append(tool)
1557        toolGroups.append(group)
1558    currentGroup = int(
1559        prefClass.settings.value("Toolgroups/Current Group", -1))
1560    return toolGroups, currentGroup
1561
1562
1563def saveToolGroups(toolGroups, currentGroup, prefClass=Prefs):
1564    """
1565    Module function to write the tool groups configuration.
1566
1567    @param toolGroups reference to the list of tool groups
1568    @param currentGroup index of the currently selected tool group (integer)
1569    @param prefClass preferences class used as the storage area
1570    """
1571    # first step, remove all tool group entries
1572    prefClass.settings.remove("Toolgroups")
1573
1574    # second step, write the tool group entries
1575    prefClass.settings.setValue("Toolgroups/Groups", len(toolGroups))
1576    for groupIndex, group in enumerate(toolGroups):
1577        prefClass.settings.setValue(
1578            "Toolgroups/{0:02d}/Name".format(groupIndex), group[0])
1579        prefClass.settings.setValue(
1580            "Toolgroups/{0:02d}/Items".format(groupIndex), len(group[1]))
1581        for ind, tool in enumerate(group[1]):
1582            prefClass.settings.setValue(
1583                "Toolgroups/{0:02d}/{1:02d}/Menutext".format(groupIndex, ind),
1584                tool['menutext'])
1585            prefClass.settings.setValue(
1586                "Toolgroups/{0:02d}/{1:02d}/Icon".format(groupIndex, ind),
1587                tool['icon'])
1588            prefClass.settings.setValue(
1589                "Toolgroups/{0:02d}/{1:02d}/Executable".format(
1590                    groupIndex, ind),
1591                tool['executable'])
1592            prefClass.settings.setValue(
1593                "Toolgroups/{0:02d}/{1:02d}/Arguments".format(groupIndex, ind),
1594                tool['arguments'])
1595            prefClass.settings.setValue(
1596                "Toolgroups/{0:02d}/{1:02d}/Redirect".format(groupIndex, ind),
1597                tool['redirect'])
1598    prefClass.settings.setValue("Toolgroups/Current Group", currentGroup)
1599
1600
1601def initPreferences():
1602    """
1603    Module function to initialize the central configuration store.
1604    """
1605    from E5Gui.E5Application import e5App
1606    Prefs.settings = QSettings(
1607        QSettings.Format.IniFormat, QSettings.Scope.UserScope,
1608        Globals.settingsNameOrganization, Globals.settingsNameGlobal,
1609        e5App())
1610    if not Globals.isWindowsPlatform():
1611        hp = QDir.homePath()
1612        dn = QDir(hp)
1613        dn.mkdir(".eric6")
1614    QCoreApplication.setOrganizationName(Globals.settingsNameOrganization)
1615    QCoreApplication.setApplicationName(Globals.settingsNameGlobal)
1616    with contextlib.suppress(AttributeError):
1617        Prefs.settings.setAtomicSyncRequired(False)
1618        # backward compatibility for Qt < 5.10
1619
1620    Prefs.settings.value("UI/SingleApplicationMode")
1621
1622
1623def syncPreferences(prefClass=Prefs):
1624    """
1625    Module function to sync the preferences to disk.
1626
1627    In addition to syncing, the central configuration store is reinitialized
1628    as well.
1629
1630    @param prefClass preferences class used as the storage area
1631    """
1632    prefClass.settings.setValue("General/Configured", True)
1633    prefClass.settings.sync()
1634
1635
1636def exportPreferences(prefClass=Prefs):
1637    """
1638    Module function to export the current preferences.
1639
1640    @param prefClass preferences class used as the storage area
1641    """
1642    filename, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
1643        None,
1644        QCoreApplication.translate("Preferences", "Export Preferences"),
1645        "",
1646        QCoreApplication.translate(
1647            "Preferences",
1648            "Properties File (*.ini);;All Files (*)"),
1649        None,
1650        E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
1651    if filename:
1652        ext = QFileInfo(filename).suffix()
1653        if not ext:
1654            ex = selectedFilter.split("(*")[1].split(")")[0]
1655            if ex:
1656                filename += ex
1657        settingsFile = prefClass.settings.fileName()
1658        prefClass.settings = None
1659        shutil.copy(settingsFile, filename)
1660        initPreferences()
1661
1662
1663def importPreferences(prefClass=Prefs):
1664    """
1665    Module function to import preferences from a file previously saved by
1666    the export function.
1667
1668    @param prefClass preferences class used as the storage area
1669    """
1670    filename = E5FileDialog.getOpenFileName(
1671        None,
1672        QCoreApplication.translate("Preferences", "Import Preferences"),
1673        "",
1674        QCoreApplication.translate(
1675            "Preferences",
1676            "Properties File (*.ini);;All Files (*)"))
1677    if filename:
1678        settingsFile = prefClass.settings.fileName()
1679        shutil.copy(filename, settingsFile)
1680        initPreferences()
1681
1682
1683def isConfigured(prefClass=Prefs):
1684    """
1685    Module function to check, if the the application has been configured.
1686
1687    @param prefClass preferences class used as the storage area
1688    @return flag indicating the configured status (boolean)
1689    """
1690    return toBool(prefClass.settings.value("General/Configured", False))
1691
1692
1693def initRecentSettings():
1694    """
1695    Module function to initialize the central configuration store for recently
1696    opened files and projects.
1697
1698    This function is called once upon import of the module.
1699    """
1700    Prefs.rsettings = QSettings(
1701        QSettings.Format.IniFormat, QSettings.Scope.UserScope,
1702        Globals.settingsNameOrganization, Globals.settingsNameRecent)
1703
1704
1705def getVarFilters(prefClass=Prefs):
1706    """
1707    Module function to retrieve the variables filter settings.
1708
1709    @param prefClass preferences class used as the storage area
1710    @return a tuple defining the variables filter
1711    """
1712    localsFilter = ast.literal_eval(prefClass.settings.value(
1713        "Variables/LocalsFilter", prefClass.varDefaults["LocalsFilter"]))
1714    globalsFilter = ast.literal_eval(prefClass.settings.value(
1715        "Variables/GlobalsFilter", prefClass.varDefaults["GlobalsFilter"]))
1716    return (localsFilter, globalsFilter)
1717
1718
1719def setVarFilters(filters, prefClass=Prefs):
1720    """
1721    Module function to store the variables filter settings.
1722
1723    @param filters variable filters to set
1724    @param prefClass preferences class used as the storage area
1725    """
1726    prefClass.settings.setValue("Variables/LocalsFilter", str(filters[0]))
1727    prefClass.settings.setValue("Variables/GlobalsFilter", str(filters[1]))
1728
1729
1730def getDebugger(key, prefClass=Prefs):
1731    """
1732    Module function to retrieve the debugger settings.
1733
1734    @param key the key of the value to get
1735    @param prefClass preferences class used as the storage area
1736    @return the requested debugger setting
1737    """
1738    if key in ["RemoteDbgEnabled", "PassiveDbgEnabled",
1739               "AutomaticReset", "DebugEnvironmentReplace",
1740               "PythonRedirect", "PythonNoEncoding",
1741               "Python3Redirect", "Python3NoEncoding",
1742               "RubyRedirect",
1743               "ConsoleDbgEnabled", "PathTranslation",
1744               "Autosave", "ThreeStateBreakPoints",
1745               "BreakAlways", "AutoViewSourceCode",
1746               "ShowExceptionInShell", "MultiProcessEnabled",
1747               ]:
1748        return toBool(prefClass.settings.value(
1749            "Debugger/" + key, prefClass.debuggerDefaults[key]))
1750    elif key in ["PassiveDbgPort", "MaxVariableSize", "RecentNumber"]:
1751        return int(
1752            prefClass.settings.value(
1753                "Debugger/" + key, prefClass.debuggerDefaults[key]))
1754    elif key in ["AllowedHosts"]:
1755        return toList(
1756            prefClass.settings.value(
1757                "Debugger/" + key, prefClass.debuggerDefaults[key]))
1758    elif key in ["PythonInterpreter", "Python3Interpreter"]:
1759        # This code is here to ensure backward compatibility.
1760        # Keep "PythonInterpreter" for backward compatibility.
1761        newKey = "Python3VirtualEnv"
1762        venvName = prefClass.settings.value(
1763            "Debugger/" + newKey, prefClass.debuggerDefaults[newKey])
1764        if venvName:
1765            try:
1766                from E5Gui.E5Application import e5App
1767                virtualenvManager = e5App().getObject("VirtualEnvManager")
1768            except KeyError:
1769                from VirtualEnv.VirtualenvManager import VirtualenvManager
1770                virtualenvManager = VirtualenvManager()
1771            interpreter = virtualenvManager.getVirtualenvInterpreter(venvName)
1772        else:
1773            interpreter = ""
1774        if not interpreter:
1775            return sys.executable
1776        return interpreter
1777    elif key == "DebugClientType3":
1778        debugClientType = prefClass.settings.value(
1779            "Debugger/" + key, prefClass.debuggerDefaults[key])
1780        # Correct obsolete entry "threaded"
1781        if debugClientType == 'threaded':
1782            return "standard"
1783        else:
1784            return debugClientType
1785    elif key in ("PythonExtensions", "Python2VirtualEnv"):
1786        # we don't support Python2 anymore
1787        return ""
1788    else:
1789        return prefClass.settings.value(
1790            "Debugger/" + key, prefClass.debuggerDefaults[key])
1791
1792
1793def setDebugger(key, value, prefClass=Prefs):
1794    """
1795    Module function to store the debugger settings.
1796
1797    @param key the key of the setting to be set
1798    @param value the value to be set
1799    @param prefClass preferences class used as the storage area
1800    """
1801    prefClass.settings.setValue("Debugger/" + key, value)
1802
1803
1804def getPython(key, prefClass=Prefs):
1805    """
1806    Module function to retrieve the Python settings.
1807
1808    @param key the key of the value to get
1809    @param prefClass preferences class used as the storage area
1810    @return the requested debugger setting
1811    """
1812    if key == "PythonExtensions":
1813        # we don't support Python2 anymore
1814        return []
1815
1816    if key == "Python3Extensions":
1817        exts = []
1818        for ext in getDebugger(key, prefClass).split():
1819            if ext.startswith("."):
1820                exts.append(ext)
1821            else:
1822                exts.append(".{0}".format(ext))
1823        return exts
1824    elif key in (
1825        "ASTViewerErrorColor", "DisViewerErrorColor",
1826        "DisViewerCurrentColor", "DisViewerLabeledColor",
1827    ):
1828        return QColor(prefClass.settings.value(
1829            "Python/" + key, prefClass.pythonDefaults[key]))
1830    elif key in ("DisViewerExpandCodeInfoDetails"):
1831        return toBool(prefClass.settings.value(
1832            "Python/" + key, prefClass.pythonDefaults[key]))
1833    else:
1834        return prefClass.settings.value(
1835            "Python/" + key, prefClass.pythonDefaults[key])
1836
1837
1838def setPython(key, value, prefClass=Prefs):
1839    """
1840    Module function to store the Python settings.
1841
1842    @param key the key of the setting to be set
1843    @param value the value to be set
1844    @param prefClass preferences class used as the storage area
1845    """
1846    if key == "Python3Extensions":
1847        setDebugger(key, value, prefClass)
1848    elif key in (
1849        "ASTViewerErrorColor", "DisViewerErrorColor",
1850        "DisViewerCurrentColor", "DisViewerLabeledColor",
1851    ):
1852        if value.alpha() < 255:
1853            val = "#{0:8x}".format(value.rgba())
1854        else:
1855            val = value.name()
1856        prefClass.settings.setValue("Python/" + key, val)
1857    else:
1858        prefClass.settings.setValue("Python/" + key, value)
1859
1860
1861def getUILanguage(prefClass=Prefs):
1862    """
1863    Module function to retrieve the language for the user interface.
1864
1865    @param prefClass preferences class used as the storage area
1866    @return the language for the UI
1867    """
1868    lang = prefClass.settings.value("UI/Language",
1869                                    prefClass.uiDefaults["Language"])
1870    if lang in ("None", "", None):
1871        return None
1872    else:
1873        return lang
1874
1875
1876def setUILanguage(lang, prefClass=Prefs):
1877    """
1878    Module function to store the language for the user interface.
1879
1880    @param lang the language
1881    @param prefClass preferences class used as the storage area
1882    """
1883    if lang is None:
1884        prefClass.settings.setValue("UI/Language", "None")
1885    else:
1886        prefClass.settings.setValue("UI/Language", lang)
1887
1888
1889def getViewManager(prefClass=Prefs):
1890    """
1891    Module function to retrieve the selected viewmanager type.
1892
1893    @param prefClass preferences class used as the storage area
1894    @return the viewmanager type
1895    """
1896    return prefClass.settings.value(
1897        "UI/ViewManager", prefClass.uiDefaults["ViewManager"])
1898
1899
1900def setViewManager(vm, prefClass=Prefs):
1901    """
1902    Module function to store the selected viewmanager type.
1903
1904    @param vm the viewmanager type
1905    @param prefClass preferences class used as the storage area
1906    """
1907    prefClass.settings.setValue("UI/ViewManager", vm)
1908
1909
1910def getUI(key, prefClass=Prefs):
1911    """
1912    Module function to retrieve the various UI settings.
1913
1914    @param key the key of the value to get
1915    @param prefClass preferences class used as the storage area
1916    @return the requested UI setting
1917    """
1918    if key in ["BrowsersListFoldersFirst", "BrowsersHideNonPublic",
1919               "BrowsersListContentsByOccurrence", "BrowsersListHiddenFiles",
1920               "BrowserShowCoding", "LogViewerAutoRaise",
1921               "SingleApplicationMode", "TabViewManagerFilenameOnly",
1922               "ShowFilePreview", "ShowFilePreviewJS", "ShowFilePreviewSSI",
1923               "CaptionShowsFilename", "ShowSplash",
1924               "SplitOrientationVertical",
1925               "UseProxy", "UseSystemProxy", "UseHttpProxyForAll",
1926               "RequestDownloadFilename", "CheckErrorLog",
1927               "OpenCrashSessionOnStartup", "CrashSessionEnabled",
1928               "ShowCodeDocumentationViewer", "ShowPyPIPackageManager",
1929               "ShowCondaPackageManager", "ShowCooperation", "ShowIrc",
1930               "ShowTemplateViewer", "ShowFileBrowser", "ShowSymbolsViewer",
1931               "ShowNumbersViewer", "ShowMicroPython", "UseNativeMenuBar"]:
1932        return toBool(prefClass.settings.value(
1933            "UI/" + key, prefClass.uiDefaults[key]))
1934    elif key in ["TabViewManagerFilenameLength", "CaptionFilenameLength",
1935                 "ProxyPort/Http", "ProxyPort/Https", "ProxyPort/Ftp",
1936                 "OpenOnStartup", "PerformVersionCheck", "RecentNumber",
1937                 "NotificationTimeout", "SidebarDelay",
1938                 "KeyboardInputInterval", "BackgroundServiceProcesses",
1939                 "MinimumMessageTypeSeverity"]:
1940        return int(prefClass.settings.value(
1941            "UI/" + key, prefClass.uiDefaults[key]))
1942    elif key in ["ProxyType/Ftp", ]:
1943        return E5FtpProxyType(int(prefClass.settings.value(
1944            "UI/" + key, prefClass.uiDefaults[key].value)))
1945    elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
1946                 "ProxyPassword/Ftp", ]:
1947        from Utilities.crypto import pwConvert
1948        return pwConvert(
1949            prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]),
1950            encode=False)
1951    elif key in ("LogStdErrColour",):
1952        col = prefClass.settings.value("UI/" + key)
1953        if col is not None:
1954            return QColor(col)
1955        else:
1956            return prefClass.uiDefaults[key]
1957    elif key in "ViewProfiles2":
1958        profilesStr = prefClass.settings.value("UI/ViewProfiles2")
1959        if profilesStr is None:
1960            # use the defaults
1961            viewProfiles = prefClass.uiDefaults["ViewProfiles2"]
1962        else:
1963            viewProfiles = {}
1964            profiles = json.loads(profilesStr)
1965            for name in ["edit", "debug"]:
1966                viewProfiles[name] = [
1967                    QByteArray.fromBase64(profiles[name][0].encode("utf-8")),
1968                    profiles[name][1][:],
1969                    []
1970                ]
1971                for bs in profiles[name][2]:
1972                    viewProfiles[name][2].append(
1973                        QByteArray.fromBase64(bs.encode("utf-8")))
1974        return viewProfiles
1975    elif key in ["ToolbarManagerState", "PreviewSplitterState"]:
1976        state = prefClass.settings.value("UI/" + key)
1977        if state is not None:
1978            return state
1979        else:
1980            return prefClass.uiDefaults[key]
1981    elif key in ["VersionsUrls6"]:
1982        urls = toList(
1983            prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]))
1984        if len(urls) == 0:
1985            return prefClass.uiDefaults[key]
1986        else:
1987            return urls
1988    elif key in ["LogViewerStdoutFilter", "LogViewerStderrFilter",
1989                 "LogViewerStdxxxFilter", "TextMimeTypes"]:
1990        return toList(
1991            prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key]))
1992    else:
1993        return prefClass.settings.value("UI/" + key, prefClass.uiDefaults[key])
1994
1995
1996def setUI(key, value, prefClass=Prefs):
1997    """
1998    Module function to store the various UI settings.
1999
2000    @param key the key of the setting to be set
2001    @param value the value to be set
2002    @param prefClass preferences class used as the storage area
2003    """
2004    if key == "ViewProfiles2":
2005        profiles = {}
2006        for name in ["edit", "debug"]:
2007            profiles[name] = [
2008                bytes(value[name][0].toBase64()).decode(),
2009                value[name][1][:],
2010                []
2011            ]
2012            for ba in value[name][2]:
2013                profiles[name][2].append(bytes(ba.toBase64()).decode())
2014        prefClass.settings.setValue("UI/" + key, json.dumps(profiles))
2015    elif key in ("LogStdErrColour",):
2016        prefClass.settings.setValue("UI/" + key, value.name())
2017    elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
2018                 "ProxyPassword/Ftp", ]:
2019        from Utilities.crypto import pwConvert
2020        prefClass.settings.setValue("UI/" + key, pwConvert(value, encode=True))
2021    elif key in ["ProxyType/Ftp", ]:
2022        # value is an enum.Enum derived item
2023        prefClass.settings.setValue("UI/" + key, value.value)
2024    else:
2025        prefClass.settings.setValue("UI/" + key, value)
2026
2027
2028def getIcons(key, prefClass=Prefs):
2029    """
2030    Module function to retrieve the various Icons settings.
2031
2032    @param key the key of the value to get
2033    @param prefClass preferences class used as the storage area
2034    @return the requested Icons setting
2035    """
2036    dirlist = prefClass.settings.value("UI/Icons/" + key)
2037    if dirlist is not None:
2038        return dirlist
2039    else:
2040        return prefClass.iconsDefaults[key]
2041
2042    if key in ["Path"]:
2043        return toList(prefClass.settings.value(
2044            "UI/Icons/" + key, prefClass.iconsDefaults[key]))
2045    else:
2046        return prefClass.settings.value(
2047            "UI/Icons/" + key, prefClass.iconsDefaults[key])
2048
2049
2050def setIcons(key, value, prefClass=Prefs):
2051    """
2052    Module function to store the various Icons settings.
2053
2054    @param key the key of the setting to be set
2055    @param value the value to be set
2056    @param prefClass preferences class used as the storage area
2057    """
2058    prefClass.settings.setValue("UI/Icons/" + key, value)
2059
2060
2061def getCooperation(key, prefClass=Prefs):
2062    """
2063    Module function to retrieve the various Cooperation settings.
2064
2065    @param key the key of the value to get
2066    @param prefClass preferences class used as the storage area
2067    @return the requested UI setting
2068    """
2069    if key in ["AutoStartServer", "TryOtherPorts", "AutoAcceptConnections"]:
2070        return toBool(prefClass.settings.value(
2071            "Cooperation/" + key, prefClass.cooperationDefaults[key]))
2072    elif key in ["ServerPort", "MaxPortsToTry"]:
2073        return int(prefClass.settings.value(
2074            "Cooperation/" + key, prefClass.cooperationDefaults[key]))
2075    elif key in ["BannedUsers"]:
2076        return toList(prefClass.settings.value(
2077            "Cooperation/" + key, prefClass.cooperationDefaults[key]))
2078    else:
2079        return prefClass.settings.value(
2080            "Cooperation/" + key, prefClass.cooperationDefaults[key])
2081
2082
2083def setCooperation(key, value, prefClass=Prefs):
2084    """
2085    Module function to store the various Cooperation settings.
2086
2087    @param key the key of the setting to be set
2088    @param value the value to be set
2089    @param prefClass preferences class used as the storage area
2090    """
2091    prefClass.settings.setValue("Cooperation/" + key, value)
2092
2093
2094def getEditor(key, prefClass=Prefs):
2095    """
2096    Module function to retrieve the various editor settings.
2097
2098    @param key the key of the value to get
2099    @param prefClass preferences class used as the storage area
2100    @return the requested editor setting
2101    """
2102    if key in ["DefaultEncoding", "DefaultOpenFilter", "DefaultSaveFilter",
2103               "SpellCheckingDefaultLanguage", "SpellCheckingPersonalWordList",
2104               "SpellCheckingPersonalExcludeList",
2105               "PreviewMarkdownHTMLFormat", "PreviewRestDocutilsHTMLFormat",
2106               "DocstringType"]:
2107        return prefClass.settings.value(
2108            "Editor/" + key, prefClass.editorDefaults[key])
2109    elif key in ["AutosaveInterval", "TabWidth", "IndentWidth",
2110                 "FoldingStyle", "WarnFilesize", "EdgeMode", "EdgeColumn",
2111                 "CaretWidth", "CaretLineFrameWidth", "AutoCompletionSource",
2112                 "AutoCompletionThreshold", "AutoCompletionTimeout",
2113                 "AutoCompletionCacheSize", "AutoCompletionCacheTime",
2114                 "AutoCompletionWatchdogTime", "AutoCompletionMaxLines",
2115                 "AutoCompletionMaxChars", "CallTipsVisible",
2116                 "CallTipsStyle", "MarkOccurrencesTimeout", "SearchRegexpMode",
2117                 "AutoSpellCheckChunkSize", "SpellCheckingMinWordSize",
2118                 "PostScriptLevel", "EOLMode", "ZoomFactor", "WhitespaceSize",
2119                 "OnlineSyntaxCheckInterval", "OnlineChangeTraceInterval",
2120                 "WrapLongLinesMode", "WrapVisualFlag", "WrapIndentMode",
2121                 "WrapStartIndent", "CallTipsPosition", "VirtualSpaceOptions",
2122                 "PreviewRefreshWaitTimer", "SourceOutlineWidth",
2123                 "SourceOutlineStepSize"]:
2124        return int(prefClass.settings.value(
2125            "Editor/" + key, prefClass.editorDefaults[key]))
2126    elif key in ["AdditionalOpenFilters", "AdditionalSaveFilters",
2127                 "PreviewMarkdownFileNameExtensions",
2128                 "PreviewRestFileNameExtensions",
2129                 "PreviewHtmlFileNameExtensions",
2130                 "PreviewQssFileNameExtensions",
2131                 "FullSpellCheckExtensions"]:
2132        return toList(prefClass.settings.value(
2133            "Editor/" + key, prefClass.editorDefaults[key]))
2134    elif key in ["PythonBadIndentation"]:
2135        value = prefClass.settings.value(
2136            "Editor/" + key, prefClass.editorDefaults[key])
2137        if value in ["true", "True"]:
2138            value = 1
2139        elif value in ["false", "False"]:
2140            value = 0
2141        return QsciLexerPython.IndentationWarning(int(value))
2142    elif key == "TabIndentOverride":
2143        overrideStr = prefClass.settings.value(
2144            "Editor/" + key, prefClass.editorDefaults[key])
2145        if overrideStr:
2146            return json.loads(overrideStr)
2147        else:
2148            return {}
2149    else:
2150        return toBool(prefClass.settings.value(
2151            "Editor/" + key, prefClass.editorDefaults[key]))
2152
2153
2154def setEditor(key, value, prefClass=Prefs):
2155    """
2156    Module function to store the various editor settings.
2157
2158    @param key the key of the setting to be set
2159    @param value the value to be set
2160    @param prefClass preferences class used as the storage area
2161    """
2162    if key == "TabIndentOverride":
2163        prefClass.settings.setValue("Editor/" + key, json.dumps(value))
2164    else:
2165        prefClass.settings.setValue("Editor/" + key, value)
2166
2167
2168def getEditorColour(key, prefClass=Prefs):
2169    """
2170    Module function to retrieve the various editor marker colours.
2171
2172    @param key the key of the value to get
2173    @param prefClass preferences class used as the storage area
2174    @return the requested editor colour
2175    """
2176    col = prefClass.settings.value("Editor/Colour/" + key)
2177    if col is not None:
2178        if len(col) == 9:
2179            # color string with alpha
2180            return QColor.fromRgba(int(col[1:], 16))
2181        else:
2182            return QColor(col)
2183    else:
2184        # palette based defaults here because of Qt5
2185        if key == "EditAreaForeground":
2186            return QApplication.palette().color(QPalette.ColorGroup.Active,
2187                                                QPalette.ColorRole.Base)
2188        elif key == "EditAreaBackground":
2189            return QApplication.palette().color(QPalette.ColorGroup.Active,
2190                                                QPalette.ColorRole.Text)
2191        else:
2192            return prefClass.editorColourDefaults[key]
2193
2194
2195def setEditorColour(key, value, prefClass=Prefs):
2196    """
2197    Module function to store the various editor marker colours.
2198
2199    @param key the key of the colour to be set
2200    @param value the colour to be set
2201    @param prefClass preferences class used as the storage area
2202    """
2203    val = ("#{0:8x}".format(value.rgba()) if value.alpha() < 255
2204           else value.name())
2205    prefClass.settings.setValue("Editor/Colour/" + key, val)
2206
2207
2208def getEditorOtherFonts(key, prefClass=Prefs):
2209    """
2210    Module function to retrieve the various editor fonts except the lexer
2211    fonts.
2212
2213    @param key the key of the value to get
2214    @param prefClass preferences class used as the storage area
2215    @return the requested editor font (QFont)
2216    """
2217    f = QFont()
2218    f.fromString(prefClass.settings.value(
2219        "Editor/Other Fonts/" + key, prefClass.editorOtherFontsDefaults[key]))
2220    return f
2221
2222
2223def setEditorOtherFonts(key, font, prefClass=Prefs):
2224    """
2225    Module function to store the various editor fonts except the lexer fonts.
2226
2227    @param key the key of the font to be set
2228    @param font the font to be set (QFont)
2229    @param prefClass preferences class used as the storage area
2230    """
2231    prefClass.settings.setValue("Editor/Other Fonts/" + key, font.toString())
2232
2233
2234def getEditorAPI(language, projectType="", prefClass=Prefs):
2235    """
2236    Module function to retrieve the various lists of API files.
2237
2238    @param language language of the API list
2239    @type str
2240    @param projectType project type of the API list
2241    @type str
2242    @param prefClass preferences class used as the storage area
2243    @type Prefs
2244    @return requested list of API files
2245    @rtype list of str
2246    """
2247    key = "{0}_{1}".format(language, projectType) if projectType else language
2248    apis = prefClass.settings.value("Editor/APIs/" + key)
2249    if apis is not None:
2250        if len(apis) and apis[0] == "":
2251            return []
2252        else:
2253            return apis
2254    else:
2255        if projectType:
2256            # try again without project type
2257            return getEditorAPI(language, prefClass=prefClass)
2258
2259        return []
2260
2261
2262def setEditorAPI(language, projectType, apilist, prefClass=Prefs):
2263    """
2264    Module function to store the various lists of API files.
2265
2266    @param language language of the API list
2267    @type str
2268    @param projectType project type of the API list
2269    @type str
2270    @param apilist list of API files
2271    @type list of str
2272    @param prefClass preferences class used as the storage area
2273    @type Prefs
2274    """
2275    key = "{0}_{1}".format(language, projectType) if projectType else language
2276    prefClass.settings.setValue("Editor/APIs/" + key, apilist)
2277
2278
2279def getEditorKeywords(key, prefClass=Prefs):
2280    """
2281    Module function to retrieve the various lists of language keywords.
2282
2283    @param key the key of the value to get
2284    @param prefClass preferences class used as the storage area
2285    @return the requested list of language keywords (list of strings)
2286    """
2287    keywords = prefClass.settings.value("Editor/Keywords/" + key)
2288    if keywords is not None:
2289        return keywords
2290    else:
2291        return []
2292
2293
2294def setEditorKeywords(key, keywordsLists, prefClass=Prefs):
2295    """
2296    Module function to store the various lists of language keywords.
2297
2298    @param key the key of the api to be set
2299    @param keywordsLists the list of language keywords (list of strings)
2300    @param prefClass preferences class used as the storage area
2301    """
2302    prefClass.settings.setValue("Editor/Keywords/" + key, keywordsLists)
2303
2304
2305def getEditorLexerAssocs(prefClass=Prefs):
2306    """
2307    Module function to retrieve all lexer associations.
2308
2309    @param prefClass preferences class used as the storage area
2310    @return a reference to the list of lexer associations
2311        (dictionary of strings)
2312    """
2313    editorLexerAssoc = {}
2314    prefClass.settings.beginGroup("Editor/LexerAssociations")
2315    keyList = prefClass.settings.childKeys()
2316    prefClass.settings.endGroup()
2317
2318    import QScintilla.Lexers
2319    editorLexerAssocDefaults = QScintilla.Lexers.getDefaultLexerAssociations()
2320
2321    if len(keyList) == 0:
2322        # build from scratch
2323        for key in list(editorLexerAssocDefaults.keys()):
2324            editorLexerAssoc[key] = editorLexerAssocDefaults[key]
2325    else:
2326        for key in keyList:
2327            defaultValue = editorLexerAssocDefaults.get(key, "")
2328            editorLexerAssoc[key] = prefClass.settings.value(
2329                "Editor/LexerAssociations/" + key, defaultValue)
2330
2331        # check for new default lexer associations
2332        for key in list(editorLexerAssocDefaults.keys()):
2333            if key not in editorLexerAssoc:
2334                editorLexerAssoc[key] = editorLexerAssocDefaults[key]
2335    return editorLexerAssoc
2336
2337
2338def setEditorLexerAssocs(assocs, prefClass=Prefs):
2339    """
2340    Module function to retrieve all lexer associations.
2341
2342    @param assocs dictionary of lexer associations to be set
2343    @param prefClass preferences class used as the storage area
2344    """
2345    # first remove lexer associations that no longer exist, than save the rest
2346    prefClass.settings.beginGroup("Editor/LexerAssociations")
2347    keyList = prefClass.settings.childKeys()
2348    prefClass.settings.endGroup()
2349    for key in keyList:
2350        if key not in assocs:
2351            prefClass.settings.remove("Editor/LexerAssociations/" + key)
2352    for key in assocs:
2353        prefClass.settings.setValue(
2354            "Editor/LexerAssociations/" + key, assocs[key])
2355
2356
2357def getEditorLexerAssoc(filename, prefClass=Prefs):
2358    """
2359    Module function to retrieve a lexer association.
2360
2361    @param filename filename used to determine the associated lexer language
2362        (string)
2363    @param prefClass preferences class used as the storage area
2364    @return the requested lexer language (string)
2365    """
2366    for pattern, language in list(getEditorLexerAssocs().items()):
2367        if fnmatch.fnmatch(filename, pattern):
2368            return language
2369
2370    return ""
2371
2372
2373def getEditorTyping(key, prefClass=Prefs):
2374    """
2375    Module function to retrieve the various editor typing settings.
2376
2377    @param key the key of the value to get
2378    @param prefClass preferences class used as the storage area
2379    @return the requested editor setting
2380    """
2381    return toBool(prefClass.settings.value(
2382        "Editor/Typing/" + key, prefClass.editorTypingDefaults[key]))
2383
2384
2385def setEditorTyping(key, value, prefClass=Prefs):
2386    """
2387    Module function to store the various editor typing settings.
2388
2389    @param key the key of the setting to be set
2390    @param value the value to be set
2391    @param prefClass preferences class used as the storage area
2392    """
2393    prefClass.settings.setValue("Editor/Typing/" + key, value)
2394
2395
2396def getEditorExporter(key, prefClass=Prefs):
2397    """
2398    Module function to retrieve the various editor exporters settings.
2399
2400    @param key the key of the value to get
2401    @param prefClass preferences class used as the storage area
2402    @return the requested editor setting
2403    """
2404    if key in ["RTF/Font"]:
2405        f = QFont()
2406        f.fromString(prefClass.settings.value(
2407            "Editor/Exporters/" + key, prefClass.editorExporterDefaults[key]))
2408        return f
2409    elif key in ["HTML/WYSIWYG", "HTML/Folding", "HTML/OnlyStylesUsed",
2410                 "HTML/FullPathAsTitle", "HTML/UseTabs", "RTF/WYSIWYG",
2411                 "RTF/UseTabs", "TeX/OnlyStylesUsed", "TeX/FullPathAsTitle",
2412                 "ODT/WYSIWYG", "ODT/OnlyStylesUsed", "ODT/UseTabs"]:
2413        return toBool(prefClass.settings.value(
2414            "Editor/Exporters/" + key, prefClass.editorExporterDefaults[key]))
2415    elif key in ["PDF/Magnification", "PDF/MarginLeft", "PDF/MarginRight",
2416                 "PDF/MarginTop", "PDF/MarginBottom"]:
2417        return int(prefClass.settings.value(
2418            "Editor/Exporters/" + key, prefClass.editorExporterDefaults[key]))
2419    else:
2420        return prefClass.settings.value(
2421            "Editor/Exporters/" + key, prefClass.editorExporterDefaults[key])
2422
2423
2424def setEditorExporter(key, value, prefClass=Prefs):
2425    """
2426    Module function to store the various editor exporters settings.
2427
2428    @param key the key of the setting to be set
2429    @param value the value to be set
2430    @param prefClass preferences class used as the storage area
2431    """
2432    if key in ["RTF/Font"]:
2433        prefClass.settings.setValue(
2434            "Editor/Exporters/" + key, value.toString())
2435    else:
2436        prefClass.settings.setValue("Editor/Exporters/" + key, value)
2437
2438
2439def getPrinter(key, prefClass=Prefs):
2440    """
2441    Module function to retrieve the various printer settings.
2442
2443    @param key the key of the value to get
2444    @param prefClass preferences class used as the storage area
2445    @return the requested printer setting
2446    """
2447    if key in ["ColorMode", "FirstPageFirst"]:
2448        return toBool(prefClass.settings.value(
2449            "Printer/" + key, prefClass.printerDefaults[key]))
2450    elif key in ["Magnification", "Orientation", "PageSize", "Resolution"]:
2451        return int(prefClass.settings.value(
2452            "Printer/" + key, prefClass.printerDefaults[key]))
2453    elif key in ["LeftMargin", "RightMargin", "TopMargin", "BottomMargin"]:
2454        return float(prefClass.settings.value(
2455            "Printer/" + key, prefClass.printerDefaults[key]))
2456    elif key in ["HeaderFont"]:
2457        f = QFont()
2458        f.fromString(prefClass.settings.value(
2459            "Printer/" + key, prefClass.printerDefaults[key]))
2460        return f
2461    else:
2462        return prefClass.settings.value(
2463            "Printer/" + key, prefClass.printerDefaults[key])
2464
2465
2466def setPrinter(key, value, prefClass=Prefs):
2467    """
2468    Module function to store the various printer settings.
2469
2470    @param key the key of the setting to be set
2471    @param value the value to be set
2472    @param prefClass preferences class used as the storage area
2473    """
2474    if key in ["HeaderFont"]:
2475        prefClass.settings.setValue("Printer/" + key, value.toString())
2476    else:
2477        prefClass.settings.setValue("Printer/" + key, value)
2478
2479
2480def getShell(key, prefClass=Prefs):
2481    """
2482    Module function to retrieve the various shell settings.
2483
2484    @param key the key of the value to get
2485    @param prefClass preferences class used as the storage area
2486    @return the requested shell setting
2487    """
2488    if key in ["MonospacedFont", "MarginsFont"]:
2489        f = QFont()
2490        f.fromString(prefClass.settings.value(
2491            "Shell/" + key, prefClass.shellDefaults[key]))
2492        return f
2493    elif key in ["MaxHistoryEntries"]:
2494        return int(prefClass.settings.value(
2495            "Shell/" + key, prefClass.shellDefaults[key]))
2496    elif key in ["HistoryStyle"]:
2497        return ShellHistoryStyle(int(prefClass.settings.value(
2498            "Shell/" + key, prefClass.shellDefaults[key].value)))
2499    elif key in ["LastVirtualEnvironment"]:
2500        return prefClass.settings.value(
2501            "Shell/" + key, prefClass.shellDefaults[key])
2502    else:
2503        return toBool(prefClass.settings.value(
2504            "Shell/" + key, prefClass.shellDefaults[key]))
2505
2506
2507def setShell(key, value, prefClass=Prefs):
2508    """
2509    Module function to store the various shell settings.
2510
2511    @param key the key of the setting to be set
2512    @param value the value to be set
2513    @param prefClass preferences class used as the storage area
2514    """
2515    if key in ["MonospacedFont", "MarginsFont"]:
2516        prefClass.settings.setValue("Shell/" + key, value.toString())
2517    elif key in ["HistoryStyle"]:
2518        prefClass.settings.setValue("Shell/" + key, value.value)
2519    else:
2520        prefClass.settings.setValue("Shell/" + key, value)
2521
2522
2523def getProject(key, prefClass=Prefs):
2524    """
2525    Module function to retrieve the various project handling settings.
2526
2527    @param key the key of the value to get
2528    @param prefClass preferences class used as the storage area
2529    @return the requested project setting
2530    """
2531    if key in ["RecentNumber"]:
2532        return int(prefClass.settings.value(
2533            "Project/" + key, prefClass.projectDefaults[key]))
2534    elif key in ["DebugClientsHistory", "DebuggerInterpreterHistory"]:
2535        return toList(prefClass.settings.value(
2536            "Project/" + key, prefClass.projectDefaults[key]))
2537    else:
2538        return toBool(prefClass.settings.value(
2539            "Project/" + key, prefClass.projectDefaults[key]))
2540
2541
2542def setProject(key, value, prefClass=Prefs):
2543    """
2544    Module function to store the various project handling settings.
2545
2546    @param key the key of the setting to be set
2547    @param value the value to be set
2548    @param prefClass preferences class used as the storage area
2549    """
2550    if key in ["DebugClientsHistory", "DebuggerInterpreterHistory"]:
2551        # max. list sizes is hard coded to 20 entries
2552        newList = [v for v in value if v]
2553        if len(newList) > 20:
2554            newList = newList[:20]
2555        prefClass.settings.setValue("Project/" + key, newList)
2556    else:
2557        prefClass.settings.setValue("Project/" + key, value)
2558
2559
2560def getProjectBrowserFlags(key, prefClass=Prefs):
2561    """
2562    Module function to retrieve the various project browser flags settings.
2563
2564    @param key the key of the value to get
2565    @param prefClass preferences class used as the storage area
2566    @return the requested project setting
2567    """
2568    try:
2569        default = prefClass.projectBrowserFlagsDefaults[key]
2570    except KeyError:
2571        default = AllBrowsersFlag
2572
2573    return int(prefClass.settings.value(
2574        "Project/BrowserFlags/" + key, default))
2575
2576
2577def setProjectBrowserFlags(key, value, prefClass=Prefs):
2578    """
2579    Module function to store the various project browser flags settings.
2580
2581    @param key the key of the setting to be set
2582    @param value the value to be set
2583    @param prefClass preferences class used as the storage area
2584    """
2585    prefClass.settings.setValue("Project/BrowserFlags/" + key, value)
2586
2587
2588def setProjectBrowserFlagsDefault(key, value, prefClass=Prefs):
2589    """
2590    Module function to store the various project browser flags settings.
2591
2592    @param key the key of the setting to be set
2593    @param value the value to be set
2594    @param prefClass preferences class used as the storage area
2595    """
2596    prefClass.projectBrowserFlagsDefaults[key] = value
2597
2598
2599def removeProjectBrowserFlags(key, prefClass=Prefs):
2600    """
2601    Module function to remove a project browser flags setting.
2602
2603    @param key the key of the setting to be removed
2604    @param prefClass preferences class used as the storage area
2605    """
2606    prefClass.settings.remove("Project/BrowserFlags/" + key)
2607
2608
2609def getProjectBrowserColour(key, prefClass=Prefs):
2610    """
2611    Module function to retrieve the various project browser colours.
2612
2613    @param key the key of the value to get
2614    @param prefClass preferences class used as the storage area
2615    @return the requested project browser colour
2616    """
2617    col = prefClass.settings.value("Project/Colour/" + key)
2618    if col is not None:
2619        return QColor(col)
2620    else:
2621        return prefClass.projectBrowserColourDefaults[key]
2622
2623
2624def setProjectBrowserColour(key, value, prefClass=Prefs):
2625    """
2626    Module function to store the various project browser colours.
2627
2628    @param key the key of the colour to be set
2629    @param value the colour to be set
2630    @param prefClass preferences class used as the storage area
2631    """
2632    prefClass.settings.setValue("Project/Colour/" + key, value.name())
2633
2634
2635def getMultiProject(key, prefClass=Prefs):
2636    """
2637    Module function to retrieve the various project handling settings.
2638
2639    @param key the key of the value to get
2640    @param prefClass preferences class used as the storage area
2641    @return the requested project setting
2642    """
2643    if key in ["RecentNumber"]:
2644        return int(prefClass.settings.value(
2645            "MultiProject/" + key, prefClass.multiProjectDefaults[key]))
2646    elif key in ["OpenMasterAutomatically", "TimestampFile"]:
2647        return toBool(prefClass.settings.value(
2648            "MultiProject/" + key, prefClass.multiProjectDefaults[key]))
2649    else:
2650        return prefClass.settings.value(
2651            "MultiProject/" + key, prefClass.multiProjectDefaults[key])
2652
2653
2654def setMultiProject(key, value, prefClass=Prefs):
2655    """
2656    Module function to store the various project handling settings.
2657
2658    @param key the key of the setting to be set
2659    @param value the value to be set
2660    @param prefClass preferences class used as the storage area
2661    """
2662    prefClass.settings.setValue("MultiProject/" + key, value)
2663
2664
2665def getQtDocDir(version, prefClass=Prefs):
2666    """
2667    Module function to retrieve the Qt5DocDir setting.
2668
2669    @param version Qt version to get documentation directory for
2670    @type int
2671    @param prefClass preferences class used as the storage area
2672    @return the requested Qt5DocDir setting
2673    @rtype str
2674    """
2675    key = "Qt{0}DocDir".format(version)
2676    s = prefClass.settings.value(
2677        "Help/{0}".format(key), prefClass.helpDefaults[key])
2678    if s == "":
2679        s = os.getenv(key.upper(), "")
2680    if s == "":
2681        s = os.path.join(
2682            QLibraryInfo.location(
2683                QLibraryInfo.LibraryLocation.DocumentationPath),
2684            "qtdoc")
2685    return s
2686
2687
2688def getHelp(key, prefClass=Prefs):
2689    """
2690    Module function to retrieve the various help settings.
2691
2692    @param key the key of the value to get
2693    @param prefClass preferences class used as the storage area
2694    @return the requested help setting
2695    """
2696    return prefClass.settings.value("Help/" + key,
2697                                    prefClass.helpDefaults[key])
2698
2699
2700def setHelp(key, value, prefClass=Prefs):
2701    """
2702    Module function to store the various help settings.
2703
2704    @param key the key of the setting to be set
2705    @param value the value to be set
2706    @param prefClass preferences class used as the storage area
2707    """
2708    prefClass.settings.setValue("Help/" + key, value)
2709
2710
2711def getWebBrowser(key, prefClass=Prefs):
2712    """
2713    Module function to retrieve the various web browser settings.
2714
2715    @param key the key of the value to get
2716    @param prefClass preferences class used as the storage area
2717    @return the requested help setting
2718    """
2719    if not prefClass.webEngineSettingsIntitialized:
2720        prefClass.initWebEngineSettingsDefaults()
2721
2722    if key in ["StandardFont", "FixedFont"]:
2723        f = QFont()
2724        f.fromString(prefClass.settings.value(
2725            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2726        return f
2727    elif key in ["SecureUrlColor", "InsecureUrlColor", "MaliciousUrlColor",
2728                 "PrivateModeUrlColor"]:
2729        col = prefClass.settings.value("WebBrowser/" + key)
2730        if col is not None:
2731            return QColor(col)
2732        else:
2733            return prefClass.webBrowserDefaults[key]
2734    elif key in ["WebSearchKeywords"]:
2735        # return a list of tuples of (keyword, engine name)
2736        keywords = []
2737        size = prefClass.settings.beginReadArray("WebBrowser/" + key)
2738        for index in range(size):
2739            prefClass.settings.setArrayIndex(index)
2740            keyword = prefClass.settings.value("Keyword")
2741            engineName = prefClass.settings.value("Engine")
2742            keywords.append((keyword, engineName))
2743        prefClass.settings.endArray()
2744        return keywords
2745    elif key == "DownloadManagerDownloads":
2746        # return a list of dicts containing the URL, save location, done flag,
2747        # page URL, date/time downloaded
2748        downloads = []
2749        length = prefClass.settings.beginReadArray("WebBrowser/" + key)
2750        for index in range(length):
2751            download = {}
2752            prefClass.settings.setArrayIndex(index)
2753            download["URL"] = prefClass.settings.value("URL")
2754            if download["URL"] is None:
2755                download["URL"] = QUrl()
2756            download["Location"] = prefClass.settings.value("Location")
2757            download["Done"] = toBool(prefClass.settings.value("Done"))
2758            download["PageURL"] = prefClass.settings.value("PageURL")
2759            if download["PageURL"] is None:
2760                download["PageURL"] = QUrl()
2761            download["Downloaded"] = prefClass.settings.value("Downloaded")
2762            if download["Downloaded"] is None:
2763                download["Downloaded"] = QDateTime()
2764            elif isinstance(download["Downloaded"], str):
2765                download["Downloaded"] = QDateTime.fromString(
2766                    download["Downloaded"], "yyyy-MM-dd hh:mm:ss")
2767            downloads.append(download)
2768        prefClass.settings.endArray()
2769        return downloads
2770    elif key == "RssFeeds":
2771        # return a list of tuples of (URL, title, icon)
2772        feeds = []
2773        length = prefClass.settings.beginReadArray("WebBrowser/" + key)
2774        for index in range(length):
2775            prefClass.settings.setArrayIndex(index)
2776            url = prefClass.settings.value("URL")
2777            title = prefClass.settings.value("Title")
2778            icon = prefClass.settings.value("Icon")
2779            feeds.append((url, title, icon))
2780        prefClass.settings.endArray()
2781        return feeds
2782    elif key in ["SyncFtpPassword", "SyncEncryptionKey"]:
2783        from Utilities.crypto import pwConvert
2784        return pwConvert(prefClass.settings.value(
2785            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]),
2786            encode=False)
2787    elif key == "HelpViewerType":
2788        # special treatment to adjust for missing QtWebEngine
2789        value = int(prefClass.settings.value(
2790            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2791        if QWebEngineSettings is None:
2792            value = prefClass.webBrowserDefaults[key]
2793        return value
2794    elif key in ["StartupBehavior", "HistoryLimit",
2795                 "DownloadManagerRemovePolicy", "SyncType", "SyncFtpPort",
2796                 "SyncFtpIdleTimeout", "SyncEncryptionKeyLength",
2797                 "SearchLanguage", "DefaultFontSize", "DefaultFixedFontSize",
2798                 "MinimumFontSize", "MinimumLogicalFontSize",
2799                 "DiskCacheSize", "AcceptCookies", "KeepCookiesUntil",
2800                 "AdBlockUpdatePeriod", "TabManagerGroupByType",
2801                 "SessionAutoSaveInterval", "NewTabBehavior",
2802                 "RefererSendReferer", "RefererDefaultPolicy",
2803                 "RefererTrimmingPolicy", "AcceptQuotaRequest",
2804                 "AcceptProtocolHandlerRequest",
2805                 ]:
2806        return int(prefClass.settings.value(
2807            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2808    elif key in ["SingleWebBrowserWindow", "SaveGeometry",
2809                 "JavaScriptEnabled", "JavaScriptCanOpenWindows",
2810                 "JavaScriptCanAccessClipboard",
2811                 "AutoLoadImages", "LocalStorageEnabled",
2812                 "SpatialNavigationEnabled", "LinksIncludedInFocusChain",
2813                 "LocalContentCanAccessRemoteUrls",
2814                 "LocalContentCanAccessFileUrls", "XSSAuditingEnabled",
2815                 "ScrollAnimatorEnabled", "ErrorPageEnabled",
2816                 "WarnOnMultipleClose", "WebSearchSuggestions",
2817                 "SyncEnabled", "SyncBookmarks", "SyncHistory",
2818                 "SyncPasswords", "SyncUserAgents", "SyncSpeedDial",
2819                 "SyncEncryptData", "SyncEncryptPasswordsOnly",
2820                 "ShowPreview", "DiskCacheEnabled",
2821                 "DoNotTrack", "FilterTrackingCookies",
2822                 "AdBlockEnabled", "AdBlockUseLimitedEasyList",
2823                 "PluginsEnabled", "FullScreenSupportEnabled",
2824                 "AutoScrollEnabled", "ScreenCaptureEnabled",
2825                 "WebGLEnabled", "FocusOnNavigationEnabled",
2826                 "PrintElementBackgrounds", "AllowRunningInsecureContent",
2827                 "SpellCheckEnabled", "ShowToolbars", "MenuBarVisible",
2828                 "BookmarksToolBarVisible", "StatusBarVisible",
2829                 "SessionAutoSave", "LoadTabOnActivation",
2830                 "SafeBrowsingEnabled", "SafeBrowsingFilterPlatform",
2831                 "SafeBrowsingAutoUpdate", "SafeBrowsingUseLookupApi",
2832                 "AllowGeolocationOnInsecureOrigins",
2833                 "AllowWindowActivationFromJavaScript", "ShowScrollBars",
2834                 "DownloadManagerAutoOpen", "DownloadManagerAutoClose",
2835                 "PlaybackRequiresUserGesture", "JavaScriptCanPaste",
2836                 "WebRTCPublicInterfacesOnly", "DnsPrefetchEnabled",
2837                 "VirusTotalEnabled", "VirusTotalSecure",
2838                 "PdfViewerEnabled", "AlwaysRejectFaultyCertificates",
2839                 ]:
2840        return toBool(prefClass.settings.value(
2841            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2842    elif key in ["GreaseMonkeyDisabledScripts", "SendRefererWhitelist",
2843                 "AdBlockSubscriptions", "AdBlockExceptions",
2844                 "SpellCheckLanguages",
2845                 ]:
2846        return toList(prefClass.settings.value(
2847            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2848    elif key in ["AutoScrollDivider"]:
2849        return float(prefClass.settings.value(
2850            "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
2851    elif key in ["SafeBrowsingUpdateDateTime"]:
2852        dateTimeStr = prefClass.settings.value("WebBrowser/" + key)
2853        if dateTimeStr is not None:
2854            return QDateTime.fromString(dateTimeStr, Qt.DateFormat.ISODate)
2855        else:
2856            return prefClass.webBrowserDefaults[key]
2857    else:
2858        return prefClass.settings.value("WebBrowser/" + key,
2859                                        prefClass.webBrowserDefaults[key])
2860
2861
2862def setWebBrowser(key, value, prefClass=Prefs):
2863    """
2864    Module function to store the various web browser settings.
2865
2866    @param key the key of the setting to be set
2867    @param value the value to be set
2868    @param prefClass preferences class used as the storage area
2869    """
2870    if key in ["StandardFont", "FixedFont"]:
2871        prefClass.settings.setValue("WebBrowser/" + key, value.toString())
2872    elif key in ["SecureUrlColor", "InsecureUrlColor", "MaliciousUrlColor",
2873                 "PrivateModeUrlColor"]:
2874        prefClass.settings.setValue("WebBrowser/" + key, value.name())
2875    elif key == "WebSearchKeywords":
2876        # value is list of tuples of (keyword, engine name)
2877        prefClass.settings.remove("WebBrowser/" + key)
2878        prefClass.settings.beginWriteArray("WebBrowser/" + key, len(value))
2879        for index, v in enumerate(value):
2880            prefClass.settings.setArrayIndex(index)
2881            prefClass.settings.setValue("Keyword", v[0])
2882            prefClass.settings.setValue("Engine", v[1])
2883        prefClass.settings.endArray()
2884    elif key == "DownloadManagerDownloads":
2885        # value is list of dicts containing the URL, save location, done flag,
2886        # page URL, date/time downloaded
2887        prefClass.settings.remove("Help/" + key)
2888        prefClass.settings.beginWriteArray("WebBrowser/" + key, len(value))
2889        for index, v in enumerate(value):
2890            prefClass.settings.setArrayIndex(index)
2891            prefClass.settings.setValue("URL", v["URL"])
2892            prefClass.settings.setValue("Location", v["Location"])
2893            prefClass.settings.setValue("Done", v["Done"])
2894            prefClass.settings.setValue("PageURL", v["PageURL"])
2895            prefClass.settings.setValue(
2896                "Downloaded", v["Downloaded"].toString("yyyy-MM-dd hh:mm:ss"))
2897        prefClass.settings.endArray()
2898    elif key == "RssFeeds":
2899        # value is list of tuples of (URL, title, icon)
2900        prefClass.settings.remove("WebBrowser/" + key)
2901        prefClass.settings.beginWriteArray("WebBrowser/" + key, len(value))
2902        for index, v in enumerate(value):
2903            prefClass.settings.setArrayIndex(index)
2904            prefClass.settings.setValue("URL", v[0])
2905            prefClass.settings.setValue("Title", v[1])
2906            prefClass.settings.setValue("Icon", v[2])
2907        prefClass.settings.endArray()
2908    elif key in ["SyncFtpPassword", "SyncEncryptionKey"]:
2909        from Utilities.crypto import pwConvert
2910        prefClass.settings.setValue(
2911            "WebBrowser/" + key, pwConvert(value, encode=True))
2912    elif key in ["SafeBrowsingUpdateDateTime"]:
2913        # value is a QDateTime
2914        prefClass.settings.setValue("WebBrowser/" + key,
2915                                    value.toString(Qt.DateFormat.ISODate))
2916    else:
2917        prefClass.settings.setValue("WebBrowser/" + key, value)
2918
2919
2920def getSystem(key, prefClass=Prefs):
2921    """
2922    Module function to retrieve the various system settings.
2923
2924    @param key the key of the value to get
2925    @param prefClass preferences class used as the storage area
2926    @return the requested system setting
2927    """
2928    from Utilities import supportedCodecs
2929    if key in ["StringEncoding", "IOEncoding"]:
2930        encoding = prefClass.settings.value(
2931            "System/" + key, prefClass.sysDefaults[key])
2932        if encoding not in supportedCodecs:
2933            encoding = prefClass.sysDefaults[key]
2934        return encoding
2935
2936    return None
2937
2938
2939def setSystem(key, value, prefClass=Prefs):
2940    """
2941    Module function to store the various system settings.
2942
2943    @param key the key of the setting to be set
2944    @param value the value to be set
2945    @param prefClass preferences class used as the storage area
2946    """
2947    prefClass.settings.setValue("System/" + key, value)
2948
2949
2950def getQtTranslationsDir(prefClass=Prefs):
2951    """
2952    Module function to retrieve the Qt5TranslationsDir
2953    setting depending on the current Qt version.
2954
2955    @param prefClass preferences class used as the storage area
2956    @return the requested setting (string)
2957    """
2958    s = prefClass.settings.value(
2959        "Qt/Qt5TranslationsDir",
2960        prefClass.qtDefaults["Qt5TranslationsDir"])
2961    if s == "":
2962        s = QLibraryInfo.location(
2963            QLibraryInfo.LibraryLocation.TranslationsPath)
2964    if s == "" and Globals.isWindowsPlatform():
2965        transPath = os.path.join(Globals.getPyQt5ModulesDirectory(),
2966                                 "translations")
2967        if os.path.exists(transPath):
2968            s = transPath
2969    return s
2970
2971
2972def getQt(key, prefClass=Prefs):
2973    """
2974    Module function to retrieve the various Qt settings.
2975
2976    @param key the key of the value to get
2977    @param prefClass preferences class used as the storage area
2978    @return the requested Qt setting
2979    """
2980    if key in ["Qt5TranslationsDir"]:
2981        return getQtTranslationsDir(prefClass)
2982    elif key in ["PyuicIndent", "Pyuic6Indent"]:
2983        return int(prefClass.settings.value(
2984            "Qt/" + key, prefClass.qtDefaults[key]))
2985    elif key in ["PyuicFromImports", "PyuicExecute", "Pyuic6Execute",
2986                 "PySide2FromImports", "PySide6FromImports"]:
2987        return toBool(prefClass.settings.value(
2988            "Qt/" + key, prefClass.qtDefaults[key]))
2989    else:
2990        return prefClass.settings.value("Qt/" + key, prefClass.qtDefaults[key])
2991
2992
2993def setQt(key, value, prefClass=Prefs):
2994    """
2995    Module function to store the various Qt settings.
2996
2997    @param key the key of the setting to be set
2998    @param value the value to be set
2999    @param prefClass preferences class used as the storage area
3000    """
3001    prefClass.settings.setValue("Qt/" + key, value)
3002
3003
3004def getCorba(key, prefClass=Prefs):
3005    """
3006    Module function to retrieve the various Corba settings.
3007
3008    @param key the key of the value to get
3009    @param prefClass preferences class used as the storage area
3010    @return the requested corba setting
3011    """
3012    return prefClass.settings.value(
3013        "Corba/" + key, prefClass.corbaDefaults[key])
3014
3015
3016def setCorba(key, value, prefClass=Prefs):
3017    """
3018    Module function to store the various Corba settings.
3019
3020    @param key the key of the setting to be set
3021    @param value the value to be set
3022    @param prefClass preferences class used as the storage area
3023    """
3024    prefClass.settings.setValue("Corba/" + key, value)
3025
3026
3027def getProtobuf(key, prefClass=Prefs):
3028    """
3029    Module function to retrieve the various protobuf settings.
3030
3031    @param key the key of the value to get
3032    @type str
3033    @param prefClass preferences class used as the storage area
3034    @type Prefs
3035    @return the requested protobuf setting
3036    @rtype any
3037    """
3038    return prefClass.settings.value(
3039        "Protobuf/" + key, prefClass.protobufDefaults[key])
3040
3041
3042def setProtobuf(key, value, prefClass=Prefs):
3043    """
3044    Module function to store the various protobuf settings.
3045
3046    @param key the key of the setting to be set
3047    @type str
3048    @param value the value to be set
3049    @type any
3050    @param prefClass preferences class used as the storage area
3051    @type Prefs
3052    """
3053    prefClass.settings.setValue("Protobuf/" + key, value)
3054
3055
3056def getUser(key, prefClass=Prefs):
3057    """
3058    Module function to retrieve the various user settings.
3059
3060    @param key the key of the value to get
3061    @param prefClass preferences class used as the storage area
3062    @return the requested user setting
3063    """
3064    if key == "MailServerPassword":
3065        from Utilities.crypto import pwConvert
3066        return pwConvert(prefClass.settings.value(
3067            "User/" + key, prefClass.userDefaults[key]), encode=False)
3068    elif key in ["MailServerPort"]:
3069        try:
3070            return int(prefClass.settings.value(
3071                "User/" + key, prefClass.userDefaults[key]))
3072        except ValueError:
3073            return prefClass.userDefaults[key]
3074    elif key in ["MailServerAuthentication", "UseSystemEmailClient",
3075                 "UseMasterPassword", "SavePasswords", "UseGoogleMailOAuth2"]:
3076        return toBool(prefClass.settings.value(
3077            "User/" + key, prefClass.userDefaults[key]))
3078    elif key == "MailServerEncryption":
3079        # convert from old key 'MailServerUseTLS'
3080        val = prefClass.settings.value("User/" + key)
3081        if val is None:
3082            if toBool(prefClass.settings.value("User/MailServerUseTLS")):
3083                val = "TLS"
3084            else:
3085                val = prefClass.userDefaults[key]
3086        return val
3087    else:
3088        return prefClass.settings.value(
3089            "User/" + key, prefClass.userDefaults[key])
3090
3091
3092def setUser(key, value, prefClass=Prefs):
3093    """
3094    Module function to store the various user settings.
3095
3096    @param key the key of the setting to be set
3097    @param value the value to be set
3098    @param prefClass preferences class used as the storage area
3099    """
3100    if key == "MailServerPassword":
3101        from Utilities.crypto import pwConvert
3102        prefClass.settings.setValue(
3103            "User/" + key, pwConvert(value, encode=True))
3104    elif key == "MasterPassword":
3105        from Utilities.crypto.py3PBKDF2 import hashPassword
3106        prefClass.settings.setValue(
3107            "User/" + key, hashPassword(value))
3108    else:
3109        prefClass.settings.setValue("User/" + key, value)
3110
3111
3112def getVCS(key, prefClass=Prefs):
3113    """
3114    Module function to retrieve the VCS related settings.
3115
3116    @param key the key of the value to get
3117    @param prefClass preferences class used as the storage area
3118    @return the requested user setting
3119    """
3120    if key in ["StatusMonitorInterval"]:
3121        return int(prefClass.settings.value(
3122            "VCS/" + key, prefClass.vcsDefaults[key]))
3123    else:
3124        return toBool(prefClass.settings.value(
3125            "VCS/" + key, prefClass.vcsDefaults[key]))
3126
3127
3128def setVCS(key, value, prefClass=Prefs):
3129    """
3130    Module function to store the VCS related settings.
3131
3132    @param key the key of the setting to be set
3133    @param value the value to be set
3134    @param prefClass preferences class used as the storage area
3135    """
3136    prefClass.settings.setValue("VCS/" + key, value)
3137
3138
3139def getTasks(key, prefClass=Prefs):
3140    """
3141    Module function to retrieve the Tasks related settings.
3142
3143    @param key the key of the value to get
3144    @param prefClass preferences class used as the storage area
3145    @return the requested user setting
3146    """
3147    if key in ["TasksFixmeColor", "TasksWarningColor",
3148               "TasksTodoColor", "TasksNoteColor",
3149               "TasksTestColor", "TasksDocuColor"]:
3150        col = prefClass.settings.value("Tasks/" + key)
3151        if col is not None:
3152            return QColor(col)
3153        else:
3154            return prefClass.tasksDefaults[key]
3155    elif key in ["ClearOnFileClose", ]:
3156        return toBool(prefClass.settings.value(
3157            "Tasks/" + key, prefClass.tasksDefaults[key]))
3158    else:
3159        return prefClass.settings.value(
3160            "Tasks/" + key, prefClass.tasksDefaults[key])
3161
3162
3163def setTasks(key, value, prefClass=Prefs):
3164    """
3165    Module function to store the Tasks related settings.
3166
3167    @param key the key of the setting to be set
3168    @param value the value to be set
3169    @param prefClass preferences class used as the storage area
3170    """
3171    if key in ["TasksFixmeColor", "TasksWarningColor",
3172               "TasksTodoColor", "TasksNoteColor"]:
3173        prefClass.settings.setValue("Tasks/" + key, value.name())
3174    else:
3175        prefClass.settings.setValue("Tasks/" + key, value)
3176
3177
3178def getTemplates(key, prefClass=Prefs):
3179    """
3180    Module function to retrieve the Templates related settings.
3181
3182    @param key the key of the value to get
3183    @param prefClass preferences class used as the storage area
3184    @return the requested user setting
3185    """
3186    if key in ["SeparatorChar"]:
3187        return prefClass.settings.value(
3188            "Templates/" + key, prefClass.templatesDefaults[key])
3189    elif key in ["EditorFont"]:
3190        f = QFont()
3191        f.fromString(prefClass.settings.value(
3192            "Templates/" + key, prefClass.templatesDefaults[key]))
3193        return f
3194    else:
3195        return toBool(prefClass.settings.value(
3196            "Templates/" + key, prefClass.templatesDefaults[key]))
3197
3198
3199def setTemplates(key, value, prefClass=Prefs):
3200    """
3201    Module function to store the Templates related settings.
3202
3203    @param key the key of the setting to be set
3204    @param value the value to be set
3205    @param prefClass preferences class used as the storage area
3206    """
3207    if key in ["EditorFont"]:
3208        prefClass.settings.setValue("Templates/" + key, value.toString())
3209    else:
3210        prefClass.settings.setValue("Templates/" + key, value)
3211
3212
3213def getPluginManager(key, prefClass=Prefs):
3214    """
3215    Module function to retrieve the plugin manager related settings.
3216
3217    @param key the key of the value to get
3218    @param prefClass preferences class used as the storage area
3219    @return the requested user setting
3220    """
3221    if key in ["DownloadPath"]:
3222        return prefClass.settings.value(
3223            "PluginManager/" + key, prefClass.pluginManagerDefaults[key])
3224    elif key in ["UpdatesCheckInterval", "KeepGenerations"]:
3225        return int(prefClass.settings.value(
3226            "PluginManager/" + key, prefClass.pluginManagerDefaults[key]))
3227    elif key in ["HiddenPlugins"]:
3228        return toList(prefClass.settings.value(
3229            "PluginManager/" + key, prefClass.pluginManagerDefaults[key]))
3230    else:
3231        return toBool(prefClass.settings.value(
3232            "PluginManager/" + key, prefClass.pluginManagerDefaults[key]))
3233
3234
3235def setPluginManager(key, value, prefClass=Prefs):
3236    """
3237    Module function to store the plugin manager related settings.
3238
3239    @param key the key of the setting to be set
3240    @param value the value to be set
3241    @param prefClass preferences class used as the storage area
3242    """
3243    prefClass.settings.setValue("PluginManager/" + key, value)
3244
3245
3246def getGraphics(key, prefClass=Prefs):
3247    """
3248    Module function to retrieve the Graphics related settings.
3249
3250    @param key the key of the value to get
3251    @param prefClass preferences class used as the storage area
3252    @return the requested user setting
3253    """
3254    if key in ["Font"]:
3255        font = prefClass.settings.value(
3256            "Graphics/" + key, prefClass.graphicsDefaults[key])
3257        if isinstance(font, QFont):
3258            # workaround for an old bug in eric < 4.4
3259            return font
3260        else:
3261            f = QFont()
3262            f.fromString(font)
3263            return f
3264    else:
3265        return prefClass.settings.value(
3266            "Graphics/" + key, prefClass.graphicsDefaults[key])
3267
3268
3269def setGraphics(key, value, prefClass=Prefs):
3270    """
3271    Module function to store the Graphics related settings.
3272
3273    @param key the key of the setting to be set
3274    @param value the value to be set
3275    @param prefClass preferences class used as the storage area
3276    """
3277    if key in ["Font"]:
3278        prefClass.settings.setValue("Graphics/" + key, value.toString())
3279    else:
3280        prefClass.settings.setValue("Graphics/" + key, value)
3281
3282
3283def getIconEditor(key, prefClass=Prefs):
3284    """
3285    Module function to retrieve the Icon Editor related settings.
3286
3287    @param key the key of the value to get
3288    @param prefClass preferences class used as the storage area
3289    @return the requested user setting
3290    """
3291    return prefClass.settings.value(
3292        "IconEditor/" + key, prefClass.iconEditorDefaults[key])
3293
3294
3295def setIconEditor(key, value, prefClass=Prefs):
3296    """
3297    Module function to store the Icon Editor related settings.
3298
3299    @param key the key of the setting to be set
3300    @param value the value to be set
3301    @param prefClass preferences class used as the storage area
3302    """
3303    prefClass.settings.setValue("IconEditor/" + key, value)
3304
3305
3306def getFlakes(key, prefClass=Prefs):
3307    """
3308    Module function to retrieve the pyflakes related settings.
3309
3310    @param key the key of the value to get
3311    @param prefClass preferences class used as the storage area
3312    @return the requested user setting
3313    """
3314    if key in ["IncludeInSyntaxCheck", "IgnoreStarImportWarnings"]:
3315        return toBool(prefClass.settings.value("Py3Flakes/" + key,
3316                      prefClass.pyflakesDefaults[key]))
3317    else:
3318        return prefClass.settings.value(
3319            "Py3Flakes/" + key, prefClass.pyflakesDefaults[key])
3320
3321
3322def setFlakes(key, value, prefClass=Prefs):
3323    """
3324    Module function to store the pyflakes related settings.
3325
3326    @param key the key of the setting to be set
3327    @param value the value to be set
3328    @param prefClass preferences class used as the storage area
3329    """
3330    prefClass.settings.setValue("Py3Flakes/" + key, value)
3331
3332
3333def getTrayStarter(key, prefClass=Prefs):
3334    """
3335    Module function to retrieve the tray starter related settings.
3336
3337    @param key the key of the value to get
3338    @param prefClass preferences class used as the storage area
3339    @return the requested user setting
3340    """
3341    return prefClass.settings.value(
3342        "TrayStarter/" + key, prefClass.trayStarterDefaults[key])
3343
3344
3345def setTrayStarter(key, value, prefClass=Prefs):
3346    """
3347    Module function to store the tray starter related settings.
3348
3349    @param key the key of the setting to be set
3350    @param value the value to be set
3351    @param prefClass preferences class used as the storage area
3352    """
3353    prefClass.settings.setValue("TrayStarter/" + key, value)
3354
3355
3356def getIrc(key, prefClass=Prefs):
3357    """
3358    Module function to retrieve the IRC related settings.
3359
3360    @param key the key of the value to get
3361    @param prefClass preferences class used as the storage area
3362    @return the requested user setting
3363    """
3364    if key in ["TimestampIncludeDate", "ShowTimestamps", "ShowNotifications",
3365               "NotifyJoinPart", "NotifyMessage", "NotifyNick",
3366               "EnableIrcColours", "AutoUserInfoLookup",
3367               "MarkPositionWhenHidden", "AskOnShutdown"]:
3368        return toBool(prefClass.settings.value(
3369            "IRC/" + key, prefClass.ircDefaults[key]))
3370    elif key in ["AutoUserInfoMax", "AutoUserInfoInterval"]:
3371        return int(prefClass.settings.value(
3372            "IRC/" + key, prefClass.ircDefaults[key]))
3373    else:
3374        return prefClass.settings.value(
3375            "IRC/" + key, prefClass.ircDefaults[key])
3376
3377
3378def setIrc(key, value, prefClass=Prefs):
3379    """
3380    Module function to store the IRC related settings.
3381
3382    @param key the key of the setting to be set
3383    @param value the value to be set
3384    @param prefClass preferences class used as the storage area
3385    """
3386    prefClass.settings.setValue("IRC/" + key, value)
3387
3388
3389def getHexEditor(key, prefClass=Prefs):
3390    """
3391    Module function to retrieve the Hex Editor related settings.
3392
3393    @param key the key of the value to get
3394    @param prefClass preferences class used as the storage area
3395    @return the requested user setting
3396    """
3397    if key in ["AddressAreaWidth", "RecentNumber"]:
3398        return int(prefClass.settings.value(
3399            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
3400    elif key in ["ShowAddressArea", "ShowAsciiArea", "OpenInOverwriteMode",
3401                 "OpenReadOnly", "HighlightChanges"]:
3402        return toBool(prefClass.settings.value(
3403            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
3404    elif key in ["HighlightingBackGround", "HighlightingForeGround",
3405                 "SelectionBackGround", "SelectionForeGround",
3406                 "AddressAreaBackGround", "AddressAreaForeGround"]:
3407        return QColor(prefClass.settings.value(
3408            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
3409    elif key in ["Font"]:
3410        f = QFont()
3411        f.fromString(prefClass.settings.value(
3412            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
3413        return f
3414    else:
3415        return prefClass.settings.value(
3416            "HexEditor/" + key, prefClass.hexEditorDefaults[key])
3417
3418
3419def setHexEditor(key, value, prefClass=Prefs):
3420    """
3421    Module function to store the Hex Editor related settings.
3422
3423    @param key the key of the setting to be set
3424    @param value the value to be set
3425    @param prefClass preferences class used as the storage area
3426    """
3427    if key in ["HighlightingBackGround", "HighlightingForeGround",
3428               "SelectionBackGround", "SelectionForeGround",
3429               "AddressAreaBackGround", "AddressAreaForeGround"]:
3430        if value.alpha() < 255:
3431            val = "#{0:8x}".format(value.rgba())
3432        else:
3433            val = value.name()
3434        prefClass.settings.setValue("HexEditor/" + key, val)
3435    elif key in ["Font"]:
3436        prefClass.settings.setValue("HexEditor/" + key, value.toString())
3437    else:
3438        prefClass.settings.setValue("HexEditor/" + key, value)
3439
3440
3441def getDiffColour(key, prefClass=Prefs):
3442    """
3443    Module function to retrieve the colours for the diff highlighter.
3444
3445    @param key the key of the value to get
3446    @param prefClass preferences class used as the storage area
3447    @return the requested diff colour
3448    """
3449    col = prefClass.settings.value("Diff/" + key)
3450    if col is not None:
3451        if len(col) == 9:
3452            # color string with alpha
3453            return QColor.fromRgba(int(col[1:], 16))
3454        else:
3455            return QColor(col)
3456    else:
3457        return prefClass.diffColourDefaults[key]
3458
3459
3460def setDiffColour(key, value, prefClass=Prefs):
3461    """
3462    Module function to store the diff highlighter colours.
3463
3464    @param key the key of the colour to be set
3465    @param value the colour to be set
3466    @param prefClass preferences class used as the storage area
3467    """
3468    val = ("#{0:8x}".format(value.rgba())
3469           if value.alpha() < 255 else value.name())
3470    prefClass.settings.setValue("Diff/" + key, val)
3471
3472
3473def getDocuViewer(key, prefClass=Prefs):
3474    """
3475    Module function to retrieve the Code Documentation Viewer related settings.
3476
3477    @param key the key of the value to get
3478    @param prefClass preferences class used as the storage area
3479    @return the requested Code Documentation Viewer value
3480    """
3481    if key in ["ShowInfoAsRichText", "ShowInfoOnOpenParenthesis"]:
3482        return toBool(prefClass.settings.value(
3483            "CodeDocumentationViewer/" + key,
3484            prefClass.docuViewerDefaults[key]))
3485    else:
3486        return prefClass.settings.value(
3487            "CodeDocumentationViewer/" + key,
3488            prefClass.docuViewerDefaults[key])
3489
3490
3491def setDocuViewer(key, value, prefClass=Prefs):
3492    """
3493    Module function to store the Code Documentation Viewer related settings.
3494
3495    @param key the key of the setting to be set
3496    @param value the value to be set
3497    @param prefClass preferences class used as the storage area
3498    """
3499    prefClass.settings.setValue("CodeDocumentationViewer/" + key, value)
3500
3501
3502def getConda(key, prefClass=Prefs):
3503    """
3504    Module function to retrieve the conda related settings.
3505
3506    @param key the key of the value to get
3507    @param prefClass preferences class used as the storage area
3508    @return the requested conda value
3509    """
3510    return prefClass.settings.value(
3511        "Conda/" + key,
3512        prefClass.condaDefaults[key])
3513
3514
3515def setConda(key, value, prefClass=Prefs):
3516    """
3517    Module function to store the conda related settings.
3518
3519    @param key the key of the setting to be set
3520    @param value the value to be set
3521    @param prefClass preferences class used as the storage area
3522    """
3523    prefClass.settings.setValue("Conda/" + key, value)
3524
3525
3526def getPip(key, prefClass=Prefs):
3527    """
3528    Module function to retrieve the pip related settings.
3529
3530    @param key the key of the value to get
3531    @param prefClass preferences class used as the storage area
3532    @return the requested pip value
3533    """
3534    if key in ("ExcludeCondaEnvironments"):
3535        return toBool(prefClass.settings.value(
3536            "Pip/" + key,
3537            prefClass.pipDefaults[key]))
3538    else:
3539        return prefClass.settings.value(
3540            "Pip/" + key,
3541            prefClass.pipDefaults[key])
3542
3543
3544def setPip(key, value, prefClass=Prefs):
3545    """
3546    Module function to store the pip related settings.
3547
3548    @param key the key of the setting to be set
3549    @param value the value to be set
3550    @param prefClass preferences class used as the storage area
3551    """
3552    prefClass.settings.setValue("Pip/" + key, value)
3553
3554
3555def getMicroPython(key, prefClass=Prefs):
3556    """
3557    Module function to retrieve the MicroPython related settings.
3558
3559    @param key the key of the value to get
3560    @param prefClass preferences class used as the storage area
3561    @return the requested MicroPython value
3562    """
3563    if key in ("SerialTimeout", "ChartColorTheme"):
3564        return int(prefClass.settings.value(
3565            "MicroPython/" + key,
3566            prefClass.microPythonDefaults[key]))
3567    elif key in ["ReplLineWrap", "SyncTimeAfterConnect", "ShowHiddenLocal",
3568                 "ShowHiddenDevice"]:
3569        return toBool(prefClass.settings.value(
3570            "MicroPython/" + key,
3571            prefClass.microPythonDefaults[key]))
3572    elif key in ["IgnoredUnknownDevices", "ManualDevices"]:
3573        jsonStr = prefClass.settings.value(
3574            "MicroPython/" + key,
3575            prefClass.microPythonDefaults[key])
3576        if jsonStr:
3577            return json.loads(jsonStr)
3578        else:
3579            return None
3580    else:
3581        return prefClass.settings.value(
3582            "MicroPython/" + key,
3583            prefClass.microPythonDefaults[key])
3584
3585
3586def setMicroPython(key, value, prefClass=Prefs):
3587    """
3588    Module function to store the pip MicroPython settings.
3589
3590    @param key the key of the setting to be set
3591    @param value the value to be set
3592    @param prefClass preferences class used as the storage area
3593    """
3594    if key in ["IgnoredUnknownDevices", "ManualDevices"]:
3595        prefClass.settings.setValue(
3596            "MicroPython/" + key,
3597            json.dumps(value))
3598    else:
3599        prefClass.settings.setValue(
3600            "MicroPython/" + key,
3601            value)
3602
3603
3604def getGeometry(key, prefClass=Prefs):
3605    """
3606    Module function to retrieve the display geometry.
3607
3608    @param key the key of the value to get
3609    @param prefClass preferences class used as the storage area
3610    @return the requested geometry setting
3611    """
3612    if key in ["MainMaximized"]:
3613        return toBool(prefClass.settings.value(
3614            "Geometry/" + key,
3615            prefClass.geometryDefaults[key]))
3616    else:
3617        v = prefClass.settings.value("Geometry/" + key)
3618        if v is not None:
3619            return v
3620        else:
3621            return prefClass.geometryDefaults[key]
3622
3623
3624def setGeometry(key, value, prefClass=Prefs):
3625    """
3626    Module function to store the display geometry.
3627
3628    @param key the key of the setting to be set
3629    @param value the geometry to be set
3630    @param prefClass preferences class used as the storage area
3631    """
3632    if key in ["MainMaximized"]:
3633        prefClass.settings.setValue("Geometry/" + key, value)
3634    else:
3635        if prefClass.resetLayout:
3636            v = prefClass.geometryDefaults[key]
3637        else:
3638            v = value
3639        prefClass.settings.setValue("Geometry/" + key, v)
3640
3641
3642def resetLayout(prefClass=Prefs):
3643    """
3644    Module function to set a flag not storing the current layout.
3645
3646    @param prefClass preferences class used as the storage area
3647    """
3648    prefClass.resetLayout = True
3649
3650
3651def shouldResetLayout(prefClass=Prefs):
3652    """
3653    Module function to indicate a reset of the layout.
3654
3655    @param prefClass preferences class used as the storage area
3656    @return flag indicating a reset of the layout (boolean)
3657    """
3658    return prefClass.resetLayout
3659
3660
3661def saveResetLayout(prefClass=Prefs):
3662    """
3663    Module function to save the reset layout.
3664
3665    @param prefClass preferences class used as the storage area
3666    """
3667    if prefClass.resetLayout:
3668        for key in list(prefClass.geometryDefaults.keys()):
3669            prefClass.settings.setValue(
3670                "Geometry/" + key,
3671                prefClass.geometryDefaults[key])
3672
3673
3674def toBool(value):
3675    """
3676    Module function to convert a value to bool.
3677
3678    @param value value to be converted
3679    @return converted data
3680    """
3681    if value in ["true", "1", "True"]:
3682        return True
3683    elif value in ["false", "0", "False"]:
3684        return False
3685    else:
3686        return bool(value)
3687
3688
3689def toList(value):
3690    """
3691    Module function to convert a value to a list.
3692
3693    @param value value to be converted
3694    @return converted data
3695    """
3696    if value is None:
3697        return []
3698    elif not isinstance(value, list):
3699        return [value]
3700    else:
3701        return value
3702
3703
3704def toByteArray(value):
3705    """
3706    Module function to convert a value to a byte array.
3707
3708    @param value value to be converted
3709    @return converted data
3710    """
3711    if value is None:
3712        return QByteArray()
3713    else:
3714        return value
3715
3716
3717def toDict(value):
3718    """
3719    Module function to convert a value to a dictionary.
3720
3721    @param value value to be converted
3722    @return converted data
3723    """
3724    if value is None:
3725        return {}
3726    else:
3727        return value
3728
3729
3730def convertPasswords(oldPassword, newPassword, prefClass=Prefs):
3731    """
3732    Module function to convert all passwords.
3733
3734    @param oldPassword current master password (string)
3735    @param newPassword new master password (string)
3736    @param prefClass preferences class used as the storage area
3737    """
3738    from Utilities.crypto import pwRecode
3739    for key in ["ProxyPassword/Http", "ProxyPassword/Https",
3740                "ProxyPassword/Ftp", ]:
3741        prefClass.settings.setValue(
3742            "UI/" + key,
3743            pwRecode(
3744                prefClass.settings.value("UI/" + key,
3745                                         prefClass.uiDefaults[key]),
3746                oldPassword,
3747                newPassword
3748            )
3749        )
3750    for key in ["MailServerPassword"]:
3751        prefClass.settings.setValue(
3752            "User/" + key,
3753            pwRecode(
3754                prefClass.settings.value("User/" + key,
3755                                         prefClass.userDefaults[key]),
3756                oldPassword,
3757                newPassword
3758            )
3759        )
3760    for key in ["SyncFtpPassword", "SyncEncryptionKey"]:
3761        prefClass.settings.setValue(
3762            "WebBrowser/" + key,
3763            pwRecode(
3764                prefClass.settings.value("WebBrowser/" + key,
3765                                         prefClass.webBrowserDefaults[key]),
3766                oldPassword,
3767                newPassword
3768            )
3769        )
3770
3771
3772initPreferences()
3773initRecentSettings()
3774
3775#
3776# eflag: noqa = M201, M613
3777