46 Class implementing the Plugin Manager. |
46 Class implementing the Plugin Manager. |
47 |
47 |
48 @signal shutdown() emitted at shutdown of the IDE |
48 @signal shutdown() emitted at shutdown of the IDE |
49 @signal pluginAboutToBeActivated(modulName, pluginObject) emitted just |
49 @signal pluginAboutToBeActivated(modulName, pluginObject) emitted just |
50 before a plugin is activated |
50 before a plugin is activated |
51 @signal pluginActivated(modulName, pluginObject) emitted just after |
51 @signal pluginActivated(moduleName, pluginObject) emitted just after |
52 a plugin was activated |
52 a plugin was activated |
53 @signal allPlugginsActivated() emitted at startup after all plugins have |
53 @signal allPlugginsActivated() emitted at startup after all plugins have |
54 been activated |
54 been activated |
55 @signal pluginAboutToBeDeactivated(modulName, pluginObject) emitted just |
55 @signal pluginAboutToBeDeactivated(moduleName, pluginObject) emitted just |
56 before a plugin is deactivated |
56 before a plugin is deactivated |
57 @signal pluginDeactivated(modulName, pluginObject) emitted just after |
57 @signal pluginDeactivated(moduleName, pluginObject) emitted just after |
58 a plugin was deactivated |
58 a plugin was deactivated |
59 """ |
59 """ |
60 shutdown = pyqtSignal() |
60 shutdown = pyqtSignal() |
61 pluginAboutToBeActivated = pyqtSignal(str, object) |
61 pluginAboutToBeActivated = pyqtSignal(str, object) |
62 pluginActivated = pyqtSignal(str, object) |
62 pluginActivated = pyqtSignal(str, object) |
184 f = open(fname, "w") |
184 f = open(fname, "w") |
185 f.close() |
185 f.close() |
186 except IOError: |
186 except IOError: |
187 return ( |
187 return ( |
188 False, |
188 False, |
189 self.trUtf8("Could not create a package for {0}.") |
189 self.tr("Could not create a package for {0}.") |
190 .format(self.__develPluginFile)) |
190 .format(self.__develPluginFile)) |
191 |
191 |
192 if Preferences.getPluginManager("ActivateExternal"): |
192 if Preferences.getPluginManager("ActivateExternal"): |
193 fname = os.path.join(self.pluginDirs["user"], "__init__.py") |
193 fname = os.path.join(self.pluginDirs["user"], "__init__.py") |
194 if not os.path.exists(fname): |
194 if not os.path.exists(fname): |
336 """ |
336 """ |
337 try: |
337 try: |
338 fname = "{0}.py".format(os.path.join(directory, name)) |
338 fname = "{0}.py".format(os.path.join(directory, name)) |
339 module = imp.load_source(name, fname) |
339 module = imp.load_source(name, fname) |
340 if not hasattr(module, "autoactivate"): |
340 if not hasattr(module, "autoactivate"): |
341 module.error = self.trUtf8( |
341 module.error = self.tr( |
342 "Module is missing the 'autoactivate' attribute.") |
342 "Module is missing the 'autoactivate' attribute.") |
343 self.__failedModules[name] = module |
343 self.__failedModules[name] = module |
344 raise PluginLoadError(name) |
344 raise PluginLoadError(name) |
345 if getattr(module, "autoactivate"): |
345 if getattr(module, "autoactivate"): |
346 self.__inactiveModules[name] = module |
346 self.__inactiveModules[name] = module |
347 else: |
347 else: |
348 if not hasattr(module, "pluginType") or \ |
348 if not hasattr(module, "pluginType") or \ |
349 not hasattr(module, "pluginTypename"): |
349 not hasattr(module, "pluginTypename"): |
350 module.error = \ |
350 module.error = \ |
351 self.trUtf8("Module is missing the 'pluginType' " |
351 self.tr("Module is missing the 'pluginType' " |
352 "and/or 'pluginTypename' attributes.") |
352 "and/or 'pluginTypename' attributes.") |
353 self.__failedModules[name] = module |
353 self.__failedModules[name] = module |
354 raise PluginLoadError(name) |
354 raise PluginLoadError(name) |
355 else: |
355 else: |
356 self.__onDemandInactiveModules[name] = module |
356 self.__onDemandInactiveModules[name] = module |
357 module.eric5PluginModuleName = name |
357 module.eric5PluginModuleName = name |
361 imp.reload(module) |
361 imp.reload(module) |
362 except PluginLoadError: |
362 except PluginLoadError: |
363 print("Error loading plugin module:", name) |
363 print("Error loading plugin module:", name) |
364 except Exception as err: |
364 except Exception as err: |
365 module = imp.new_module(name) |
365 module = imp.new_module(name) |
366 module.error = self.trUtf8( |
366 module.error = self.tr( |
367 "Module failed to load. Error: {0}").format(str(err)) |
367 "Module failed to load. Error: {0}").format(str(err)) |
368 self.__failedModules[name] = module |
368 self.__failedModules[name] = module |
369 print("Error loading plugin module:", name) |
369 print("Error loading plugin module:", name) |
370 print(str(err)) |
370 print(str(err)) |
371 |
371 |
516 pluginObject = pluginClass(self.__ui) |
516 pluginObject = pluginClass(self.__ui) |
517 self.pluginAboutToBeActivated.emit(name, pluginObject) |
517 self.pluginAboutToBeActivated.emit(name, pluginObject) |
518 try: |
518 try: |
519 obj, ok = pluginObject.activate() |
519 obj, ok = pluginObject.activate() |
520 except TypeError: |
520 except TypeError: |
521 module.error = self.trUtf8( |
521 module.error = self.tr( |
522 "Incompatible plugin activation method.") |
522 "Incompatible plugin activation method.") |
523 obj = None |
523 obj = None |
524 ok = True |
524 ok = True |
525 except Exception as err: |
525 except Exception as err: |
526 module.error = str(err) |
526 module.error = str(err) |
1000 Public method to deactivated all activated VCS plugins. |
1000 Public method to deactivated all activated VCS plugins. |
1001 """ |
1001 """ |
1002 for name, module in list(self.__onDemandActiveModules.items()): |
1002 for name, module in list(self.__onDemandActiveModules.items()): |
1003 if getattr(module, "pluginType") == "version_control": |
1003 if getattr(module, "pluginType") == "version_control": |
1004 self.deactivatePlugin(name, True) |
1004 self.deactivatePlugin(name, True) |
1005 |
1005 |
|
1006 ######################################################################## |
|
1007 ## Methods creation of the plug-ins download directory |
|
1008 ######################################################################## |
|
1009 |
1006 def __checkPluginsDownloadDirectory(self): |
1010 def __checkPluginsDownloadDirectory(self): |
1007 """ |
1011 """ |
1008 Private slot to check for the existence of the plugins download |
1012 Private slot to check for the existence of the plugins download |
1009 directory. |
1013 directory. |
1010 """ |
1014 """ |
1022 try: |
1026 try: |
1023 os.mkdir(downloadDir, 0o755) |
1027 os.mkdir(downloadDir, 0o755) |
1024 except (OSError, IOError) as err: |
1028 except (OSError, IOError) as err: |
1025 E5MessageBox.critical( |
1029 E5MessageBox.critical( |
1026 self.__ui, |
1030 self.__ui, |
1027 self.trUtf8("Plugin Manager Error"), |
1031 self.tr("Plugin Manager Error"), |
1028 self.trUtf8( |
1032 self.tr( |
1029 """<p>The plugin download directory""" |
1033 """<p>The plugin download directory""" |
1030 """ <b>{0}</b> could not be created. Please""" |
1034 """ <b>{0}</b> could not be created. Please""" |
1031 """ configure it via the configuration""" |
1035 """ configure it via the configuration""" |
1032 """ dialog.</p><p>Reason: {1}</p>""") |
1036 """ dialog.</p><p>Reason: {1}</p>""") |
1033 .format(downloadDir, str(err))) |
1037 .format(downloadDir, str(err))) |
1050 Public method to check the availability of updates of plug-ins. |
1054 Public method to check the availability of updates of plug-ins. |
1051 """ |
1055 """ |
1052 period = Preferences.getPluginManager("UpdatesCheckInterval") |
1056 period = Preferences.getPluginManager("UpdatesCheckInterval") |
1053 if period == 0: |
1057 if period == 0: |
1054 return |
1058 return |
1055 elif period in [2, 3, 4]: |
1059 elif period in [1, 2, 3]: |
1056 lastModified = QFileInfo(self.pluginRepositoryFile).lastModified() |
1060 lastModified = QFileInfo(self.pluginRepositoryFile).lastModified() |
1057 if lastModified.isValid() and lastModified.date().isValid(): |
1061 if lastModified.isValid() and lastModified.date().isValid(): |
1058 lastModifiedDate = lastModified.date() |
1062 lastModifiedDate = lastModified.date() |
1059 now = QDate.currentDate() |
1063 now = QDate.currentDate() |
1060 if period == 2 and lastModifiedDate.day() == now.day(): |
1064 if period == 1 and lastModifiedDate.day() == now.day(): |
1061 # daily |
1065 # daily |
1062 return |
1066 return |
1063 elif period == 3 and lastModifiedDate.daysTo(now) < 7: |
1067 elif period == 2 and lastModifiedDate.daysTo(now) < 7: |
1064 # weekly |
1068 # weekly |
1065 return |
1069 return |
1066 elif period == 4 and lastModifiedDate.month() == now.month(): |
1070 elif period == 3 and \ |
|
1071 (lastModifiedDate.daysTo(now) < |
|
1072 lastModifiedDate.daysInMonth()): |
1067 # monthly |
1073 # monthly |
1068 return |
1074 return |
1069 |
1075 |
1070 self.__updateAvailable = False |
1076 self.__updateAvailable = False |
1071 |
1077 |
1072 request = QNetworkRequest( |
1078 request = QNetworkRequest( |
1073 QUrl(Preferences.getUI("PluginRepositoryUrl5"))) |
1079 QUrl(Preferences.getUI("PluginRepositoryUrl5"))) |
1074 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, |
1080 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, |
1075 QNetworkRequest.AlwaysNetwork) |
1081 QNetworkRequest.AlwaysNetwork) |
1076 reply = self.__networkManager.get(request) |
1082 reply = self.__networkManager.get(request) |
1077 reply.finished[()].connect(self.__downloadRepositoryFileDone) |
1083 reply.finished.connect(self.__downloadRepositoryFileDone) |
1078 self.__replies.append(reply) |
1084 self.__replies.append(reply) |
1079 |
1085 |
1080 def __downloadRepositoryFileDone(self): |
1086 def __downloadRepositoryFileDone(self): |
1081 """ |
1087 """ |
1082 Private method called after the repository file was downloaded. |
1088 Private method called after the repository file was downloaded. |
1085 if reply in self.__replies: |
1091 if reply in self.__replies: |
1086 self.__replies.remove(reply) |
1092 self.__replies.remove(reply) |
1087 if reply.error() != QNetworkReply.NoError: |
1093 if reply.error() != QNetworkReply.NoError: |
1088 E5MessageBox.warning( |
1094 E5MessageBox.warning( |
1089 None, |
1095 None, |
1090 self.trUtf8("Error downloading file"), |
1096 self.tr("Error downloading file"), |
1091 self.trUtf8( |
1097 self.tr( |
1092 """<p>Could not download the requested file""" |
1098 """<p>Could not download the requested file""" |
1093 """ from {0}.</p><p>Error: {1}</p>""" |
1099 """ from {0}.</p><p>Error: {1}</p>""" |
1094 ).format(Preferences.getUI("PluginRepositoryUrl5"), |
1100 ).format(Preferences.getUI("PluginRepositoryUrl5"), |
1095 reply.errorString()) |
1101 reply.errorString()) |
1096 ) |
1102 ) |
1120 return |
1126 return |
1121 |
1127 |
1122 if self.__updateAvailable: |
1128 if self.__updateAvailable: |
1123 res = E5MessageBox.information( |
1129 res = E5MessageBox.information( |
1124 None, |
1130 None, |
1125 self.trUtf8("New plugin versions available"), |
1131 self.tr("New plugin versions available"), |
1126 self.trUtf8("<p>There are new plug-ins or plug-in" |
1132 self.tr("<p>There are new plug-ins or plug-in" |
1127 " updates available. Use the plug-in" |
1133 " updates available. Use the plug-in" |
1128 " repository dialog to get them.</p>"), |
1134 " repository dialog to get them.</p>"), |
1129 E5MessageBox.StandardButtons( |
1135 E5MessageBox.StandardButtons( |
1130 E5MessageBox.Ignore | |
1136 E5MessageBox.Ignore | |
1131 E5MessageBox.Open), |
1137 E5MessageBox.Open), |
1132 E5MessageBox.Open) |
1138 E5MessageBox.Open) |
1133 if res == E5MessageBox.Open: |
1139 if res == E5MessageBox.Open: |
1145 @param author data for the author field (string) |
1151 @param author data for the author field (string) |
1146 @param version data for the version field (string) |
1152 @param version data for the version field (string) |
1147 @param filename data for the filename field (string) |
1153 @param filename data for the filename field (string) |
1148 @param status status of the plugin (string [stable, unstable, unknown]) |
1154 @param status status of the plugin (string [stable, unstable, unknown]) |
1149 """ |
1155 """ |
|
1156 # ignore hidden plug-ins |
|
1157 pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0] |
|
1158 if pluginName in Preferences.getPluginManager("HiddenPlugins"): |
|
1159 return |
|
1160 |
1150 archive = os.path.join(Preferences.getPluginManager("DownloadPath"), |
1161 archive = os.path.join(Preferences.getPluginManager("DownloadPath"), |
1151 filename) |
1162 filename) |
1152 |
1163 |
1153 # Check against installed/loaded plug-ins |
1164 # Check against installed/loaded plug-ins |
1154 pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0] |
|
1155 pluginDetails = self.getPluginDetails(pluginName) |
1165 pluginDetails = self.getPluginDetails(pluginName) |
1156 if pluginDetails is None: |
1166 if pluginDetails is None: |
1157 if not Preferences.getPluginManager("CheckInstalledOnly"): |
1167 if not Preferences.getPluginManager("CheckInstalledOnly"): |
1158 self.__updateAvailable = True |
1168 self.__updateAvailable = True |
1159 return |
1169 return |