src/eric7/WebBrowser/SpellCheck/ManageDictionariesDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
13 import glob 13 import glob
14 import shutil 14 import shutil
15 import contextlib 15 import contextlib
16 16
17 from PyQt6.QtCore import pyqtSlot, Qt, QUrl 17 from PyQt6.QtCore import pyqtSlot, Qt, QUrl
18 from PyQt6.QtWidgets import ( 18 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, QListWidgetItem
19 QDialog, QDialogButtonBox, QAbstractButton, QListWidgetItem
20 )
21 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkInformation 19 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkInformation
22 20
23 from EricWidgets import EricMessageBox 21 from EricWidgets import EricMessageBox
24 22
25 from .Ui_ManageDictionariesDialog import Ui_ManageDictionariesDialog 23 from .Ui_ManageDictionariesDialog import Ui_ManageDictionariesDialog
31 29
32 class ManageDictionariesDialog(QDialog, Ui_ManageDictionariesDialog): 30 class ManageDictionariesDialog(QDialog, Ui_ManageDictionariesDialog):
33 """ 31 """
34 Class implementing a dialog to install spell checking dictionaries. 32 Class implementing a dialog to install spell checking dictionaries.
35 """ 33 """
34
36 FilenameRole = Qt.ItemDataRole.UserRole 35 FilenameRole = Qt.ItemDataRole.UserRole
37 UrlRole = Qt.ItemDataRole.UserRole + 1 36 UrlRole = Qt.ItemDataRole.UserRole + 1
38 DocumentationDirRole = Qt.ItemDataRole.UserRole + 2 37 DocumentationDirRole = Qt.ItemDataRole.UserRole + 2
39 LocalesRole = Qt.ItemDataRole.UserRole + 3 38 LocalesRole = Qt.ItemDataRole.UserRole + 3
40 39
41 def __init__(self, writeableDirectories, parent=None): 40 def __init__(self, writeableDirectories, parent=None):
42 """ 41 """
43 Constructor 42 Constructor
44 43
45 @param writeableDirectories list of writable directories 44 @param writeableDirectories list of writable directories
46 @type list of str 45 @type list of str
47 @param parent reference to the parent widget 46 @param parent reference to the parent widget
48 @type QWidget 47 @type QWidget
49 """ 48 """
50 super().__init__(parent) 49 super().__init__(parent)
51 self.setupUi(self) 50 self.setupUi(self)
52 51
53 self.__refreshButton = self.buttonBox.addButton( 52 self.__refreshButton = self.buttonBox.addButton(
54 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole) 53 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole
54 )
55 self.__installButton = self.buttonBox.addButton( 55 self.__installButton = self.buttonBox.addButton(
56 self.tr("Install Selected"), 56 self.tr("Install Selected"), QDialogButtonBox.ButtonRole.ActionRole
57 QDialogButtonBox.ButtonRole.ActionRole) 57 )
58 self.__installButton.setEnabled(False) 58 self.__installButton.setEnabled(False)
59 self.__uninstallButton = self.buttonBox.addButton( 59 self.__uninstallButton = self.buttonBox.addButton(
60 self.tr("Uninstall Selected"), 60 self.tr("Uninstall Selected"), QDialogButtonBox.ButtonRole.ActionRole
61 QDialogButtonBox.ButtonRole.ActionRole) 61 )
62 self.__uninstallButton.setEnabled(False) 62 self.__uninstallButton.setEnabled(False)
63 self.__cancelButton = self.buttonBox.addButton( 63 self.__cancelButton = self.buttonBox.addButton(
64 self.tr("Cancel"), QDialogButtonBox.ButtonRole.ActionRole) 64 self.tr("Cancel"), QDialogButtonBox.ButtonRole.ActionRole
65 )
65 self.__cancelButton.setEnabled(False) 66 self.__cancelButton.setEnabled(False)
66 67
67 self.locationComboBox.addItems(writeableDirectories) 68 self.locationComboBox.addItems(writeableDirectories)
68 69
69 self.dictionariesUrlEdit.setText( 70 self.dictionariesUrlEdit.setText(
70 Preferences.getWebBrowser("SpellCheckDictionariesUrl")) 71 Preferences.getWebBrowser("SpellCheckDictionariesUrl")
71 72 )
72 if ( 73
73 Preferences.getUI("DynamicOnlineCheck") and 74 if Preferences.getUI("DynamicOnlineCheck") and QNetworkInformation.load(
74 QNetworkInformation.load(QNetworkInformation.Feature.Reachability) 75 QNetworkInformation.Feature.Reachability
75 ): 76 ):
76 self.__reachabilityChanged( 77 self.__reachabilityChanged(QNetworkInformation.instance().reachability())
77 QNetworkInformation.instance().reachability())
78 QNetworkInformation.instance().reachabilityChanged.connect( 78 QNetworkInformation.instance().reachabilityChanged.connect(
79 self.__reachabilityChanged) 79 self.__reachabilityChanged
80 )
80 else: 81 else:
81 # assume to be 'always online' if no backend could be loaded or 82 # assume to be 'always online' if no backend could be loaded or
82 # dynamic online check is switched of 83 # dynamic online check is switched of
83 self.__reachabilityChanged(QNetworkInformation.Reachability.Online) 84 self.__reachabilityChanged(QNetworkInformation.Reachability.Online)
84 self.__replies = [] 85 self.__replies = []
85 86
86 self.__downloadCancelled = False 87 self.__downloadCancelled = False
87 self.__dictionariesToDownload = [] 88 self.__dictionariesToDownload = []
88 89
89 self.__populateList() 90 self.__populateList()
90 91
91 def __reachabilityChanged(self, reachability): 92 def __reachabilityChanged(self, reachability):
92 """ 93 """
93 Private slot handling reachability state changes. 94 Private slot handling reachability state changes.
94 95
95 @param reachability new reachability state 96 @param reachability new reachability state
96 @type QNetworkInformation.Reachability 97 @type QNetworkInformation.Reachability
97 """ 98 """
98 online = reachability == QNetworkInformation.Reachability.Online 99 online = reachability == QNetworkInformation.Reachability.Online
99 self.__online = online 100 self.__online = online
100 101
101 self.__refreshButton.setEnabled(online) 102 self.__refreshButton.setEnabled(online)
102 103
103 msg = ( 104 msg = (
104 self.tr("Internet Reachability Status: Reachable") 105 self.tr("Internet Reachability Status: Reachable")
105 if online else 106 if online
106 self.tr("Internet Reachability Status: Not Reachable") 107 else self.tr("Internet Reachability Status: Not Reachable")
107 ) 108 )
108 self.statusLabel.setText(msg) 109 self.statusLabel.setText(msg)
109 110
110 self.on_dictionariesList_itemSelectionChanged() 111 self.on_dictionariesList_itemSelectionChanged()
111 112
112 @pyqtSlot(QAbstractButton) 113 @pyqtSlot(QAbstractButton)
113 def on_buttonBox_clicked(self, button): 114 def on_buttonBox_clicked(self, button):
114 """ 115 """
115 Private slot to handle the click of a button of the button box. 116 Private slot to handle the click of a button of the button box.
116 117
117 @param button reference to the button pressed 118 @param button reference to the button pressed
118 @type QAbstractButton 119 @type QAbstractButton
119 """ 120 """
120 if button == self.__refreshButton: 121 if button == self.__refreshButton:
121 self.__populateList() 122 self.__populateList()
123 self.__downloadCancel() 124 self.__downloadCancel()
124 elif button == self.__installButton: 125 elif button == self.__installButton:
125 self.__installSelected() 126 self.__installSelected()
126 elif button == self.__uninstallButton: 127 elif button == self.__uninstallButton:
127 self.__uninstallSelected() 128 self.__uninstallSelected()
128 129
129 @pyqtSlot() 130 @pyqtSlot()
130 def on_dictionariesList_itemSelectionChanged(self): 131 def on_dictionariesList_itemSelectionChanged(self):
131 """ 132 """
132 Private slot to handle a change of the selection. 133 Private slot to handle a change of the selection.
133 """ 134 """
134 self.__installButton.setEnabled( 135 self.__installButton.setEnabled(
135 self.locationComboBox.count() > 0 and 136 self.locationComboBox.count() > 0
136 len(self.dictionariesList.selectedItems()) > 0 and 137 and len(self.dictionariesList.selectedItems()) > 0
137 self.__online 138 and self.__online
138 ) 139 )
139 140
140 self.__uninstallButton.setEnabled( 141 self.__uninstallButton.setEnabled(
141 self.locationComboBox.count() > 0 and 142 self.locationComboBox.count() > 0
142 len([itm 143 and len(
143 for itm in self.dictionariesList.selectedItems() 144 [
144 if itm.checkState() == Qt.CheckState.Checked 145 itm
145 ]) 146 for itm in self.dictionariesList.selectedItems()
146 ) 147 if itm.checkState() == Qt.CheckState.Checked
147 148 ]
149 )
150 )
151
148 @pyqtSlot(bool) 152 @pyqtSlot(bool)
149 def on_dictionariesUrlEditButton_toggled(self, checked): 153 def on_dictionariesUrlEditButton_toggled(self, checked):
150 """ 154 """
151 Private slot to set the read only status of the dictionaries URL line 155 Private slot to set the read only status of the dictionaries URL line
152 edit. 156 edit.
153 157
154 @param checked state of the push button (boolean) 158 @param checked state of the push button (boolean)
155 """ 159 """
156 self.dictionariesUrlEdit.setReadOnly(not checked) 160 self.dictionariesUrlEdit.setReadOnly(not checked)
157 161
158 @pyqtSlot(str) 162 @pyqtSlot(str)
159 def on_locationComboBox_currentTextChanged(self, txt): 163 def on_locationComboBox_currentTextChanged(self, txt):
160 """ 164 """
161 Private slot to handle a change of the installation location. 165 Private slot to handle a change of the installation location.
162 166
163 @param txt installation location 167 @param txt installation location
164 @type str 168 @type str
165 """ 169 """
166 self.__checkInstalledDictionaries() 170 self.__checkInstalledDictionaries()
167 171
168 def __populateList(self): 172 def __populateList(self):
169 """ 173 """
170 Private method to populate the list of available plugins. 174 Private method to populate the list of available plugins.
171 """ 175 """
172 self.dictionariesList.clear() 176 self.dictionariesList.clear()
173 self.downloadProgress.setValue(0) 177 self.downloadProgress.setValue(0)
174 178
175 url = self.dictionariesUrlEdit.text() 179 url = self.dictionariesUrlEdit.text()
176 180
177 if self.__online: 181 if self.__online:
178 self.__refreshButton.setEnabled(False) 182 self.__refreshButton.setEnabled(False)
179 self.__installButton.setEnabled(False) 183 self.__installButton.setEnabled(False)
180 self.__uninstallButton.setEnabled(False) 184 self.__uninstallButton.setEnabled(False)
181 self.__cancelButton.setEnabled(True) 185 self.__cancelButton.setEnabled(True)
182 186
183 self.statusLabel.setText(url) 187 self.statusLabel.setText(url)
184 188
185 self.__downloadCancelled = False 189 self.__downloadCancelled = False
186 190
187 request = QNetworkRequest(QUrl(url)) 191 request = QNetworkRequest(QUrl(url))
188 request.setAttribute( 192 request.setAttribute(
189 QNetworkRequest.Attribute.CacheLoadControlAttribute, 193 QNetworkRequest.Attribute.CacheLoadControlAttribute,
190 QNetworkRequest.CacheLoadControl.AlwaysNetwork) 194 QNetworkRequest.CacheLoadControl.AlwaysNetwork,
195 )
191 reply = WebBrowserWindow.networkManager().get(request) 196 reply = WebBrowserWindow.networkManager().get(request)
192 reply.finished.connect( 197 reply.finished.connect(lambda: self.__listFileDownloaded(reply))
193 lambda: self.__listFileDownloaded(reply))
194 reply.downloadProgress.connect(self.__downloadProgress) 198 reply.downloadProgress.connect(self.__downloadProgress)
195 self.__replies.append(reply) 199 self.__replies.append(reply)
196 else: 200 else:
197 EricMessageBox.warning( 201 EricMessageBox.warning(
198 self, 202 self,
199 self.tr("Error populating list of dictionaries"), 203 self.tr("Error populating list of dictionaries"),
200 self.tr( 204 self.tr(
201 """<p>Could not download the dictionaries list""" 205 """<p>Could not download the dictionaries list"""
202 """ from {0}.</p><p>Error: {1}</p>""" 206 """ from {0}.</p><p>Error: {1}</p>"""
203 ).format(url, self.tr("No connection to Internet."))) 207 ).format(url, self.tr("No connection to Internet.")),
204 208 )
209
205 def __listFileDownloaded(self, reply): 210 def __listFileDownloaded(self, reply):
206 """ 211 """
207 Private method called, after the dictionaries list file has been 212 Private method called, after the dictionaries list file has been
208 downloaded from the Internet. 213 downloaded from the Internet.
209 214
210 @param reply reference to the network reply 215 @param reply reference to the network reply
211 @type QNetworkReply 216 @type QNetworkReply
212 """ 217 """
213 self.__refreshButton.setEnabled(True) 218 self.__refreshButton.setEnabled(True)
214 self.__cancelButton.setEnabled(False) 219 self.__cancelButton.setEnabled(False)
215 220
216 self.downloadProgress.setValue(0) 221 self.downloadProgress.setValue(0)
217 222
218 if reply in self.__replies: 223 if reply in self.__replies:
219 self.__replies.remove(reply) 224 self.__replies.remove(reply)
220 reply.deleteLater() 225 reply.deleteLater()
221 226
222 if reply.error() != QNetworkReply.NetworkError.NoError: 227 if reply.error() != QNetworkReply.NetworkError.NoError:
223 if not self.__downloadCancelled: 228 if not self.__downloadCancelled:
224 EricMessageBox.warning( 229 EricMessageBox.warning(
225 self, 230 self,
226 self.tr("Error downloading dictionaries list"), 231 self.tr("Error downloading dictionaries list"),
227 self.tr( 232 self.tr(
228 """<p>Could not download the dictionaries list""" 233 """<p>Could not download the dictionaries list"""
229 """ from {0}.</p><p>Error: {1}</p>""" 234 """ from {0}.</p><p>Error: {1}</p>"""
230 ).format(self.dictionariesUrlEdit.text(), 235 ).format(self.dictionariesUrlEdit.text(), reply.errorString()),
231 reply.errorString())
232 ) 236 )
233 self.downloadProgress.setValue(0) 237 self.downloadProgress.setValue(0)
234 return 238 return
235 239
236 listFileData = reply.readAll() 240 listFileData = reply.readAll()
237 241
238 # extract the dictionaries 242 # extract the dictionaries
239 from EricXML.SpellCheckDictionariesReader import ( 243 from EricXML.SpellCheckDictionariesReader import SpellCheckDictionariesReader
240 SpellCheckDictionariesReader 244
241 )
242 reader = SpellCheckDictionariesReader(listFileData, self.addEntry) 245 reader = SpellCheckDictionariesReader(listFileData, self.addEntry)
243 reader.readXML() 246 reader.readXML()
244 url = Preferences.getWebBrowser("SpellCheckDictionariesUrl") 247 url = Preferences.getWebBrowser("SpellCheckDictionariesUrl")
245 if url != self.dictionariesUrlEdit.text(): 248 if url != self.dictionariesUrlEdit.text():
246 self.dictionariesUrlEdit.setText(url) 249 self.dictionariesUrlEdit.setText(url)
249 self.tr("Dictionaries URL Changed"), 252 self.tr("Dictionaries URL Changed"),
250 self.tr( 253 self.tr(
251 """The URL of the spell check dictionaries has""" 254 """The URL of the spell check dictionaries has"""
252 """ changed. Select the "Refresh" button to get""" 255 """ changed. Select the "Refresh" button to get"""
253 """ the new dictionaries list.""" 256 """ the new dictionaries list."""
254 ) 257 ),
255 ) 258 )
256 259
257 if self.locationComboBox.count() == 0: 260 if self.locationComboBox.count() == 0:
258 # no writable locations available 261 # no writable locations available
259 EricMessageBox.warning( 262 EricMessageBox.warning(
260 self, 263 self,
261 self.tr("Error installing dictionaries"), 264 self.tr("Error installing dictionaries"),
262 self.tr( 265 self.tr(
263 """<p>None of the dictionary locations is writable by""" 266 """<p>None of the dictionary locations is writable by"""
264 """ you. Please download required dictionaries manually""" 267 """ you. Please download required dictionaries manually"""
265 """ and install them as administrator.</p>""" 268 """ and install them as administrator.</p>"""
266 ) 269 ),
267 ) 270 )
268 271
269 self.__checkInstalledDictionaries() 272 self.__checkInstalledDictionaries()
270 273
271 def __downloadCancel(self): 274 def __downloadCancel(self):
272 """ 275 """
273 Private slot to cancel the current download. 276 Private slot to cancel the current download.
274 """ 277 """
275 if self.__replies: 278 if self.__replies:
276 reply = self.__replies[0] 279 reply = self.__replies[0]
277 self.__downloadCancelled = True 280 self.__downloadCancelled = True
278 self.__dictionariesToDownload = [] 281 self.__dictionariesToDownload = []
279 reply.abort() 282 reply.abort()
280 283
281 def __downloadProgress(self, done, total): 284 def __downloadProgress(self, done, total):
282 """ 285 """
283 Private slot to show the download progress. 286 Private slot to show the download progress.
284 287
285 @param done number of bytes downloaded so far 288 @param done number of bytes downloaded so far
286 @type int 289 @type int
287 @param total total bytes to be downloaded 290 @param total total bytes to be downloaded
288 @type int 291 @type int
289 """ 292 """
290 if total: 293 if total:
291 self.downloadProgress.setMaximum(total) 294 self.downloadProgress.setMaximum(total)
292 self.downloadProgress.setValue(done) 295 self.downloadProgress.setValue(done)
293 296
294 def addEntry(self, short, filename, url, documentationDir, locales): 297 def addEntry(self, short, filename, url, documentationDir, locales):
295 """ 298 """
296 Public method to add an entry to the list. 299 Public method to add an entry to the list.
297 300
298 @param short data for the description field 301 @param short data for the description field
299 @type str 302 @type str
300 @param filename data for the filename field 303 @param filename data for the filename field
301 @type str 304 @type str
302 @param url download URL for the dictionary entry 305 @param url download URL for the dictionary entry
306 @type str 309 @type str
307 @param locales list of locales 310 @param locales list of locales
308 @type list of str 311 @type list of str
309 """ 312 """
310 itm = QListWidgetItem( 313 itm = QListWidgetItem(
311 self.tr("{0} ({1})").format(short, " ".join(locales)), 314 self.tr("{0} ({1})").format(short, " ".join(locales)), self.dictionariesList
312 self.dictionariesList) 315 )
313 itm.setCheckState(Qt.CheckState.Unchecked) 316 itm.setCheckState(Qt.CheckState.Unchecked)
314 317
315 itm.setData(ManageDictionariesDialog.FilenameRole, filename) 318 itm.setData(ManageDictionariesDialog.FilenameRole, filename)
316 itm.setData(ManageDictionariesDialog.UrlRole, url) 319 itm.setData(ManageDictionariesDialog.UrlRole, url)
317 itm.setData(ManageDictionariesDialog.DocumentationDirRole, 320 itm.setData(ManageDictionariesDialog.DocumentationDirRole, documentationDir)
318 documentationDir)
319 itm.setData(ManageDictionariesDialog.LocalesRole, locales) 321 itm.setData(ManageDictionariesDialog.LocalesRole, locales)
320 322
321 def __checkInstalledDictionaries(self): 323 def __checkInstalledDictionaries(self):
322 """ 324 """
323 Private method to check all installed dictionaries. 325 Private method to check all installed dictionaries.
324 326
325 Note: A dictionary is assumed to be installed, if at least one of its 327 Note: A dictionary is assumed to be installed, if at least one of its
326 binary dictionaries (*.bdic) is found in the selected dictionaries 328 binary dictionaries (*.bdic) is found in the selected dictionaries
327 location. 329 location.
328 """ 330 """
329 if self.locationComboBox.currentText(): 331 if self.locationComboBox.currentText():
331 os.path.splitext(os.path.basename(dic))[0] 333 os.path.splitext(os.path.basename(dic))[0]
332 for dic in glob.glob( 334 for dic in glob.glob(
333 os.path.join(self.locationComboBox.currentText(), "*.bdic") 335 os.path.join(self.locationComboBox.currentText(), "*.bdic")
334 ) 336 )
335 } 337 }
336 338
337 for row in range(self.dictionariesList.count()): 339 for row in range(self.dictionariesList.count()):
338 itm = self.dictionariesList.item(row) 340 itm = self.dictionariesList.item(row)
339 locales = set(itm.data(ManageDictionariesDialog.LocalesRole)) 341 locales = set(itm.data(ManageDictionariesDialog.LocalesRole))
340 if locales.intersection(installedLocales): 342 if locales.intersection(installedLocales):
341 itm.setCheckState(Qt.CheckState.Checked) 343 itm.setCheckState(Qt.CheckState.Checked)
343 itm.setCheckState(Qt.CheckState.Unchecked) 345 itm.setCheckState(Qt.CheckState.Unchecked)
344 else: 346 else:
345 for row in range(self.dictionariesList.count()): 347 for row in range(self.dictionariesList.count()):
346 itm = self.dictionariesList.item(row) 348 itm = self.dictionariesList.item(row)
347 itm.setCheckState(Qt.CheckState.Unchecked) 349 itm.setCheckState(Qt.CheckState.Unchecked)
348 350
349 def __installSelected(self): 351 def __installSelected(self):
350 """ 352 """
351 Private method to install the selected dictionaries. 353 Private method to install the selected dictionaries.
352 """ 354 """
353 if self.__online and bool(self.locationComboBox.currentText()): 355 if self.__online and bool(self.locationComboBox.currentText()):
354 self.__dictionariesToDownload = [ 356 self.__dictionariesToDownload = [
355 itm.data(ManageDictionariesDialog.UrlRole) 357 itm.data(ManageDictionariesDialog.UrlRole)
356 for itm in self.dictionariesList.selectedItems() 358 for itm in self.dictionariesList.selectedItems()
357 ] 359 ]
358 360
359 self.__refreshButton.setEnabled(False) 361 self.__refreshButton.setEnabled(False)
360 self.__installButton.setEnabled(False) 362 self.__installButton.setEnabled(False)
361 self.__uninstallButton.setEnabled(False) 363 self.__uninstallButton.setEnabled(False)
362 self.__cancelButton.setEnabled(True) 364 self.__cancelButton.setEnabled(True)
363 365
364 self.__downloadCancelled = False 366 self.__downloadCancelled = False
365 367
366 self.__downloadDictionary() 368 self.__downloadDictionary()
367 369
368 def __downloadDictionary(self): 370 def __downloadDictionary(self):
369 """ 371 """
370 Private slot to download a dictionary. 372 Private slot to download a dictionary.
371 """ 373 """
372 if self.__online: 374 if self.__online:
373 if self.__dictionariesToDownload: 375 if self.__dictionariesToDownload:
374 url = self.__dictionariesToDownload.pop(0) 376 url = self.__dictionariesToDownload.pop(0)
375 self.statusLabel.setText(url) 377 self.statusLabel.setText(url)
376 378
377 self.__downloadCancelled = False 379 self.__downloadCancelled = False
378 380
379 request = QNetworkRequest(QUrl(url)) 381 request = QNetworkRequest(QUrl(url))
380 request.setAttribute( 382 request.setAttribute(
381 QNetworkRequest.Attribute.CacheLoadControlAttribute, 383 QNetworkRequest.Attribute.CacheLoadControlAttribute,
382 QNetworkRequest.CacheLoadControl.AlwaysNetwork) 384 QNetworkRequest.CacheLoadControl.AlwaysNetwork,
385 )
383 reply = WebBrowserWindow.networkManager().get(request) 386 reply = WebBrowserWindow.networkManager().get(request)
384 reply.finished.connect( 387 reply.finished.connect(lambda: self.__installDictionary(reply))
385 lambda: self.__installDictionary(reply))
386 reply.downloadProgress.connect(self.__downloadProgress) 388 reply.downloadProgress.connect(self.__downloadProgress)
387 self.__replies.append(reply) 389 self.__replies.append(reply)
388 else: 390 else:
389 self.__installationFinished() 391 self.__installationFinished()
390 else: 392 else:
392 self, 394 self,
393 self.tr("Error downloading dictionary file"), 395 self.tr("Error downloading dictionary file"),
394 self.tr( 396 self.tr(
395 """<p>Could not download the requested dictionary file""" 397 """<p>Could not download the requested dictionary file"""
396 """ from {0}.</p><p>Error: {1}</p>""" 398 """ from {0}.</p><p>Error: {1}</p>"""
397 ).format(url, self.tr("No connection to Internet."))) 399 ).format(url, self.tr("No connection to Internet.")),
398 400 )
401
399 self.__installationFinished() 402 self.__installationFinished()
400 403
401 def __installDictionary(self, reply): 404 def __installDictionary(self, reply):
402 """ 405 """
403 Private slot to install the downloaded dictionary. 406 Private slot to install the downloaded dictionary.
404 407
405 @param reply reference to the network reply 408 @param reply reference to the network reply
406 @type QNetworkReply 409 @type QNetworkReply
407 """ 410 """
408 if reply in self.__replies: 411 if reply in self.__replies:
409 self.__replies.remove(reply) 412 self.__replies.remove(reply)
410 reply.deleteLater() 413 reply.deleteLater()
411 414
412 if reply.error() != QNetworkReply.NetworkError.NoError: 415 if reply.error() != QNetworkReply.NetworkError.NoError:
413 if not self.__downloadCancelled: 416 if not self.__downloadCancelled:
414 EricMessageBox.warning( 417 EricMessageBox.warning(
415 self, 418 self,
416 self.tr("Error downloading dictionary file"), 419 self.tr("Error downloading dictionary file"),
417 self.tr( 420 self.tr(
418 """<p>Could not download the requested dictionary""" 421 """<p>Could not download the requested dictionary"""
419 """ file from {0}.</p><p>Error: {1}</p>""" 422 """ file from {0}.</p><p>Error: {1}</p>"""
420 ).format(reply.url(), reply.errorString()) 423 ).format(reply.url(), reply.errorString()),
421 ) 424 )
422 self.downloadProgress.setValue(0) 425 self.downloadProgress.setValue(0)
423 return 426 return
424 427
425 archiveData = reply.readAll() 428 archiveData = reply.readAll()
426 archiveFile = io.BytesIO(bytes(archiveData)) 429 archiveFile = io.BytesIO(bytes(archiveData))
427 archive = zipfile.ZipFile(archiveFile, "r") 430 archive = zipfile.ZipFile(archiveFile, "r")
428 if archive.testzip() is not None: 431 if archive.testzip() is not None:
429 EricMessageBox.critical( 432 EricMessageBox.critical(
430 self, 433 self,
431 self.tr("Error downloading dictionary"), 434 self.tr("Error downloading dictionary"),
432 self.tr( 435 self.tr(
433 """<p>The downloaded dictionary archive is invalid.""" 436 """<p>The downloaded dictionary archive is invalid."""
434 """ Skipping it.</p>""") 437 """ Skipping it.</p>"""
438 ),
435 ) 439 )
436 else: 440 else:
437 installDir = self.locationComboBox.currentText() 441 installDir = self.locationComboBox.currentText()
438 archive.extractall(installDir) 442 archive.extractall(installDir)
439 443
440 if self.__dictionariesToDownload: 444 if self.__dictionariesToDownload:
441 self.__downloadDictionary() 445 self.__downloadDictionary()
442 else: 446 else:
443 self.__installationFinished() 447 self.__installationFinished()
444 448
445 def __installationFinished(self): 449 def __installationFinished(self):
446 """ 450 """
447 Private method called after all selected dictionaries have been 451 Private method called after all selected dictionaries have been
448 installed. 452 installed.
449 """ 453 """
450 self.__refreshButton.setEnabled(True) 454 self.__refreshButton.setEnabled(True)
451 self.__cancelButton.setEnabled(False) 455 self.__cancelButton.setEnabled(False)
452 456
453 self.dictionariesList.clearSelection() 457 self.dictionariesList.clearSelection()
454 self.downloadProgress.setValue(0) 458 self.downloadProgress.setValue(0)
455 459
456 self.__checkInstalledDictionaries() 460 self.__checkInstalledDictionaries()
457 461
458 def __uninstallSelected(self): 462 def __uninstallSelected(self):
459 """ 463 """
460 Private method to uninstall the selected dictionaries. 464 Private method to uninstall the selected dictionaries.
461 """ 465 """
462 installLocation = self.locationComboBox.currentText() 466 installLocation = self.locationComboBox.currentText()
463 if not installLocation: 467 if not installLocation:
464 return 468 return
465 469
466 itemsToDelete = [ 470 itemsToDelete = [
467 itm 471 itm
468 for itm in self.dictionariesList.selectedItems() 472 for itm in self.dictionariesList.selectedItems()
469 if itm.checkState() == Qt.CheckState.Checked 473 if itm.checkState() == Qt.CheckState.Checked
470 ] 474 ]
471 for itm in itemsToDelete: 475 for itm in itemsToDelete:
472 documentationDir = itm.data( 476 documentationDir = itm.data(ManageDictionariesDialog.DocumentationDirRole)
473 ManageDictionariesDialog.DocumentationDirRole) 477 shutil.rmtree(os.path.join(installLocation, documentationDir), True)
474 shutil.rmtree(os.path.join(installLocation, documentationDir), 478
475 True)
476
477 locales = itm.data(ManageDictionariesDialog.LocalesRole) 479 locales = itm.data(ManageDictionariesDialog.LocalesRole)
478 for locale in locales: 480 for locale in locales:
479 bdic = os.path.join(installLocation, locale + ".bdic") 481 bdic = os.path.join(installLocation, locale + ".bdic")
480 with contextlib.suppress(OSError): 482 with contextlib.suppress(OSError):
481 os.remove(bdic) 483 os.remove(bdic)
482 484
483 self.dictionariesList.clearSelection() 485 self.dictionariesList.clearSelection()
484 486
485 self.__checkInstalledDictionaries() 487 self.__checkInstalledDictionaries()

eric ide

mercurial