Make the new version lookup run in the background
This commit is contained in:
@@ -31,10 +31,10 @@ from datetime import datetime
|
|||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
|
|
||||||
from PyQt5.QtGui import QDesktopServices
|
from PyQt5.QtGui import QDesktopServices
|
||||||
from PyQt5.QtCore import QUrl, pyqtSlot
|
from PyQt5.QtCore import QObject, QRunnable, QUrl, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QLabel, QVBoxLayout, QWidget
|
from PyQt5.QtWidgets import QLabel, QVBoxLayout, QWidget
|
||||||
|
|
||||||
from novelwriter import CONFIG, __version__, __date__, __domain__
|
from novelwriter import CONFIG, SHARED, __version__, __date__, __domain__
|
||||||
from novelwriter.common import formatVersion
|
from novelwriter.common import formatVersion
|
||||||
from novelwriter.constants import nwConst
|
from novelwriter.constants import nwConst
|
||||||
|
|
||||||
@@ -52,6 +52,11 @@ class VersionInfoWidget(QWidget):
|
|||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
# Label Strings
|
||||||
|
self._trLatest = self.tr("Latest Version: {0}")
|
||||||
|
self._trChecking = self.tr("Checking ...")
|
||||||
|
self._trDownload = self.tr("Download from {0}")
|
||||||
|
|
||||||
# Labels
|
# Labels
|
||||||
self._lblInfo = QLabel("{0} {1} \u2013 {2} {3} \u2013 {4}".format(
|
self._lblInfo = QLabel("{0} {1} \u2013 {2} {3} \u2013 {4}".format(
|
||||||
self.tr("Version"), formatVersion(__version__),
|
self.tr("Version"), formatVersion(__version__),
|
||||||
@@ -59,15 +64,11 @@ class VersionInfoWidget(QWidget):
|
|||||||
"<a href='#notes'>{0}</a>".format(self.tr("Release Notes")),
|
"<a href='#notes'>{0}</a>".format(self.tr("Release Notes")),
|
||||||
), self)
|
), self)
|
||||||
self._lblInfo.linkActivated.connect(self._processLink)
|
self._lblInfo.linkActivated.connect(self._processLink)
|
||||||
self._lblRelease = QLabel(self.tr("Latest Version: {0}").format(
|
self._lblRelease = QLabel(self._trLatest.format(
|
||||||
"<a href='#update'>{0}</a>".format(self.tr("Check Now"))
|
"<a href='#update'>{0}</a>".format(self.tr("Check Now"))
|
||||||
), self)
|
), self)
|
||||||
self._lblRelease.linkActivated.connect(self._processLink)
|
self._lblRelease.linkActivated.connect(self._processLink)
|
||||||
|
|
||||||
# New Release
|
|
||||||
self._trRelease = self.tr("Latest Version: {0} {1} Download from {2}")
|
|
||||||
self._trFail = self.tr("Could not retrieve version information.")
|
|
||||||
|
|
||||||
# Assemble
|
# Assemble
|
||||||
self._layout = QVBoxLayout()
|
self._layout = QVBoxLayout()
|
||||||
self._layout.addWidget(self._lblInfo)
|
self._layout.addWidget(self._lblInfo)
|
||||||
@@ -91,41 +92,71 @@ class VersionInfoWidget(QWidget):
|
|||||||
elif link == "#website":
|
elif link == "#website":
|
||||||
QDesktopServices.openUrl(QUrl(nwConst.URL_WEB))
|
QDesktopServices.openUrl(QUrl(nwConst.URL_WEB))
|
||||||
elif link == "#update":
|
elif link == "#update":
|
||||||
shuffle(LOOKUPS)
|
self._lblRelease.setText(self._trLatest.format(self._trChecking))
|
||||||
for url in LOOKUPS:
|
lookup = _Retriever()
|
||||||
if result := self._pullJson(url):
|
lookup.signals.dataReady.connect(self._updateReleaseInfo)
|
||||||
self._updateReleaseInfo(result)
|
SHARED.runInThreadPool(lookup)
|
||||||
break
|
|
||||||
else:
|
|
||||||
self._updateReleaseInfo({})
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Private Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
|
@pyqtSlot(dict)
|
||||||
def _updateReleaseInfo(self, result: dict) -> None:
|
def _updateReleaseInfo(self, result: dict) -> None:
|
||||||
"""Update the widget release info."""
|
"""Update the widget release info."""
|
||||||
if version := result.get("version"):
|
if version := result.get("version"):
|
||||||
download = f"<a href='#website'>{__domain__}</a>"
|
download = f"<a href='#website'>{__domain__}</a>"
|
||||||
self._lblRelease.setText(self._trRelease.format(version, "\u2013", download))
|
self._lblRelease.setText(self._trLatest.format(
|
||||||
|
f"{version} \u2013 {self._trDownload.format(download)}"
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
self._lblRelease.setText(self._trFail)
|
self._lblRelease.setText(self._trLatest.format(self.tr("Failed")))
|
||||||
return
|
return
|
||||||
|
|
||||||
def _pullJson(self, url: str) -> dict | None:
|
|
||||||
"""Pull a JSON file from a URL."""
|
|
||||||
urlReq = Request(url)
|
|
||||||
urlReq.add_header("User-Agent", nwConst.USER_AGENT)
|
|
||||||
urlReq.add_header("Accept", "application/json")
|
|
||||||
|
|
||||||
try:
|
|
||||||
logger.info("Contacting: %s", url)
|
|
||||||
urlData = urlopen(urlReq, timeout=10)
|
|
||||||
return json.loads(urlData.read().decode()).get("release")
|
|
||||||
except Exception:
|
|
||||||
logger.error("Failed to retrieve data")
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# END Class VersionInfoWidget
|
# END Class VersionInfoWidget
|
||||||
|
|
||||||
|
|
||||||
|
class _Retriever(QRunnable):
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self._isRunning = False
|
||||||
|
self.signals = _RetrieverSignal()
|
||||||
|
return
|
||||||
|
|
||||||
|
def isRunning(self) -> bool:
|
||||||
|
return self._isRunning
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def run(self) -> None:
|
||||||
|
"""Poll the urls in the background."""
|
||||||
|
self._isRunning = True
|
||||||
|
|
||||||
|
shuffle(LOOKUPS)
|
||||||
|
for url in LOOKUPS:
|
||||||
|
req = Request(url)
|
||||||
|
req.add_header("User-Agent", nwConst.USER_AGENT)
|
||||||
|
req.add_header("Accept", "application/json")
|
||||||
|
try:
|
||||||
|
logger.info("Contacting: %s", url)
|
||||||
|
data = urlopen(req, timeout=10).read().decode()
|
||||||
|
if isinstance(release := json.loads(data).get("release"), dict):
|
||||||
|
self.signals.dataReady.emit(release)
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
logger.error("Failed to retrieve release info")
|
||||||
|
else:
|
||||||
|
self.signals.dataReady.emit({})
|
||||||
|
|
||||||
|
self._isRunning = False
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class _Retriever
|
||||||
|
|
||||||
|
|
||||||
|
class _RetrieverSignal(QObject):
|
||||||
|
dataReady = pyqtSignal(dict)
|
||||||
|
|
||||||
|
# END Class _RetrieverSignal
|
||||||
|
|||||||
Reference in New Issue
Block a user