7555 |
7546 |
7556 @param online flag indicating the online state |
7547 @param online flag indicating the online state |
7557 @type bool |
7548 @type bool |
7558 """ |
7549 """ |
7559 if online: |
7550 if online: |
7560 self.performVersionCheck(False) |
7551 self.performVersionCheck() |
7561 |
7552 |
7562 ############################################## |
7553 ############################################## |
7563 ## Below are methods to check for new versions |
7554 ## Below are methods to check for new versions |
7564 ############################################## |
7555 ############################################## |
7565 |
7556 |
7566 # TODO: change performVersionCheck to check against PyPI and do that |
7557 def performVersionCheck(self): |
7567 # only for the automatic check |
7558 """ |
7568 @pyqtSlot() |
7559 Public method to check for an update even if not installed via PyPI. |
7569 def performVersionCheck(self, manual=True, alternative=0, |
|
7570 showVersions=False): |
|
7571 """ |
|
7572 Public method to check the internet for an eric update. |
|
7573 |
|
7574 @param manual flag indicating an invocation via the menu (boolean) |
|
7575 @param alternative index of server to download from (integer) |
|
7576 @param showVersions flag indicating the show versions mode (boolean) |
|
7577 """ |
7560 """ |
7578 if self.isOnline(): |
7561 if self.isOnline(): |
7579 if not manual: |
7562 if VersionOnly.startswith(("rev_", "@@")): |
7580 if VersionOnly.startswith("@@"): |
7563 # cannot check against development or source installation |
7581 return |
|
7582 else: |
|
7583 period = Preferences.getUI("PerformVersionCheck") |
|
7584 if period == 0: |
|
7585 return |
|
7586 elif period in [2, 3, 4]: |
|
7587 lastCheck = Preferences.getSettings().value( |
|
7588 "Updates/LastCheckDate", QDate(1970, 1, 1)) |
|
7589 if lastCheck.isValid(): |
|
7590 now = QDate.currentDate() |
|
7591 if ( |
|
7592 (period == 2 and |
|
7593 lastCheck.day() == now.day()) or |
|
7594 (period == 3 and lastCheck.daysTo(now) < 7) or |
|
7595 (period == 4 and (lastCheck.daysTo(now) < |
|
7596 lastCheck.daysInMonth())) |
|
7597 ): |
|
7598 # daily, weekly, monthly |
|
7599 return |
|
7600 |
|
7601 self.__inVersionCheck = True |
|
7602 self.manualUpdatesCheck = manual |
|
7603 self.showAvailableVersions = showVersions |
|
7604 self.httpAlternative = alternative |
|
7605 url = QUrl(self.__httpAlternatives[alternative]) |
|
7606 self.__versionCheckCanceled = False |
|
7607 if manual: |
|
7608 if self.__versionCheckProgress is None: |
|
7609 self.__versionCheckProgress = EricProgressDialog( |
|
7610 "", self.tr("&Cancel"), |
|
7611 0, len(self.__httpAlternatives), |
|
7612 self.tr("%v/%m"), self) |
|
7613 self.__versionCheckProgress.setWindowTitle( |
|
7614 self.tr("Version Check")) |
|
7615 self.__versionCheckProgress.setMinimumDuration(0) |
|
7616 self.__versionCheckProgress.canceled.connect( |
|
7617 self.__versionsDownloadCanceled) |
|
7618 self.__versionCheckProgress.setLabelText( |
|
7619 self.tr("Trying host {0}").format(url.host())) |
|
7620 self.__versionCheckProgress.setValue(alternative) |
|
7621 request = QNetworkRequest(url) |
|
7622 request.setAttribute( |
|
7623 QNetworkRequest.Attribute.CacheLoadControlAttribute, |
|
7624 QNetworkRequest.CacheLoadControl.AlwaysNetwork) |
|
7625 reply = self.__networkManager.get(request) |
|
7626 reply.finished.connect(lambda: self.__versionsDownloadDone(reply)) |
|
7627 self.__replies.append(reply) |
|
7628 else: |
|
7629 if manual: |
|
7630 EricMessageBox.warning( |
|
7631 self, |
|
7632 self.tr("Error getting versions information"), |
|
7633 self.tr("The versions information cannot not be" |
|
7634 " downloaded because the Internet is" |
|
7635 " <b>not reachable</b>. Please try again later.") |
|
7636 ) |
|
7637 |
|
7638 @pyqtSlot() |
|
7639 def __versionsDownloadDone(self, reply): |
|
7640 """ |
|
7641 Private slot called, after the versions file has been downloaded |
|
7642 from the internet. |
|
7643 |
|
7644 @param reply reference to the network reply |
|
7645 @type QNetworkReply |
|
7646 """ |
|
7647 if self.__versionCheckCanceled: |
|
7648 self.__inVersionCheck = False |
|
7649 if self.__versionCheckProgress is not None: |
|
7650 self.__versionCheckProgress.reset() |
|
7651 self.__versionCheckProgress = None |
|
7652 return |
|
7653 |
|
7654 reply.deleteLater() |
|
7655 if reply in self.__replies: |
|
7656 self.__replies.remove(reply) |
|
7657 if reply.error() == QNetworkReply.NetworkError.NoError: |
|
7658 ioEncoding = Preferences.getSystem("IOEncoding") |
|
7659 versions = str(reply.readAll(), ioEncoding, 'replace').splitlines() |
|
7660 reply.close() |
|
7661 if ( |
|
7662 reply.error() != QNetworkReply.NetworkError.NoError or |
|
7663 len(versions) == 0 or |
|
7664 versions[0].startswith("<") |
|
7665 ): |
|
7666 # network error or an error page |
|
7667 self.httpAlternative += 1 |
|
7668 if self.httpAlternative >= len(self.__httpAlternatives): |
|
7669 self.__inVersionCheck = False |
|
7670 if self.__versionCheckProgress is not None: |
|
7671 self.__versionCheckProgress.reset() |
|
7672 self.__versionCheckProgress = None |
|
7673 firstFailure = Preferences.getSettings().value( |
|
7674 "Updates/FirstFailedCheckDate", QDate.currentDate()) |
|
7675 failedDuration = firstFailure.daysTo(QDate.currentDate()) |
|
7676 Preferences.getSettings().setValue( |
|
7677 "Updates/FirstFailedCheckDate", firstFailure) |
|
7678 if self.manualUpdatesCheck: |
|
7679 EricMessageBox.warning( |
|
7680 self, |
|
7681 self.tr("Error getting versions information"), |
|
7682 self.tr("""The versions information could not be""" |
|
7683 """ downloaded.""" |
|
7684 """ Please go online and try again.""")) |
|
7685 elif failedDuration > 7: |
|
7686 EricMessageBox.warning( |
|
7687 self, |
|
7688 self.tr("Error getting versions information"), |
|
7689 self.tr("""The versions information could not be""" |
|
7690 """ downloaded for the last 7 days.""" |
|
7691 """ Please go online and try again.""")) |
|
7692 return |
7564 return |
7693 else: |
7565 else: |
7694 self.performVersionCheck(self.manualUpdatesCheck, |
7566 period = Preferences.getUI("PerformVersionCheck") |
7695 self.httpAlternative, |
7567 if period == 0: |
7696 self.showAvailableVersions) |
7568 return |
7697 return |
7569 elif period in [2, 3, 4]: |
7698 |
7570 lastCheck = Preferences.getSettings().value( |
7699 self.__inVersionCheck = False |
7571 "Updates/LastCheckDate", QDate(1970, 1, 1)) |
7700 if self.__versionCheckProgress is not None: |
7572 if lastCheck.isValid(): |
7701 self.__versionCheckProgress.reset() |
7573 now = QDate.currentDate() |
7702 self.__versionCheckProgress = None |
7574 if ( |
7703 self.__updateVersionsUrls(versions) |
7575 (period == 2 and |
7704 if self.showAvailableVersions: |
7576 lastCheck.day() == now.day()) or |
7705 self.__showAvailableVersionInfos(versions) |
7577 (period == 3 and lastCheck.daysTo(now) < 7) or |
7706 else: |
7578 (period == 4 and (lastCheck.daysTo(now) < |
7707 Preferences.getSettings().remove("Updates/FirstFailedCheckDate") |
7579 lastCheck.daysInMonth())) |
7708 Preferences.getSettings().setValue( |
7580 ): |
7709 "Updates/LastCheckDate", QDate.currentDate()) |
7581 # daily, weekly, monthly |
7710 self.__versionCheckResult(versions) |
7582 return |
7711 |
|
7712 def __updateVersionsUrls(self, versions): |
|
7713 """ |
|
7714 Private method to update the URLs from which to retrieve the versions |
|
7715 file. |
|
7716 |
|
7717 @param versions contents of the downloaded versions file (list of |
|
7718 strings) |
|
7719 """ |
|
7720 if len(versions) > 5 and versions[4] == "---": |
|
7721 line = 5 |
|
7722 urls = [] |
|
7723 while line < len(versions): |
|
7724 urls.append(versions[line]) |
|
7725 line += 1 |
|
7726 |
7583 |
7727 Preferences.setUI("VersionsUrls7", urls) |
7584 availableVersions = ( |
7728 |
7585 self.pipInterface.getPackageVersions("eric-ide") |
7729 def __versionCheckResult(self, versions): |
7586 ) |
7730 """ |
7587 updateAvailable = bool(v for v in availableVersions |
7731 Private method to show the result of the version check action. |
7588 if v > VersionOnly) |
7732 |
7589 if updateAvailable: |
7733 @param versions contents of the downloaded versions file (list of |
7590 EricMessageBox.information( |
7734 strings) |
7591 self, |
7735 """ |
7592 self.tr("Upgrade available"), |
7736 url = "" |
7593 self.tr( |
7737 try: |
7594 """A newer version of the <b>eric-ide</b> package is""" |
7738 if "snapshot-" in VersionOnly: |
7595 """ available at <a href="{0}/eric-ide/">""" |
7739 # check snapshot version like snapshot-20170810 |
7596 """PyPI</a>.""" |
7740 if "snapshot-" in versions[2]: |
7597 ).format(self.pipInterface.getIndexUrlPypi()) |
7741 installedSnapshotDate = VersionOnly.rsplit("-", 1)[-1] |
7598 ) |
7742 availableSnapshotDate = versions[2].rsplit("-", 1)[-1] |
7599 |
7743 if availableSnapshotDate > installedSnapshotDate: |
|
7744 res = EricMessageBox.yesNo( |
|
7745 self, |
|
7746 self.tr("Update available"), |
|
7747 self.tr( |
|
7748 """The update to <b>{0}</b> of eric is""" |
|
7749 """ available at <b>{1}</b>. Would you like""" |
|
7750 """ to get it?""") |
|
7751 .format(versions[2], versions[3]), |
|
7752 yesDefault=True) |
|
7753 url = res and versions[3] or '' |
|
7754 else: |
|
7755 if self.manualUpdatesCheck: |
|
7756 EricMessageBox.information( |
|
7757 self, |
|
7758 self.tr("Update Check"), |
|
7759 self.tr( |
|
7760 """You are using a snapshot release of""" |
|
7761 """ eric. A more up-to-date stable release""" |
|
7762 """ might be available.""")) |
|
7763 elif VersionOnly.startswith(("rev_", "@@")): |
|
7764 # check installation from source |
|
7765 if self.manualUpdatesCheck: |
|
7766 EricMessageBox.information( |
|
7767 self, |
|
7768 self.tr("Update Check"), |
|
7769 self.tr( |
|
7770 """You installed eric directly from the source""" |
|
7771 """ code. There is no possibility to check""" |
|
7772 """ for the availability of an update.""")) |
|
7773 else: |
|
7774 # check release version |
|
7775 installedVersionTuple = self.__versionToTuple(VersionOnly) |
|
7776 availableVersionTuple = self.__versionToTuple(versions[0]) |
|
7777 if availableVersionTuple > installedVersionTuple: |
|
7778 res = EricMessageBox.yesNo( |
|
7779 self, |
|
7780 self.tr("Update available"), |
|
7781 self.tr( |
|
7782 """The update to <b>{0}</b> of eric is""" |
|
7783 """ available at <b>{1}</b>. Would you like""" |
|
7784 """ to get it?""") |
|
7785 .format(versions[0], versions[1]), |
|
7786 yesDefault=True) |
|
7787 url = res and versions[1] or '' |
|
7788 else: |
|
7789 if self.manualUpdatesCheck: |
|
7790 EricMessageBox.information( |
|
7791 self, |
|
7792 self.tr("eric is up to date"), |
|
7793 self.tr( |
|
7794 """You are using the latest version of""" |
|
7795 """ eric""")) |
|
7796 except (IndexError, TypeError): |
|
7797 EricMessageBox.warning( |
|
7798 self, |
|
7799 self.tr("Error during updates check"), |
|
7800 self.tr("""Could not perform updates check.""")) |
|
7801 |
|
7802 if url: |
|
7803 QDesktopServices.openUrl(QUrl(url)) |
|
7804 |
|
7805 @pyqtSlot() |
|
7806 def __versionsDownloadCanceled(self): |
|
7807 """ |
|
7808 Private slot called to cancel the version check. |
|
7809 """ |
|
7810 if self.__replies: |
|
7811 self.__versionCheckCanceled = True |
|
7812 self.__replies[-1].abort() |
|
7813 |
|
7814 def __showAvailableVersionInfos(self, versions): |
|
7815 """ |
|
7816 Private method to show the versions available for download. |
|
7817 |
|
7818 @param versions contents of the downloaded versions file (list of |
|
7819 strings) |
|
7820 """ |
|
7821 versionText = self.tr( |
|
7822 """<h3>Available versions</h3>""" |
|
7823 """<table>""") |
|
7824 line = 0 |
|
7825 while line < len(versions): |
|
7826 if versions[line] == "---": |
|
7827 break |
|
7828 |
|
7829 versionText += ( |
|
7830 """<tr><td>{0}</td><td><a href="{1}">{2}</a></td></tr>""" |
|
7831 ).format( |
|
7832 versions[line], versions[line + 1], |
|
7833 'sourceforge' in versions[line + 1] and |
|
7834 "SourceForge" or versions[line + 1]) |
|
7835 line += 2 |
|
7836 versionText += self.tr("""</table>""") |
|
7837 |
|
7838 self.__versionsDialog = EricMessageBox.EricMessageBox( |
|
7839 EricMessageBox.NoIcon, |
|
7840 Program, |
|
7841 versionText, |
|
7842 modal=False, |
|
7843 buttons=EricMessageBox.Ok, |
|
7844 parent=self |
|
7845 ) |
|
7846 self.__versionsDialog.setIconPixmap( |
|
7847 UI.PixmapCache.getPixmap("eric").scaled(64, 64)) |
|
7848 self.__versionsDialog.show() |
|
7849 |
|
7850 def __sslErrors(self, reply, errors): |
7600 def __sslErrors(self, reply, errors): |
7851 """ |
7601 """ |
7852 Private slot to handle SSL errors. |
7602 Private slot to handle SSL errors. |
7853 |
7603 |
7854 @param reply reference to the reply object (QNetworkReply) |
7604 @param reply reference to the reply object (QNetworkReply) |