10 |
10 |
11 import sys |
11 import sys |
12 import os |
12 import os |
13 import zipfile |
13 import zipfile |
14 |
14 |
15 from PyQt4.QtCore import pyqtSignal, pyqtSlot, Qt, QFile, QIODevice, QUrl, QProcess |
15 from PyQt4.QtCore import pyqtSignal, pyqtSlot, Qt, QFile, QIODevice, QUrl, \ |
16 from PyQt4.QtGui import QWidget, QDialogButtonBox, QAbstractButton, QTreeWidgetItem, \ |
16 QProcess |
17 QDialog, QVBoxLayout |
17 from PyQt4.QtGui import QWidget, QDialogButtonBox, QAbstractButton, \ |
18 from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply |
18 QTreeWidgetItem, QDialog, QVBoxLayout |
|
19 from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, \ |
|
20 QNetworkReply |
19 |
21 |
20 from .Ui_PluginRepositoryDialog import Ui_PluginRepositoryDialog |
22 from .Ui_PluginRepositoryDialog import Ui_PluginRepositoryDialog |
21 |
23 |
22 from E5Gui import E5MessageBox |
24 from E5Gui import E5MessageBox |
23 from E5Gui.E5MainWindow import E5MainWindow |
25 from E5Gui.E5MainWindow import E5MainWindow |
45 |
47 |
46 class PluginRepositoryWidget(QWidget, Ui_PluginRepositoryDialog): |
48 class PluginRepositoryWidget(QWidget, Ui_PluginRepositoryDialog): |
47 """ |
49 """ |
48 Class implementing a dialog showing the available plugins. |
50 Class implementing a dialog showing the available plugins. |
49 |
51 |
50 @signal closeAndInstall() emitted when the Close & Install button is pressed |
52 @signal closeAndInstall() emitted when the Close & Install button is |
|
53 pressed |
51 """ |
54 """ |
52 closeAndInstall = pyqtSignal() |
55 closeAndInstall = pyqtSignal() |
53 |
56 |
54 def __init__(self, parent=None, external=False): |
57 def __init__(self, parent=None, external=False): |
55 """ |
58 """ |
60 window (boolean) |
63 window (boolean) |
61 """ |
64 """ |
62 super().__init__(parent) |
65 super().__init__(parent) |
63 self.setupUi(self) |
66 self.setupUi(self) |
64 |
67 |
65 self.__updateButton = \ |
68 self.__updateButton = self.buttonBox.addButton( |
66 self.buttonBox.addButton(self.trUtf8("Update"), QDialogButtonBox.ActionRole) |
69 self.trUtf8("Update"), QDialogButtonBox.ActionRole) |
67 self.__downloadButton = \ |
70 self.__downloadButton = self.buttonBox.addButton( |
68 self.buttonBox.addButton(self.trUtf8("Download"), QDialogButtonBox.ActionRole) |
71 self.trUtf8("Download"), QDialogButtonBox.ActionRole) |
69 self.__downloadButton.setEnabled(False) |
72 self.__downloadButton.setEnabled(False) |
70 self.__downloadInstallButton = \ |
73 self.__downloadInstallButton = \ |
71 self.buttonBox.addButton(self.trUtf8("Download && Install"), |
74 self.buttonBox.addButton(self.trUtf8("Download && Install"), |
72 QDialogButtonBox.ActionRole) |
75 QDialogButtonBox.ActionRole) |
73 self.__downloadInstallButton.setEnabled(False) |
76 self.__downloadInstallButton.setEnabled(False) |
74 self.__downloadCancelButton = \ |
77 self.__downloadCancelButton = self.buttonBox.addButton( |
75 self.buttonBox.addButton(self.trUtf8("Cancel"), QDialogButtonBox.ActionRole) |
78 self.trUtf8("Cancel"), QDialogButtonBox.ActionRole) |
76 self.__installButton = \ |
79 self.__installButton = \ |
77 self.buttonBox.addButton(self.trUtf8("Close && Install"), |
80 self.buttonBox.addButton(self.trUtf8("Close && Install"), |
78 QDialogButtonBox.ActionRole) |
81 QDialogButtonBox.ActionRole) |
79 self.__downloadCancelButton.setEnabled(False) |
82 self.__downloadCancelButton.setEnabled(False) |
80 self.__installButton.setEnabled(False) |
83 self.__installButton.setEnabled(False) |
81 |
84 |
82 self.repositoryUrlEdit.setText(Preferences.getUI("PluginRepositoryUrl5")) |
85 self.repositoryUrlEdit.setText( |
83 |
86 Preferences.getUI("PluginRepositoryUrl5")) |
84 self.repositoryList.headerItem().setText(self.repositoryList.columnCount(), "") |
87 |
|
88 self.repositoryList.headerItem().setText( |
|
89 self.repositoryList.columnCount(), "") |
85 self.repositoryList.header().setSortIndicator(0, Qt.AscendingOrder) |
90 self.repositoryList.header().setSortIndicator(0, Qt.AscendingOrder) |
86 |
91 |
87 self.pluginRepositoryFile = \ |
92 self.pluginRepositoryFile = \ |
88 os.path.join(Utilities.getConfigDir(), "PluginRepository") |
93 os.path.join(Utilities.getConfigDir(), "PluginRepository") |
89 |
94 |
241 self.__pluginsToDownload = [] |
246 self.__pluginsToDownload = [] |
242 self.__downloadButton.setEnabled(False) |
247 self.__downloadButton.setEnabled(False) |
243 self.__downloadInstallButton.setEnabled(False) |
248 self.__downloadInstallButton.setEnabled(False) |
244 self.__installButton.setEnabled(False) |
249 self.__installButton.setEnabled(False) |
245 for itm in self.repositoryList.selectedItems(): |
250 for itm in self.repositoryList.selectedItems(): |
246 if itm not in [self.__stableItem, self.__unstableItem, self.__unknownItem]: |
251 if itm not in [self.__stableItem, self.__unstableItem, |
|
252 self.__unknownItem]: |
247 url = itm.data(0, urlRole) |
253 url = itm.data(0, urlRole) |
248 filename = os.path.join( |
254 filename = os.path.join( |
249 Preferences.getPluginManager("DownloadPath"), |
255 Preferences.getPluginManager("DownloadPath"), |
250 itm.data(0, filenameRole)) |
256 itm.data(0, filenameRole)) |
251 self.__pluginsToDownload.append((url, filename)) |
257 self.__pluginsToDownload.append((url, filename)) |
282 |
288 |
283 def __resortRepositoryList(self): |
289 def __resortRepositoryList(self): |
284 """ |
290 """ |
285 Private method to resort the tree. |
291 Private method to resort the tree. |
286 """ |
292 """ |
287 self.repositoryList.sortItems(self.repositoryList.sortColumn(), |
293 self.repositoryList.sortItems( |
288 self.repositoryList.header().sortIndicatorOrder()) |
294 self.repositoryList.sortColumn(), |
|
295 self.repositoryList.header().sortIndicatorOrder()) |
289 |
296 |
290 def __populateList(self): |
297 def __populateList(self): |
291 """ |
298 """ |
292 Private method to populate the list of available plugins. |
299 Private method to populate the list of available plugins. |
293 """ |
300 """ |
313 url = Preferences.getUI("PluginRepositoryUrl5") |
320 url = Preferences.getUI("PluginRepositoryUrl5") |
314 if url != self.repositoryUrlEdit.text(): |
321 if url != self.repositoryUrlEdit.text(): |
315 self.repositoryUrlEdit.setText(url) |
322 self.repositoryUrlEdit.setText(url) |
316 E5MessageBox.warning(self, |
323 E5MessageBox.warning(self, |
317 self.trUtf8("Plugins Repository URL Changed"), |
324 self.trUtf8("Plugins Repository URL Changed"), |
318 self.trUtf8("""The URL of the Plugins Repository has""" |
325 self.trUtf8( |
319 """ changed. Select the "Update" button to get""" |
326 """The URL of the Plugins Repository has""" |
320 """ the new repository file.""")) |
327 """ changed. Select the "Update" button to get""" |
|
328 """ the new repository file.""")) |
321 else: |
329 else: |
322 E5MessageBox.critical(self, |
330 E5MessageBox.critical(self, |
323 self.trUtf8("Read plugins repository file"), |
331 self.trUtf8("Read plugins repository file"), |
324 self.trUtf8("<p>The plugins repository file <b>{0}</b> " |
332 self.trUtf8("<p>The plugins repository file <b>{0}</b> " |
325 "could not be read. Select Update</p>")\ |
333 "could not be read. Select Update</p>")\ |
326 .format(self.pluginRepositoryFile)) |
334 .format(self.pluginRepositoryFile)) |
327 else: |
335 else: |
328 self.__repositoryMissing = True |
336 self.__repositoryMissing = True |
329 QTreeWidgetItem(self.repositoryList, |
337 QTreeWidgetItem(self.repositoryList, |
330 ["", |
338 ["", self.trUtf8( |
331 self.trUtf8("No plugin repository file available.\nSelect Update.") |
339 "No plugin repository file available.\nSelect Update.") |
332 ]) |
340 ]) |
333 self.repositoryList.resizeColumnToContents(1) |
341 self.repositoryList.resizeColumnToContents(1) |
334 |
342 |
335 def __downloadFile(self, url, filename, doneMethod=None): |
343 def __downloadFile(self, url, filename, doneMethod=None): |
336 """ |
344 """ |
378 ok = False |
386 ok = False |
379 if not self.__downloadCancelled: |
387 if not self.__downloadCancelled: |
380 E5MessageBox.warning(self, |
388 E5MessageBox.warning(self, |
381 self.trUtf8("Error downloading file"), |
389 self.trUtf8("Error downloading file"), |
382 self.trUtf8( |
390 self.trUtf8( |
383 """<p>Could not download the requested file from {0}.</p>""" |
391 """<p>Could not download the requested file""" |
384 """<p>Error: {1}</p>""" |
392 """ from {0}.</p><p>Error: {1}</p>""" |
385 ).format(self.__downloadURL, reply.errorString()) |
393 ).format(self.__downloadURL, reply.errorString()) |
386 ) |
394 ) |
387 self.downloadProgress.setValue(0) |
395 self.downloadProgress.setValue(0) |
388 self.__downloadURL = None |
396 self.__downloadURL = None |
389 self.__downloadIODevice.remove() |
397 self.__downloadIODevice.remove() |
391 if self.repositoryList.topLevelItemCount(): |
399 if self.repositoryList.topLevelItemCount(): |
392 if self.repositoryList.currentItem() is None: |
400 if self.repositoryList.currentItem() is None: |
393 self.repositoryList.setCurrentItem( |
401 self.repositoryList.setCurrentItem( |
394 self.repositoryList.topLevelItem(0)) |
402 self.repositoryList.topLevelItem(0)) |
395 else: |
403 else: |
396 self.__downloadButton.setEnabled(len(self.__selectedItems())) |
404 self.__downloadButton.setEnabled( |
397 self.__downloadInstallButton.setEnabled(len(self.__selectedItems())) |
405 len(self.__selectedItems())) |
|
406 self.__downloadInstallButton.setEnabled( |
|
407 len(self.__selectedItems())) |
398 return |
408 return |
399 |
409 |
400 self.__downloadIODevice.open(QIODevice.WriteOnly) |
410 self.__downloadIODevice.open(QIODevice.WriteOnly) |
401 self.__downloadIODevice.write(reply.readAll()) |
411 self.__downloadIODevice.write(reply.readAll()) |
402 self.__downloadIODevice.close() |
412 self.__downloadIODevice.close() |
428 """ |
438 """ |
429 if total: |
439 if total: |
430 self.downloadProgress.setMaximum(total) |
440 self.downloadProgress.setMaximum(total) |
431 self.downloadProgress.setValue(done) |
441 self.downloadProgress.setValue(done) |
432 |
442 |
433 def addEntry(self, name, short, description, url, author, version, filename, status): |
443 def addEntry(self, name, short, description, url, author, version, |
|
444 filename, status): |
434 """ |
445 """ |
435 Public method to add an entry to the list. |
446 Public method to add an entry to the list. |
436 |
447 |
437 @param name data for the name field (string) |
448 @param name data for the name field (string) |
438 @param short data for the short field (string) |
449 @param short data for the short field (string) |
444 @param status status of the plugin (string [stable, unstable, unknown]) |
455 @param status status of the plugin (string [stable, unstable, unknown]) |
445 """ |
456 """ |
446 if status == "stable": |
457 if status == "stable": |
447 if self.__stableItem is None: |
458 if self.__stableItem is None: |
448 self.__stableItem = \ |
459 self.__stableItem = \ |
449 QTreeWidgetItem(self.repositoryList, [self.trUtf8("Stable")]) |
460 QTreeWidgetItem(self.repositoryList, |
|
461 [self.trUtf8("Stable")]) |
450 self.__stableItem.setExpanded(True) |
462 self.__stableItem.setExpanded(True) |
451 parent = self.__stableItem |
463 parent = self.__stableItem |
452 elif status == "unstable": |
464 elif status == "unstable": |
453 if self.__unstableItem is None: |
465 if self.__unstableItem is None: |
454 self.__unstableItem = \ |
466 self.__unstableItem = \ |
455 QTreeWidgetItem(self.repositoryList, [self.trUtf8("Unstable")]) |
467 QTreeWidgetItem(self.repositoryList, |
|
468 [self.trUtf8("Unstable")]) |
456 self.__unstableItem.setExpanded(True) |
469 self.__unstableItem.setExpanded(True) |
457 parent = self.__unstableItem |
470 parent = self.__unstableItem |
458 else: |
471 else: |
459 if self.__unknownItem is None: |
472 if self.__unknownItem is None: |
460 self.__unknownItem = \ |
473 self.__unknownItem = \ |
461 QTreeWidgetItem(self.repositoryList, [self.trUtf8("Unknown")]) |
474 QTreeWidgetItem(self.repositoryList, |
|
475 [self.trUtf8("Unknown")]) |
462 self.__unknownItem.setExpanded(True) |
476 self.__unknownItem.setExpanded(True) |
463 parent = self.__unknownItem |
477 parent = self.__unknownItem |
464 itm = QTreeWidgetItem(parent, [name, version, short]) |
478 itm = QTreeWidgetItem(parent, [name, version, short]) |
465 |
479 |
466 itm.setData(0, urlRole, url) |
480 itm.setData(0, urlRole, url) |
585 self.cw = PluginRepositoryWidget(self, external=True) |
600 self.cw = PluginRepositoryWidget(self, external=True) |
586 size = self.cw.size() |
601 size = self.cw.size() |
587 self.setCentralWidget(self.cw) |
602 self.setCentralWidget(self.cw) |
588 self.resize(size) |
603 self.resize(size) |
589 |
604 |
590 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
605 self.setStyle(Preferences.getUI("Style"), |
|
606 Preferences.getUI("StyleSheet")) |
591 |
607 |
592 self.cw.buttonBox.accepted[()].connect(self.close) |
608 self.cw.buttonBox.accepted[()].connect(self.close) |
593 self.cw.buttonBox.rejected[()].connect(self.close) |
609 self.cw.buttonBox.rejected[()].connect(self.close) |
594 self.cw.closeAndInstall.connect(self.__startPluginInstall) |
610 self.cw.closeAndInstall.connect(self.__startPluginInstall) |
595 |
611 |
602 |
618 |
603 args = [] |
619 args = [] |
604 args.append(applPath) |
620 args.append(applPath) |
605 args += self.cw.getDownloadedPlugins() |
621 args += self.cw.getDownloadedPlugins() |
606 |
622 |
607 if not os.path.isfile(applPath) or not proc.startDetached(sys.executable, args): |
623 if not os.path.isfile(applPath) or \ |
|
624 not proc.startDetached(sys.executable, args): |
608 E5MessageBox.critical(self, |
625 E5MessageBox.critical(self, |
609 self.trUtf8('Process Generation Error'), |
626 self.trUtf8('Process Generation Error'), |
610 self.trUtf8( |
627 self.trUtf8( |
611 '<p>Could not start the process.<br>' |
628 '<p>Could not start the process.<br>' |
612 'Ensure that it is available as <b>{0}</b>.</p>' |
629 'Ensure that it is available as <b>{0}</b>.</p>' |