src/eric7/Preferences/ThemeManager.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2021 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a manager object for color themes.
8 """
9
10 import json
11 import os
12 import re
13
14 from PyQt6.QtCore import QObject
15
16 from EricWidgets import EricMessageBox, EricFileDialog
17
18 import Globals
19 import Preferences
20
21 from eric7config import getConfig
22
23
24 class ThemeManager(QObject):
25 """
26 Class implementing a manager object for color themes.
27 """
28 ColorKeyPatternList = [
29 "Diff/.*Color",
30 "Editor/Colour/",
31 "IRC/.*Colou?r",
32 "Project/Colour",
33 "Python/.*Color",
34 "Scintilla/.*color",
35 "Scintilla/.*paper",
36 "Tasks/.*Color",
37 "WebBrowser/.*Colou?r",
38 ]
39 ColorKeyList = [
40 "Debugger/BgColorChanged",
41 "Debugger/BgColorNew",
42 "UI/IconBarColor",
43 "UI/LogStdErrColour",
44 "UI/NotificationCriticalBackground",
45 "UI/NotificationCriticalForeground",
46 "UI/NotificationWarningBackground",
47 "UI/NotificationWarningForeground",
48 ]
49
50 def __init__(self: "ThemeManager", parent: QObject = None):
51 """
52 Constructor
53
54 @param parent reference to the parent object (defaults to None)
55 @type QObject (optional)
56 """
57 super().__init__(parent)
58
59 def importTheme(self: "ThemeManager") -> bool:
60 """
61 Public method to import a theme file and set the colors.
62
63 @return flag indicating a successful import
64 @rtype bool
65 """
66 filename = EricFileDialog.getOpenFileName(
67 None,
68 self.tr("Import Theme"),
69 getConfig("ericThemesDir"),
70 self.tr("eric Theme Files (*.ethj);;All Files (*)")
71 )
72 if filename:
73 try:
74 with open(filename, "r") as f:
75 jsonString = f.read()
76 themeDict = json.loads(jsonString)
77 except (TypeError, OSError) as err:
78 EricMessageBox.critical(
79 None,
80 self.tr("Import Theme"),
81 self.tr(
82 "<p>The theme file <b>{0}</b> could not"
83 " be read.</p><p>Reason: {1}</p>"
84 ).format(filename, str(err))
85 )
86 return False
87
88 # step 1: process stylesheet data
89 stylesheetDict = themeDict["stylesheet"]
90 if stylesheetDict["name"]:
91 stylesheetsDir = os.path.join(
92 Globals.getConfigDir(), "stylesheets")
93 if not os.path.exists(stylesheetsDir):
94 os.makedirs(stylesheetsDir)
95 stylesheetFile = os.path.join(
96 stylesheetsDir, stylesheetDict["name"])
97 ok = EricMessageBox.yesNo(
98 None,
99 self.tr("Import Theme"),
100 self.tr(
101 "The stylesheet file {0} exists already."
102 " Shall it be overwritten?"
103 ).format(stylesheetDict["name"])
104 ) if os.path.exists(stylesheetFile) else True
105 if ok:
106 try:
107 with open(stylesheetFile, "w") as f:
108 f.write(stylesheetDict["contents"])
109 except OSError as err:
110 EricMessageBox.critical(
111 None,
112 self.tr("Import Theme"),
113 self.tr(
114 "<p>The stylesheet file <b>{0}</b> could"
115 " not be written.</p><p>Reason: {1}</p>"
116 ).format(stylesheetFile, str(err))
117 )
118 stylesheetFile = ""
119 Preferences.setUI("StyleSheet", stylesheetFile)
120
121 # step 2: transfer the color entries
122 settings = Preferences.getSettings()
123 colorsDict = themeDict["colors"]
124 for key, value in colorsDict.items():
125 settings.setValue(key, value)
126
127 Preferences.syncPreferences()
128 return True
129
130 return False
131
132 def exportTheme(self: "ThemeManager"):
133 """
134 Public method to export the current colors to a theme file.
135 """
136 filename, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
137 None,
138 self.tr("Export Theme"),
139 os.path.expanduser("~"),
140 self.tr("eric Theme Files (*.ethj)"),
141 "",
142 EricFileDialog.DontConfirmOverwrite
143 )
144 if filename:
145 ext = os.path.splitext(filename)[1]
146 if not ext:
147 filename = "{0}{1}".format(
148 filename,
149 selectedFilter.rsplit(None, 1)[-1][2:-1])
150
151 ok = (
152 EricMessageBox.yesNo(
153 None,
154 self.tr("Export Theme"),
155 self.tr(
156 """<p>The theme file <b>{0}</b> exists"""
157 """ already. Overwrite it?</p>""").format(filename))
158 if os.path.exists(filename) else
159 True
160 )
161
162 if ok:
163 # step 1: generate a dictionary with all color settings
164 settings = Preferences.getSettings()
165 colorKeyFilterRe = re.compile("|".join(
166 ThemeManager.ColorKeyPatternList +
167 ThemeManager.ColorKeyList
168 ))
169
170 keys = [k for k in settings.allKeys()
171 if colorKeyFilterRe.match(k)]
172 colorsDict = {}
173 for key in keys:
174 colorsDict[key] = settings.value(key)
175
176 # step 2: read the contents of the current stylesheet
177 stylesheetDict = {
178 "contents": "",
179 "name": ""
180 }
181 stylesheet = Preferences.getUI("StyleSheet")
182 if stylesheet and os.path.exists(stylesheet):
183 try:
184 with open(stylesheet, "r") as f:
185 stylesheetDict["contents"] = f.read()
186 stylesheetDict["name"] = os.path.basename(stylesheet)
187 except OSError as err:
188 EricMessageBox.critical(
189 None,
190 self.tr("Export Theme"),
191 self.tr(
192 "<p>The stylesheet file <b>{0}</b> could not"
193 " be read.</p><p>Reason: {1}</p>"
194 ).format(stylesheet, str(err))
195 )
196
197 themeDict = {
198 "colors": colorsDict,
199 "stylesheet": stylesheetDict,
200 }
201
202 try:
203 jsonString = json.dumps(themeDict, indent=2)
204 with open(filename, "w") as f:
205 f.write(jsonString)
206 except (TypeError, OSError) as err:
207 EricMessageBox.critical(
208 None,
209 self.tr("Export Theme"),
210 self.tr(
211 "<p>The theme file <b>{0}</b> could not"
212 " be written.</p><p>Reason: {1}</p>"
213 ).format(filename, str(err))
214 )

eric ide

mercurial