src/eric7/WebBrowser/Tools/WebIconProvider.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
9 9
10 import json 10 import json
11 import os 11 import os
12 import contextlib 12 import contextlib
13 13
14 from PyQt6.QtCore import ( 14 from PyQt6.QtCore import pyqtSignal, QObject, QByteArray, QBuffer, QIODevice, QUrl
15 pyqtSignal, QObject, QByteArray, QBuffer, QIODevice, QUrl
16 )
17 from PyQt6.QtGui import QIcon, QPixmap, QImage 15 from PyQt6.QtGui import QIcon, QPixmap, QImage
18 from PyQt6.QtWidgets import QDialog 16 from PyQt6.QtWidgets import QDialog
19 17
20 from Utilities.AutoSaver import AutoSaver 18 from Utilities.AutoSaver import AutoSaver
21 19
23 21
24 22
25 class WebIconProvider(QObject): 23 class WebIconProvider(QObject):
26 """ 24 """
27 Class implementing a web site icon storage. 25 Class implementing a web site icon storage.
28 26
29 @signal changed() emitted to indicate a change of the icons database 27 @signal changed() emitted to indicate a change of the icons database
30 """ 28 """
29
31 changed = pyqtSignal() 30 changed = pyqtSignal()
32 31
33 def __init__(self, parent=None): 32 def __init__(self, parent=None):
34 """ 33 """
35 Constructor 34 Constructor
36 35
37 @param parent reference to the parent object (QObject) 36 @param parent reference to the parent object (QObject)
38 """ 37 """
39 super().__init__(parent) 38 super().__init__(parent)
40 39
41 self.__encoding = "iso-8859-1" 40 self.__encoding = "iso-8859-1"
42 self.__iconsFileName = "web_site_icons.json" 41 self.__iconsFileName = "web_site_icons.json"
43 self.__iconDatabasePath = "" # saving of icons disabled 42 self.__iconDatabasePath = "" # saving of icons disabled
44 43
45 self.__iconsDB = {} 44 self.__iconsDB = {}
46 self.__loaded = False 45 self.__loaded = False
47 46
48 self.__saveTimer = AutoSaver(self, self.save) 47 self.__saveTimer = AutoSaver(self, self.save)
49 48
50 self.changed.connect(self.__saveTimer.changeOccurred) 49 self.changed.connect(self.__saveTimer.changeOccurred)
51 50
52 def setIconDatabasePath(self, path): 51 def setIconDatabasePath(self, path):
53 """ 52 """
54 Public method to set the path for the web site icons store. 53 Public method to set the path for the web site icons store.
55 54
56 @param path path to store the icons file to 55 @param path path to store the icons file to
57 @type str 56 @type str
58 """ 57 """
59 if path != self.__iconDatabasePath: 58 if path != self.__iconDatabasePath:
60 self.close() 59 self.close()
61 60
62 self.__iconDatabasePath = path 61 self.__iconDatabasePath = path
63 62
64 def iconDatabasePath(self): 63 def iconDatabasePath(self):
65 """ 64 """
66 Public method o get the path for the web site icons store. 65 Public method o get the path for the web site icons store.
67 66
68 @return path to store the icons file to 67 @return path to store the icons file to
69 @rtype str 68 @rtype str
70 """ 69 """
71 return self.__iconDatabasePath 70 return self.__iconDatabasePath
72 71
73 def close(self): 72 def close(self):
74 """ 73 """
75 Public method to close the web icon provider. 74 Public method to close the web icon provider.
76 """ 75 """
77 self.__saveTimer.saveIfNeccessary() 76 self.__saveTimer.saveIfNeccessary()
78 self.__loaded = False 77 self.__loaded = False
79 self.__iconsDB = {} 78 self.__iconsDB = {}
80 79
81 def load(self): 80 def load(self):
82 """ 81 """
83 Public method to load the web site icons. 82 Public method to load the web site icons.
84 """ 83 """
85 if self.__loaded: 84 if self.__loaded:
86 return 85 return
87 86
88 if self.__iconDatabasePath: 87 if self.__iconDatabasePath:
89 filename = os.path.join(self.__iconDatabasePath, 88 filename = os.path.join(self.__iconDatabasePath, self.__iconsFileName)
90 self.__iconsFileName)
91 try: 89 try:
92 with open(filename, "r") as f: 90 with open(filename, "r") as f:
93 db = json.load(f) 91 db = json.load(f)
94 except OSError: 92 except OSError:
95 # ignore silentyl 93 # ignore silentyl
96 db = {} 94 db = {}
97 95
98 self.__iconsDB = {} 96 self.__iconsDB = {}
99 for url, data in db.items(): 97 for url, data in db.items():
100 self.__iconsDB[url] = QIcon(QPixmap.fromImage(QImage.fromData( 98 self.__iconsDB[url] = QIcon(
101 QByteArray(data.encode(self.__encoding))))) 99 QPixmap.fromImage(
102 100 QImage.fromData(QByteArray(data.encode(self.__encoding)))
101 )
102 )
103
103 self.__loaded = True 104 self.__loaded = True
104 105
105 def save(self): 106 def save(self):
106 """ 107 """
107 Public method to save the web site icons. 108 Public method to save the web site icons.
108 """ 109 """
109 if not self.__loaded: 110 if not self.__loaded:
110 return 111 return
111 112
112 from WebBrowser.WebBrowserWindow import WebBrowserWindow 113 from WebBrowser.WebBrowserWindow import WebBrowserWindow
114
113 if not WebBrowserWindow.isPrivate() and bool(self.__iconDatabasePath): 115 if not WebBrowserWindow.isPrivate() and bool(self.__iconDatabasePath):
114 db = {} 116 db = {}
115 for url, icon in self.__iconsDB.items(): 117 for url, icon in self.__iconsDB.items():
116 ba = QByteArray() 118 ba = QByteArray()
117 buffer = QBuffer(ba) 119 buffer = QBuffer(ba)
118 buffer.open(QIODevice.OpenModeFlag.WriteOnly) 120 buffer.open(QIODevice.OpenModeFlag.WriteOnly)
119 icon.pixmap(32).toImage().save(buffer, "PNG") 121 icon.pixmap(32).toImage().save(buffer, "PNG")
120 db[url] = bytes(buffer.data()).decode(self.__encoding) 122 db[url] = bytes(buffer.data()).decode(self.__encoding)
121 123
122 filename = os.path.join(self.__iconDatabasePath, 124 filename = os.path.join(self.__iconDatabasePath, self.__iconsFileName)
123 self.__iconsFileName)
124 with contextlib.suppress(OSError), open(filename, "w") as f: 125 with contextlib.suppress(OSError), open(filename, "w") as f:
125 json.dump(db, f) 126 json.dump(db, f)
126 127
127 def saveIcon(self, view): 128 def saveIcon(self, view):
128 """ 129 """
129 Public method to save a web site icon. 130 Public method to save a web site icon.
130 131
131 @param view reference to the view object 132 @param view reference to the view object
132 @type WebBrowserView 133 @type WebBrowserView
133 """ 134 """
134 scheme = view.url().scheme() 135 scheme = view.url().scheme()
135 if scheme in ["eric", "about", "qthelp", "file", "abp", "ftp"]: 136 if scheme in ["eric", "about", "qthelp", "file", "abp", "ftp"]:
136 return 137 return
137 138
138 self.load() 139 self.load()
139 140
140 if view.mainWindow().isPrivate(): 141 if view.mainWindow().isPrivate():
141 return 142 return
142 143
143 urlStr = self.__urlToString(view.url()) 144 urlStr = self.__urlToString(view.url())
144 self.__iconsDB[urlStr] = view.icon() 145 self.__iconsDB[urlStr] = view.icon()
145 146
146 self.changed.emit() 147 self.changed.emit()
147 148
148 def __urlToString(self, url): 149 def __urlToString(self, url):
149 """ 150 """
150 Private method to convert an URL to a string. 151 Private method to convert an URL to a string.
151 152
152 @param url URL to be converted 153 @param url URL to be converted
153 @type QUrl 154 @type QUrl
154 @return string representation of the URL 155 @return string representation of the URL
155 @rtype str 156 @rtype str
156 """ 157 """
157 return url.toString( 158 return url.toString(
158 QUrl.UrlFormattingOption.RemoveUserInfo | 159 QUrl.UrlFormattingOption.RemoveUserInfo
159 QUrl.UrlFormattingOption.RemoveFragment | 160 | QUrl.UrlFormattingOption.RemoveFragment
160 QUrl.UrlFormattingOption.RemovePath 161 | QUrl.UrlFormattingOption.RemovePath
161 ) 162 )
162 163
163 def iconForUrl(self, url): 164 def iconForUrl(self, url):
164 """ 165 """
165 Public method to get an icon for an URL. 166 Public method to get an icon for an URL.
166 167
167 @param url URL to get icon for 168 @param url URL to get icon for
168 @type QUrl 169 @type QUrl
169 @return icon for the URL 170 @return icon for the URL
170 @rtype QIcon 171 @rtype QIcon
171 """ 172 """
175 "qthelp": "qthelp", 176 "qthelp": "qthelp",
176 "file": "fileMisc", 177 "file": "fileMisc",
177 "abp": "adBlockPlus", 178 "abp": "adBlockPlus",
178 "ftp": "network-server", 179 "ftp": "network-server",
179 } 180 }
180 181
181 scheme = url.scheme() 182 scheme = url.scheme()
182 iconName = scheme2iconName.get(scheme) 183 iconName = scheme2iconName.get(scheme)
183 if iconName: 184 if iconName:
184 return UI.PixmapCache.getIcon(iconName) 185 return UI.PixmapCache.getIcon(iconName)
185 186
186 self.load() 187 self.load()
187 188
188 urlStr = self.__urlToString(url) 189 urlStr = self.__urlToString(url)
189 if urlStr in self.__iconsDB: 190 if urlStr in self.__iconsDB:
190 return self.__iconsDB[urlStr] 191 return self.__iconsDB[urlStr]
191 else: 192 else:
192 for iconUrlStr in self.__iconsDB: 193 for iconUrlStr in self.__iconsDB:
193 if iconUrlStr.startswith(urlStr): 194 if iconUrlStr.startswith(urlStr):
194 return self.__iconsDB[iconUrlStr] 195 return self.__iconsDB[iconUrlStr]
195 196
196 # try replacing http scheme with https scheme 197 # try replacing http scheme with https scheme
197 url = QUrl(url) 198 url = QUrl(url)
198 if url.scheme() == "http": 199 if url.scheme() == "http":
199 url.setScheme("https") 200 url.setScheme("https")
200 urlStr = self.__urlToString(url) 201 urlStr = self.__urlToString(url)
202 return self.__iconsDB[urlStr] 203 return self.__iconsDB[urlStr]
203 else: 204 else:
204 for iconUrlStr in self.__iconsDB: 205 for iconUrlStr in self.__iconsDB:
205 if iconUrlStr.startswith(urlStr): 206 if iconUrlStr.startswith(urlStr):
206 return self.__iconsDB[iconUrlStr] 207 return self.__iconsDB[iconUrlStr]
207 208
208 if scheme == "https": 209 if scheme == "https":
209 return UI.PixmapCache.getIcon("securityHigh32") 210 return UI.PixmapCache.getIcon("securityHigh32")
210 else: 211 else:
211 return UI.PixmapCache.getIcon("defaultIcon") 212 return UI.PixmapCache.getIcon("defaultIcon")
212 213
213 def clear(self): 214 def clear(self):
214 """ 215 """
215 Public method to clear the icons cache. 216 Public method to clear the icons cache.
216 """ 217 """
217 self.load() 218 self.load()
218 self.__iconsDB = {} 219 self.__iconsDB = {}
219 self.changed.emit() 220 self.changed.emit()
220 self.__saveTimer.saveIfNeccessary() 221 self.__saveTimer.saveIfNeccessary()
221 222
222 def showWebIconDialog(self): 223 def showWebIconDialog(self):
223 """ 224 """
224 Public method to show a dialog to manage the Favicons. 225 Public method to show a dialog to manage the Favicons.
225 """ 226 """
226 self.load() 227 self.load()
227 228
228 from .WebIconDialog import WebIconDialog 229 from .WebIconDialog import WebIconDialog
230
229 dlg = WebIconDialog(self.__iconsDB) 231 dlg = WebIconDialog(self.__iconsDB)
230 if dlg.exec() == QDialog.DialogCode.Accepted: 232 if dlg.exec() == QDialog.DialogCode.Accepted:
231 changed = False 233 changed = False
232 urls = dlg.getUrls() 234 urls = dlg.getUrls()
233 for url in list(self.__iconsDB.keys())[:]: 235 for url in list(self.__iconsDB.keys())[:]:
243 245
244 def instance(): 246 def instance():
245 """ 247 """
246 Global function to get a reference to the web icon provider and create it, 248 Global function to get a reference to the web icon provider and create it,
247 if it hasn't been yet. 249 if it hasn't been yet.
248 250
249 @return reference to the web icon provider object 251 @return reference to the web icon provider object
250 @rtype WebIconProvider 252 @rtype WebIconProvider
251 """ 253 """
252 global _WebIconProvider 254 global _WebIconProvider
253 255
254 if _WebIconProvider is None: 256 if _WebIconProvider is None:
255 _WebIconProvider = WebIconProvider() 257 _WebIconProvider = WebIconProvider()
256 258
257 return _WebIconProvider 259 return _WebIconProvider

eric ide

mercurial