Fix a bug in the *.spec files and also apply the following major changes:

- Add support for adding the base folder to PATH.
- Only display one pop up window at a time in order to avoid confusion.
- Add automatic updates feature:
	- Windows and Linux versions will be shipped with an updater program used to
	  update both Artemis and the updater itself.
	- MacOs versions will not have the updater. Instead the user will be asked
	  to download the new software version (if present) via browser.
This commit is contained in:
Alessandro
2019-09-21 16:11:53 +02:00
parent 08b3312b23
commit 8e79bf6adf
34 changed files with 1360 additions and 280 deletions

141
src/updatescontroller.py Normal file
View File

@@ -0,0 +1,141 @@
import subprocess as sp
import webbrowser
from PyQt5.QtCore import QObject, pyqtSlot, QProcess
from PyQt5.QtWidgets import QMessageBox, qApp
from constants import Constants, Messages, DownloadTarget
from downloadtargetfactory import get_download_target
from utilities import pop_up
from os_utilities import IS_MAC
from executable_utilities import IS_BINARY
from threads import UpdatesControllerThread
from versioncontroller import VersionController
class UpdatesController(QObject):
def __init__(self, current_version, owner):
super().__init__()
self._owner = owner
self._download_window = self._owner.download_window
self._current_version = current_version
self.version_controller = VersionController()
self._updates_thread = UpdatesControllerThread(self.version_controller)
self._updates_thread.on_success.connect(self._startup_updates_check)
def start(self):
"""Start the thread."""
if IS_BINARY:
self._updates_thread.start()
@pyqtSlot()
def start_verify_software_version(self):
if not IS_BINARY:
pop_up(
self._owner,
title=Messages.FEATURE_NOT_AVAILABLE,
text=Messages.SCRIPT_NOT_UPDATE
).show()
return
if not self._download_window.isVisible():
self._updates_thread.start()
@pyqtSlot(bool)
def _verify_software_version(self, success):
"""Verify if there is a new software version.
Otherwise notify the user that the software is up to date."""
if not self._download_window.isVisible():
if success:
new_version_found = self._check_new_version()
if not new_version_found:
pop_up(
self._owner,
title=Messages.UP_TO_DATE,
text=Messages.UP_TO_DATE_MSG
).show()
else:
pop_up(
self._owner,
title=Messages.NO_CONNECTION,
text=Messages.NO_CONNECTION_MSG
).show()
@pyqtSlot(bool)
def _startup_updates_check(self, success):
self._updates_thread.on_success.disconnect()
self._updates_thread.on_success.connect(self._verify_software_version)
if success:
if not self._check_new_version():
# Check for a new version of the updater only if Artemis is up to date.
self._check_updater_version()
def _check_new_version(self):
"""Check whether there is a new software version available.
Does something only if the running program is a compiled version."""
if not IS_BINARY:
return None
latest_version = self.version_controller.software.version
if latest_version is None:
return False
if latest_version == self._current_version:
return False
answer = pop_up(
self._owner,
title=Messages.NEW_VERSION_AVAILABLE,
text=Messages.NEW_VERSION_MSG(latest_version),
informative_text=Messages.DOWNLOAD_SUGG_MSG,
is_question=True,
).exec()
if answer == QMessageBox.Yes:
if IS_MAC:
webbrowser.open(self.version_controller.software.url)
else:
updater = QProcess()
command = Constants.UPDATER_SOFTWARE + " " + \
self.version_controller.software.url + \
" " + self.version_controller.software.hash_code + \
" " + str(self.version_controller.software.size)
try:
updater.startDetached(command)
except BaseException:
pass
else:
qApp.quit()
return True
def _check_updater_version(self):
"""Check is a new version of the updater is available.
If so, ask to download the new version.
If the software is not a compiled version, the function is a NOP."""
if not IS_BINARY or IS_MAC:
return
latest_updater_version = self.version_controller.updater.version
try:
with sp.Popen(
[Constants.UPDATER_SOFTWARE, "--version"],
encoding="UTF-8",
stdout=sp.PIPE,
stderr=sp.STDOUT,
stdin=sp.DEVNULL # Needed to avoid OsError: [WinError 6] The handle is invalid.
) as proc:
updater_version = proc.stdout.read().rstrip("\r\n") # Strip any possible newline, to be sure.
except Exception:
updater_version = latest_updater_version
if latest_updater_version is None:
return
if updater_version != latest_updater_version:
answer = pop_up(
self._owner,
title=Messages.UPDATES_AVAILABALE,
text=Messages.UPDATES_MSG,
is_question=True,
).exec()
if answer == QMessageBox.Yes:
self._download_window.activate(
get_download_target(
DownloadTarget.UPDATER,
self.version_controller.updater
)
)