--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/SpellCheck/InstallDictionariesDialog.py Sat Sep 02 20:00:57 2017 +0200 @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to install spell checking dictionaries. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSlot, Qt, QUrl +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ + QListWidgetItem +from PyQt5.QtNetwork import QNetworkConfigurationManager, QNetworkRequest, \ + QNetworkReply + +from E5Gui import E5MessageBox + +from .Ui_InstallDictionariesDialog import Ui_InstallDictionariesDialog + +from WebBrowser.WebBrowserWindow import WebBrowserWindow + +import Preferences + + +class InstallDictionariesDialog(QDialog, Ui_InstallDictionariesDialog): + """ + Class implementing a dialog to install spell checking dictionaries. + """ + FilenameRole = Qt.UserRole + + def __init__(self, writeableDirectories, parent=None): + """ + Constructor + + @param writeableDirectories list of writable directories + @type list of str + @param parent reference to the parent widget + @type QWidget + """ + super(InstallDictionariesDialog, self).__init__(parent) + self.setupUi(self) + + self.__refreshButton = self.buttonBox.addButton( + self.tr("Refresh"), QDialogButtonBox.ActionRole) + self.__installButton = self.buttonBox.addButton( + self.tr("Install Selected"), QDialogButtonBox.ActionRole) + self.__installButton.setEnabled(False) + self.__cancelButton = self.buttonBox.addButton( + self.tr("Cancel"), QDialogButtonBox.ActionRole) + self.__cancelButton.setEnabled(False) + + self.locationComboBox.addItems(writeableDirectories) + + self.dictionariesUrlEdit.setText( + Preferences.getWebBrowser("SpellCheckDictionariesUrl")) + + if Preferences.getUI("DynamicOnlineCheck"): + self.__networkConfigurationManager = \ + QNetworkConfigurationManager(self) + self.__onlineStateChanged( + self.__networkConfigurationManager.isOnline()) + self.__networkConfigurationManager.onlineStateChanged.connect( + self.__onlineStateChanged) + else: + self.__networkConfigurationManager = None + self.__onlineStateChanged(True) + self.__replies = [] + + self.__downloadCancelled = False + self.__dictionariesToDownload = [] + + self.__populateList() + + @pyqtSlot(bool) + def __onlineStateChanged(self, online): + """ + Private slot handling online state changes. + + @param online flag indicating the online status + @type bool + """ + self.__refreshButton.setEnabled(online) + if online: + msg = self.tr("Network Status: online") + else: + msg = self.tr("Network Status: offline") + self.statusLabel.setText(msg) + + def __isOnline(self): + """ + Private method to check the online status. + + @return flag indicating the online status + @rtype bool + """ + if self.__networkConfigurationManager is not None: + return self.__networkConfigurationManager.isOnline() + else: + return True + + @pyqtSlot(QAbstractButton) + def on_buttonBox_clicked(self, button): + """ + Private slot to handle the click of a button of the button box. + + @param button reference to the button pressed + @type QAbstractButton + """ + if button == self.__refreshButton: + self.__populateList() + elif button == self.__cancelButton: + self.__downloadCancel() + elif button == self.__installButton: + self.__installSelected() + + @pyqtSlot() + def on_dictionariesList_itemSelectionChanged(self): + """ + Private slot to handle a change of the selection. + """ + self.__installButton.setEnabled( + len(self.dictionariesList.selectedItems()) > 0) + + def __populateList(self): + """ + Private method to populate the list of available plugins. + """ + self.dictionariesList.clear() + self.downloadProgress.setValue(0) + + if self.__isOnline(): + self.__refreshButton.setEnabled(False) + self.__installButton.setEnabled(False) + self.__cancelButton.setEnabled(True) + + url = self.dictionariesUrlEdit.text() + self.statusLabel.setText(url) + + self.__downloadCancelled = False + + request = QNetworkRequest(QUrl(url)) + request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, + QNetworkRequest.AlwaysNetwork) + reply = WebBrowserWindow.networkManager().get(request) + reply.finished.connect(self.__listFileDownloaded) + reply.downloadProgress.connect(self.__downloadProgress) + self.__replies.append(reply) + + def __listFileDownloaded(self): + """ + Private method called, after the dictionaries list file has been + downloaded from the Internet. + """ + self.__refreshButton.setEnabled(True) + self.__cancelButton.setEnabled(False) + self.__onlineStateChanged(self.__isOnline()) + + reply = self.sender() + if reply in self.__replies: + self.__replies.remove(reply) + if reply.error() != QNetworkReply.NoError: + if not self.__downloadCancelled: + E5MessageBox.warning( + self, + self.tr("Error downloading dictionaries list"), + self.tr( + """<p>Could not download the dictionaries list""" + """ from {0}.</p><p>Error: {1}</p>""" + ).format(self.repositoryUrlEdit.text(), + reply.errorString()) + ) + self.downloadProgress.setValue(0) + reply.deleteLater() + return + + listFileData = reply.readAll() + reply.deleteLater() + + # extract the dictionaries + from E5XML.SpellCheckDictionariesReader import \ + SpellCheckDictionariesReader + reader = SpellCheckDictionariesReader(listFileData, self.addEntry) + reader.readXML() + url = Preferences.getWebBrowser("SpellCheckDictionariesUrl") + if url != self.dictionariesUrlEdit.text(): + self.dictionariesUrlEdit.setText(url) + E5MessageBox.warning( + self, + self.tr("Dictionaries URL Changed"), + self.tr( + """The URL of the spell check dictionaries has""" + """ changed. Select the "Refresh" button to get""" + """ the new dictionaries list.""")) + + def __downloadCancel(self): + """ + Private slot to cancel the current download. + """ + if self.__replies: + reply = self.__replies[0] + self.__downloadCancelled = True + self.__dictionariesToDownload = [] + reply.abort() + + def __downloadProgress(self, done, total): + """ + Private slot to show the download progress. + + @param done number of bytes downloaded so far + @type int + @param total total bytes to be downloaded + @type int + """ + if total: + self.downloadProgress.setMaximum(total) + self.downloadProgress.setValue(done) + + def addEntry(self, short, filename): + """ + Public method to add an entry to the list. + + @param short data for the description field + @type str + @param filename data for the filename field + @type str + """ + itm = QListWidgetItem(short, self.dictionariesList) + itm.setData(InstallDictionariesDialog.FilenameRole, filename) + + def __installSelected(self): + """ + Private method to install the selected dictionaries. + """ + self.__dictionariesToDownload = [ + itm.data(InstallDictionariesDialog.FilenameRole) + for itm in self.dictionariesList.selectedItems() + ] + + self.__refreshButton.setEnabled(False) + self.__installButton.setEnabled(False) + self.__cancelButton.setEnabled(True) + + self.__downloadCancelled = False + + self.__downloadDictionary() + + def __downloadDictionary(self): + """ + Private slot to download a dictionary. + """ + # TODO: implement this + # use __installDictionary as finish slot + + def __installDictionary(self): + """ + Private slot to install the downloaded dictionary. + """ + # TODO: implement this + + if not bool(self.__dictionariesToDownload): + self.__installationFinished() + + def __installationFinished(self): + """ + Private method called after all selected dictionaries have been + installed. + """ + # TODO: implement this