8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 import sys |
11 import sys |
12 import imp |
12 import imp |
13 |
13 import zipfile |
14 from PyQt4.QtCore import pyqtSignal, QObject |
14 |
|
15 from PyQt4.QtCore import pyqtSignal, QObject, QDate, QFile, QUrl, QIODevice |
15 from PyQt4.QtGui import QPixmap |
16 from PyQt4.QtGui import QPixmap |
|
17 from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, \ |
|
18 QNetworkReply |
16 |
19 |
17 from E5Gui import E5MessageBox |
20 from E5Gui import E5MessageBox |
|
21 |
|
22 from E5Network.E5NetworkProxyFactory import proxyAuthenticationRequired |
|
23 try: |
|
24 from E5Network.E5SslErrorHandler import E5SslErrorHandler |
|
25 SSL_AVAILABLE = True |
|
26 except ImportError: |
|
27 SSL_AVAILABLE = False |
18 |
28 |
19 from .PluginExceptions import PluginPathError, PluginModulesError, \ |
29 from .PluginExceptions import PluginPathError, PluginModulesError, \ |
20 PluginLoadError, PluginActivationError, PluginModuleFormatError, \ |
30 PluginLoadError, PluginActivationError, PluginModuleFormatError, \ |
21 PluginClassFormatError |
31 PluginClassFormatError |
22 |
32 |
1013 def preferencesChanged(self): |
1035 def preferencesChanged(self): |
1014 """ |
1036 """ |
1015 Public slot to react to changes in configuration. |
1037 Public slot to react to changes in configuration. |
1016 """ |
1038 """ |
1017 self.__checkPluginsDownloadDirectory() |
1039 self.__checkPluginsDownloadDirectory() |
|
1040 |
|
1041 ######################################################################## |
|
1042 ## Methods for automatic plug-in update check below |
|
1043 ######################################################################## |
|
1044 |
|
1045 def checkPluginUpdatesAvailable(self): |
|
1046 """ |
|
1047 Public method to check the availability of updates of plug-ins. |
|
1048 """ |
|
1049 period = Preferences.getPluginManager("UpdatesCheckInterval") |
|
1050 if period == 0: |
|
1051 return |
|
1052 elif period in [2, 3, 4]: |
|
1053 lastCheck = Preferences.Prefs.settings.value( |
|
1054 "PluginUpdates/LastCheckDate", QDate(1970, 1, 1)) |
|
1055 if lastCheck.isValid(): |
|
1056 now = QDate.currentDate() |
|
1057 if period == 2 and lastCheck.day() == now.day(): |
|
1058 # daily |
|
1059 return |
|
1060 elif period == 3 and lastCheck.daysTo(now) < 7: |
|
1061 # weekly |
|
1062 return |
|
1063 elif period == 4 and lastCheck.month() == now.month(): |
|
1064 # monthly |
|
1065 return |
|
1066 |
|
1067 self.__updateAvailable = False |
|
1068 |
|
1069 request = QNetworkRequest( |
|
1070 QUrl(Preferences.getUI("PluginRepositoryUrl5"))) |
|
1071 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, |
|
1072 QNetworkRequest.AlwaysNetwork) |
|
1073 reply = self.__networkManager.get(request) |
|
1074 reply.finished[()].connect(self.__downloadFileDone) |
|
1075 reply.downloadProgress.connect(self.__downloadRepositoryFileDone) |
|
1076 self.__replies.append(reply) |
|
1077 |
|
1078 def __downloadRepositoryFileDone(self): |
|
1079 """ |
|
1080 Private method called after the repository file was downloaded. |
|
1081 """ |
|
1082 reply = self.sender() |
|
1083 if reply in self.__replies: |
|
1084 self.__replies.remove(reply) |
|
1085 if reply.error() != QNetworkReply.NoError: |
|
1086 E5MessageBox.warning( |
|
1087 None, |
|
1088 self.trUtf8("Error downloading file"), |
|
1089 self.trUtf8( |
|
1090 """<p>Could not download the requested file""" |
|
1091 """ from {0}.</p><p>Error: {1}</p>""" |
|
1092 ).format(Preferences.getUI("PluginRepositoryUrl5"), |
|
1093 reply.errorString()) |
|
1094 ) |
|
1095 return |
|
1096 |
|
1097 ioDevice = QFile(self.pluginRepositoryFile + ".tmp") |
|
1098 ioDevice.open(QIODevice.WriteOnly) |
|
1099 ioDevice.write(reply.readAll()) |
|
1100 ioDevice.close() |
|
1101 if QFile.exists(self.pluginRepositoryFile): |
|
1102 QFile.remove(self.pluginRepositoryFile) |
|
1103 ioDevice.rename(self.pluginRepositoryFile) |
|
1104 |
|
1105 if os.path.exists(self.pluginRepositoryFile): |
|
1106 f = QFile(self.pluginRepositoryFile) |
|
1107 if f.open(QIODevice.ReadOnly): |
|
1108 from E5XML.PluginRepositoryReader import PluginRepositoryReader |
|
1109 reader = PluginRepositoryReader(f, self) |
|
1110 reader.readXML() |
|
1111 url = Preferences.getUI("PluginRepositoryUrl5") |
|
1112 if url != self.repositoryUrlEdit.text(): |
|
1113 self.checkPluginUpdatesAvailable() |
|
1114 return |
|
1115 Preferences.Prefs.settings.setValue( |
|
1116 "Updates/LastCheckDate", QDate.currentDate()) |
|
1117 |
|
1118 if self.__updateAvailable: |
|
1119 E5MessageBox.information( |
|
1120 None, |
|
1121 self.trUtf8("New plugin versions available"), |
|
1122 self.trUtf8("<p>There are new plugins or plugin" |
|
1123 " updates available. Use the plugin" |
|
1124 " repository dialog to get them.</p>") |
|
1125 ) |
|
1126 |
|
1127 def addEntry(self, name, short, description, url, author, version, |
|
1128 filename, status): |
|
1129 """ |
|
1130 Public method to add an entry to the list. |
|
1131 |
|
1132 @param name data for the name field (string) |
|
1133 @param short data for the short field (string) |
|
1134 @param description data for the description field (list of strings) |
|
1135 @param url data for the url field (string) |
|
1136 @param author data for the author field (string) |
|
1137 @param version data for the version field (string) |
|
1138 @param filename data for the filename field (string) |
|
1139 @param status status of the plugin (string [stable, unstable, unknown]) |
|
1140 """ |
|
1141 archive = os.path.join(Preferences.getPluginManager("DownloadPath"), |
|
1142 filename) |
|
1143 |
|
1144 # check, if the archive exists |
|
1145 if not os.path.exists(archive) and \ |
|
1146 not Preferences.getPluginManager("CheckInstalledOnly"): |
|
1147 self.__updateAvailable = True |
|
1148 return |
|
1149 |
|
1150 # check, if the archive is a valid zip file |
|
1151 if not zipfile.is_zipfile(archive) and \ |
|
1152 not Preferences.getPluginManager("CheckInstalledOnly"): |
|
1153 self.__updateAvailable = True |
|
1154 return |
|
1155 |
|
1156 zip = zipfile.ZipFile(archive, "r") |
|
1157 try: |
|
1158 aversion = zip.read("VERSION").decode("utf-8") |
|
1159 except KeyError: |
|
1160 aversion = "" |
|
1161 zip.close() |
|
1162 |
|
1163 if aversion != version: |
|
1164 self.__updateAvailable = True |
|
1165 |
|
1166 def __sslErrors(self, reply, errors): |
|
1167 """ |
|
1168 Private slot to handle SSL errors. |
|
1169 |
|
1170 @param reply reference to the reply object (QNetworkReply) |
|
1171 @param errors list of SSL errors (list of QSslError) |
|
1172 """ |
|
1173 ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0] |
|
1174 if ignored == E5SslErrorHandler.NotIgnored: |
|
1175 self.__downloadCancelled = True |
|
1176 |
|
1177 # TODO: test this stuff |
|
1178 # TODO: update the config page |