|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to install spell checking dictionaries. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 from PyQt5.QtCore import pyqtSlot, Qt, QUrl |
|
13 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ |
|
14 QListWidgetItem |
|
15 from PyQt5.QtNetwork import QNetworkConfigurationManager, QNetworkRequest, \ |
|
16 QNetworkReply |
|
17 |
|
18 from E5Gui import E5MessageBox |
|
19 |
|
20 from .Ui_InstallDictionariesDialog import Ui_InstallDictionariesDialog |
|
21 |
|
22 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
23 |
|
24 import Preferences |
|
25 |
|
26 |
|
27 class InstallDictionariesDialog(QDialog, Ui_InstallDictionariesDialog): |
|
28 """ |
|
29 Class implementing a dialog to install spell checking dictionaries. |
|
30 """ |
|
31 FilenameRole = Qt.UserRole |
|
32 |
|
33 def __init__(self, writeableDirectories, parent=None): |
|
34 """ |
|
35 Constructor |
|
36 |
|
37 @param writeableDirectories list of writable directories |
|
38 @type list of str |
|
39 @param parent reference to the parent widget |
|
40 @type QWidget |
|
41 """ |
|
42 super(InstallDictionariesDialog, self).__init__(parent) |
|
43 self.setupUi(self) |
|
44 |
|
45 self.__refreshButton = self.buttonBox.addButton( |
|
46 self.tr("Refresh"), QDialogButtonBox.ActionRole) |
|
47 self.__installButton = self.buttonBox.addButton( |
|
48 self.tr("Install Selected"), QDialogButtonBox.ActionRole) |
|
49 self.__installButton.setEnabled(False) |
|
50 self.__cancelButton = self.buttonBox.addButton( |
|
51 self.tr("Cancel"), QDialogButtonBox.ActionRole) |
|
52 self.__cancelButton.setEnabled(False) |
|
53 |
|
54 self.locationComboBox.addItems(writeableDirectories) |
|
55 |
|
56 self.dictionariesUrlEdit.setText( |
|
57 Preferences.getWebBrowser("SpellCheckDictionariesUrl")) |
|
58 |
|
59 if Preferences.getUI("DynamicOnlineCheck"): |
|
60 self.__networkConfigurationManager = \ |
|
61 QNetworkConfigurationManager(self) |
|
62 self.__onlineStateChanged( |
|
63 self.__networkConfigurationManager.isOnline()) |
|
64 self.__networkConfigurationManager.onlineStateChanged.connect( |
|
65 self.__onlineStateChanged) |
|
66 else: |
|
67 self.__networkConfigurationManager = None |
|
68 self.__onlineStateChanged(True) |
|
69 self.__replies = [] |
|
70 |
|
71 self.__downloadCancelled = False |
|
72 self.__dictionariesToDownload = [] |
|
73 |
|
74 self.__populateList() |
|
75 |
|
76 @pyqtSlot(bool) |
|
77 def __onlineStateChanged(self, online): |
|
78 """ |
|
79 Private slot handling online state changes. |
|
80 |
|
81 @param online flag indicating the online status |
|
82 @type bool |
|
83 """ |
|
84 self.__refreshButton.setEnabled(online) |
|
85 if online: |
|
86 msg = self.tr("Network Status: online") |
|
87 else: |
|
88 msg = self.tr("Network Status: offline") |
|
89 self.statusLabel.setText(msg) |
|
90 |
|
91 def __isOnline(self): |
|
92 """ |
|
93 Private method to check the online status. |
|
94 |
|
95 @return flag indicating the online status |
|
96 @rtype bool |
|
97 """ |
|
98 if self.__networkConfigurationManager is not None: |
|
99 return self.__networkConfigurationManager.isOnline() |
|
100 else: |
|
101 return True |
|
102 |
|
103 @pyqtSlot(QAbstractButton) |
|
104 def on_buttonBox_clicked(self, button): |
|
105 """ |
|
106 Private slot to handle the click of a button of the button box. |
|
107 |
|
108 @param button reference to the button pressed |
|
109 @type QAbstractButton |
|
110 """ |
|
111 if button == self.__refreshButton: |
|
112 self.__populateList() |
|
113 elif button == self.__cancelButton: |
|
114 self.__downloadCancel() |
|
115 elif button == self.__installButton: |
|
116 self.__installSelected() |
|
117 |
|
118 @pyqtSlot() |
|
119 def on_dictionariesList_itemSelectionChanged(self): |
|
120 """ |
|
121 Private slot to handle a change of the selection. |
|
122 """ |
|
123 self.__installButton.setEnabled( |
|
124 len(self.dictionariesList.selectedItems()) > 0) |
|
125 |
|
126 def __populateList(self): |
|
127 """ |
|
128 Private method to populate the list of available plugins. |
|
129 """ |
|
130 self.dictionariesList.clear() |
|
131 self.downloadProgress.setValue(0) |
|
132 |
|
133 if self.__isOnline(): |
|
134 self.__refreshButton.setEnabled(False) |
|
135 self.__installButton.setEnabled(False) |
|
136 self.__cancelButton.setEnabled(True) |
|
137 |
|
138 url = self.dictionariesUrlEdit.text() |
|
139 self.statusLabel.setText(url) |
|
140 |
|
141 self.__downloadCancelled = False |
|
142 |
|
143 request = QNetworkRequest(QUrl(url)) |
|
144 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, |
|
145 QNetworkRequest.AlwaysNetwork) |
|
146 reply = WebBrowserWindow.networkManager().get(request) |
|
147 reply.finished.connect(self.__listFileDownloaded) |
|
148 reply.downloadProgress.connect(self.__downloadProgress) |
|
149 self.__replies.append(reply) |
|
150 |
|
151 def __listFileDownloaded(self): |
|
152 """ |
|
153 Private method called, after the dictionaries list file has been |
|
154 downloaded from the Internet. |
|
155 """ |
|
156 self.__refreshButton.setEnabled(True) |
|
157 self.__cancelButton.setEnabled(False) |
|
158 self.__onlineStateChanged(self.__isOnline()) |
|
159 |
|
160 reply = self.sender() |
|
161 if reply in self.__replies: |
|
162 self.__replies.remove(reply) |
|
163 if reply.error() != QNetworkReply.NoError: |
|
164 if not self.__downloadCancelled: |
|
165 E5MessageBox.warning( |
|
166 self, |
|
167 self.tr("Error downloading dictionaries list"), |
|
168 self.tr( |
|
169 """<p>Could not download the dictionaries list""" |
|
170 """ from {0}.</p><p>Error: {1}</p>""" |
|
171 ).format(self.repositoryUrlEdit.text(), |
|
172 reply.errorString()) |
|
173 ) |
|
174 self.downloadProgress.setValue(0) |
|
175 reply.deleteLater() |
|
176 return |
|
177 |
|
178 listFileData = reply.readAll() |
|
179 reply.deleteLater() |
|
180 |
|
181 # extract the dictionaries |
|
182 from E5XML.SpellCheckDictionariesReader import \ |
|
183 SpellCheckDictionariesReader |
|
184 reader = SpellCheckDictionariesReader(listFileData, self.addEntry) |
|
185 reader.readXML() |
|
186 url = Preferences.getWebBrowser("SpellCheckDictionariesUrl") |
|
187 if url != self.dictionariesUrlEdit.text(): |
|
188 self.dictionariesUrlEdit.setText(url) |
|
189 E5MessageBox.warning( |
|
190 self, |
|
191 self.tr("Dictionaries URL Changed"), |
|
192 self.tr( |
|
193 """The URL of the spell check dictionaries has""" |
|
194 """ changed. Select the "Refresh" button to get""" |
|
195 """ the new dictionaries list.""")) |
|
196 |
|
197 def __downloadCancel(self): |
|
198 """ |
|
199 Private slot to cancel the current download. |
|
200 """ |
|
201 if self.__replies: |
|
202 reply = self.__replies[0] |
|
203 self.__downloadCancelled = True |
|
204 self.__dictionariesToDownload = [] |
|
205 reply.abort() |
|
206 |
|
207 def __downloadProgress(self, done, total): |
|
208 """ |
|
209 Private slot to show the download progress. |
|
210 |
|
211 @param done number of bytes downloaded so far |
|
212 @type int |
|
213 @param total total bytes to be downloaded |
|
214 @type int |
|
215 """ |
|
216 if total: |
|
217 self.downloadProgress.setMaximum(total) |
|
218 self.downloadProgress.setValue(done) |
|
219 |
|
220 def addEntry(self, short, filename): |
|
221 """ |
|
222 Public method to add an entry to the list. |
|
223 |
|
224 @param short data for the description field |
|
225 @type str |
|
226 @param filename data for the filename field |
|
227 @type str |
|
228 """ |
|
229 itm = QListWidgetItem(short, self.dictionariesList) |
|
230 itm.setData(InstallDictionariesDialog.FilenameRole, filename) |
|
231 |
|
232 def __installSelected(self): |
|
233 """ |
|
234 Private method to install the selected dictionaries. |
|
235 """ |
|
236 self.__dictionariesToDownload = [ |
|
237 itm.data(InstallDictionariesDialog.FilenameRole) |
|
238 for itm in self.dictionariesList.selectedItems() |
|
239 ] |
|
240 |
|
241 self.__refreshButton.setEnabled(False) |
|
242 self.__installButton.setEnabled(False) |
|
243 self.__cancelButton.setEnabled(True) |
|
244 |
|
245 self.__downloadCancelled = False |
|
246 |
|
247 self.__downloadDictionary() |
|
248 |
|
249 def __downloadDictionary(self): |
|
250 """ |
|
251 Private slot to download a dictionary. |
|
252 """ |
|
253 # TODO: implement this |
|
254 # use __installDictionary as finish slot |
|
255 |
|
256 def __installDictionary(self): |
|
257 """ |
|
258 Private slot to install the downloaded dictionary. |
|
259 """ |
|
260 # TODO: implement this |
|
261 |
|
262 if not bool(self.__dictionariesToDownload): |
|
263 self.__installationFinished() |
|
264 |
|
265 def __installationFinished(self): |
|
266 """ |
|
267 Private method called after all selected dictionaries have been |
|
268 installed. |
|
269 """ |
|
270 # TODO: implement this |