From d2518714e0137393695607e787a84e61ecda5503 Mon Sep 17 00:00:00 2001 From: Yannick Richter Date: Tue, 23 Aug 2022 15:16:31 +0200 Subject: [PATCH] Automatic update notificaton added --- CHANGELOG.md | 6 +++- main.py | 32 +++++++++++++++--- res/updatebrowser.ui | 50 +++++++++++++++++---------- updater.py | 80 ++++++++++++++++++++++++++++++++++++-------- 4 files changed, 131 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 641c7f1d..e55fd069 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ - Added analog filter option - Added ADS111X source dialog - Added manual range tuning option for local analog and ADS111X + +#### Updater: +- Added update browser (Help->updates) +- Added automatic update notifications for firmware and GUI if detected -Redesign: +#### Redesign: - Redesigned UI layout - Added effect monitoring windows - Added advanced effect tuning window diff --git a/main.py b/main.py index f22ebbcc..7559d719 100644 --- a/main.py +++ b/main.py @@ -46,7 +46,7 @@ import updater # This GUIs version -VERSION = "1.9.4" +VERSION = "1.9.5" # Minimal supported firmware version. # Major version of firmware must match firmware. Minor versions must be higher or equal @@ -83,6 +83,7 @@ def __init__(self): self.fw_version_str = None self.setup() + self.check_configurator_update() def setup(self): """Init the systray, the serial, the toolbar, the status bar and the connection status.""" @@ -158,6 +159,18 @@ def reboot(self): self.send_command("sys", "reboot") self.reconnect() + def check_configurator_update(self): + """Checks if there is an update for the configurator only""" + release = updater.GithubRelease.get_latest_release(updater.GUIREPO) + if not release: + return + releaseversion,_ = updater.GithubRelease.get_version(release) + if updater.UpdateChecker.compare_versions(VERSION,releaseversion): + # New release available for firmware + msg = "New configurator update available.
Warning: Check if compatible with firmware.
Install firmware from main repo" + notification = updater.UpdateNotification(release,self,msg,VERSION) + notification.exec() + def open_dfu_dialog(self): """Open the dfu dialog and start managing.""" msg = PyQt6.QtWidgets.QDialog() @@ -412,10 +425,11 @@ def version_check(self, ver): gui_outdated = False fw_outdated = ( - min_fw_split[0] > fw_ver_split[0] or min_fw_split[1] > fw_ver_split[1] \ - or min_fw_split[2] > fw_ver_split[2] + min_fw_split[0] > fw_ver_split[0] \ + or min_fw_split[1] > fw_ver_split[1] and min_fw_split[0] == fw_ver_split[0] \ + or min_fw_split[2] > fw_ver_split[2] and min_fw_split[1] == fw_ver_split[1] and min_fw_split[0] == fw_ver_split[0] ) - gui_outdated = min_fw_split[0] < fw_ver_split[0] or min_fw_split[1] < fw_ver_split[1] + gui_outdated = min_fw_split[0] < fw_ver_split[0] or min_fw_split[1] < fw_ver_split[1] and min_fw_split[0] == fw_ver_split[0] if gui_outdated: msg = PyQt6.QtWidgets.QMessageBox( @@ -439,6 +453,16 @@ def version_check(self, ver): "and GUI are up to date if you encounter errors." ) msg.exec() + # Check github + mainreporelease = updater.GithubRelease.get_latest_release(updater.MAINREPO) + releaseversion,_ = updater.GithubRelease.get_version(mainreporelease) + if updater.UpdateChecker.compare_versions(self.fw_version_str,releaseversion): + # New release available for firmware + msg = "New firmware available" + notification = updater.UpdateNotification(mainreporelease,self,msg,self.fw_version_str) + notification.exec() + + def serial_connected(self, connected): """Check the release when a board is connected.""" diff --git a/res/updatebrowser.ui b/res/updatebrowser.ui index 77ab926b..25593eec 100644 --- a/res/updatebrowser.ui +++ b/res/updatebrowser.ui @@ -14,7 +14,32 @@ Updatebrowser - + + + + + 0 + 2 + + + + Release notes + + + + + + Info + + + + + + + + + + @@ -87,7 +112,7 @@ <html><head/><body><p>Ultrawipf/OpenFFBoard-configurator</p></body></html> - Configurator only + Configurator only (Only use if newer than main repo) buttonGroup_repo @@ -97,7 +122,7 @@ - + @@ -142,22 +167,11 @@ - - - - - 0 - 2 - + + + + Info: Use the main repo for firmware updates and always use matching configurator release - - Release notes - - - - - - diff --git a/updater.py b/updater.py index e6a002e8..f3c54061 100644 --- a/updater.py +++ b/updater.py @@ -7,7 +7,7 @@ import PyQt6.QtGui import PyQt6.QtCore import PyQt6.QtWidgets -from PyQt6.QtWidgets import QListWidgetItem +from PyQt6.QtWidgets import QListWidgetItem,QGroupBox,QHBoxLayout,QVBoxLayout,QLabel,QDialog,QTextBrowser,QPushButton import base_ui import pydfu import requests @@ -16,6 +16,11 @@ import helper from PyQt6.QtGui import QPalette, QColor from PyQt6.QtCore import Qt +from datetime import datetime +from optionsdialog import OptionsDialogGroupBox + +MAINREPO = "Ultrawipf/OpenFFBoard" +GUIREPO = "Ultrawipf/OpenFFBoard-Configurator" class GithubRelease(): @@ -53,6 +58,11 @@ def get_latest_release(repo : str): release = json.loads(response.content) return(release) + @staticmethod + def get_time(release : dict): + """Returns a datetime object of the creation time""" + return datetime.strptime(release['created_at'],'%Y-%m-%dT%H:%M:%SZ') + @staticmethod def get_version(release : dict): """Returns None if invalid tag, otherwise (version,postfix) like ("1.2.3","dev")""" @@ -78,9 +88,17 @@ class UpdateChecker(): @staticmethod def compare_versions(curver,comparever): """Returns False if current version newer or identical, True if comparever is newer""" + if not curver or not comparever: + return False comparever_i = [int(i) for i in comparever.split(".")] curver_i = [int(i) for i in curver.split(".")] - return comparever_i[0] > curver_i[0] or comparever_i[1] > curver_i[1] or comparever_i[2] > curver_i[2] + outdated = ( + comparever_i[0] > curver_i[0] \ + or comparever_i[1] > curver_i[1] and comparever_i[0] == curver_i[0] \ + or comparever_i[2] > curver_i[2] and comparever_i[1] == curver_i[1] and comparever_i[0] == curver_i[0] + ) + # return comparever_i[0] > curver_i[0] or comparever_i[1] > curver_i[1] or comparever_i[2] > curver_i[2] + return outdated @staticmethod @@ -103,8 +121,7 @@ def __init__(self,parentWidget): self.listWidget_release.currentItemChanged.connect(self.release_changed) self.listWidget_files.currentItemChanged.connect(self.file_changed) self.buttonGroup_repo.buttonClicked.connect(self.repo_changed) - - self.read_releases("Ultrawipf/OpenFFBoard") + self.read_releases(MAINREPO) def fill_releases(self,releases : dict): self.listWidget_release.clear() @@ -130,9 +147,9 @@ def get_selected_release(self): def repo_changed(self,button): if button == self.radioButton_configurator: - self.read_releases("Ultrawipf/OpenFFBoard-Configurator") + self.read_releases(GUIREPO) else: - self.read_releases("Ultrawipf/OpenFFBoard") + self.read_releases(MAINREPO) def read_releases(self,repo : str): releases = GithubRelease.get_releases(repo,True) @@ -155,9 +172,12 @@ def release_changed(self,current : QListWidgetItem,old : QListWidgetItem): if not current: return release = current.data(Qt.ItemDataRole.UserRole) - self.textBrowser_releasenotes.setText(GithubRelease.get_description(release)) + self.textBrowser_releasenotes.setMarkdown(GithubRelease.get_description(release)) self.label_releaseUrl.setText(f"{release['html_url']}") self.fill_files(release) + publishtime = GithubRelease.get_time(release) + infotext = f"Date: {publishtime}" + self.label_releaseInfo.setText(infotext) def file_changed(self,current : QListWidgetItem,old : QListWidgetItem): if not current: @@ -167,11 +187,43 @@ def file_changed(self,current : QListWidgetItem,old : QListWidgetItem): -if __name__ == "__main__": - ##test - newver,r = UpdateChecker.check_update("Ultrawipf/OpenFFBoard","1.2.3") - print(GithubRelease.get_version(r),newver) +class UpdateNotification(QDialog): + """Shows a dialog with release information""" + def __init__(self,release,main,desc,curver): + self.main = main + QDialog.__init__(self, main) + self.setWindowTitle("Update available") + self.vbox = QVBoxLayout() + self.setLayout(self.vbox) + self.infolabel = QLabel(desc) + self.infolabel.setOpenExternalLinks(True) + self.infolabel.setTextFormat(Qt.TextFormat.RichText) + self.vbox.addWidget(self.infolabel) + if not release: + self.vbox.addWidget(QLabel("Error displaying release")) + return + self.releaseversion = release["tag_name"] + url = release['html_url'] + self.versionlabel = QLabel(f"New version: {self.releaseversion}, Current version: {curver}") + self.versionlabel.setOpenExternalLinks(True) + self.versionlabel.setTextFormat(Qt.TextFormat.RichText) + self.vbox.addWidget(self.versionlabel) + + self.titlelabel = QLabel(f" {GithubRelease.get_title(release)}") + self.titlelabel.setOpenExternalLinks(True) + self.vbox.addWidget(self.titlelabel) + + self.updatebrowserbutton = QPushButton("Open update browser",self) + self.updatebrowserbutton.clicked.connect(self.open_updater) + + self.releasenotes = QTextBrowser(self) + self.releasenotes.setMarkdown(GithubRelease.get_description(release)) + self.vbox.addWidget(self.releasenotes) + self.vbox.addWidget(self.updatebrowserbutton) + + - releasest = GithubRelease.get_releases("Ultrawipf/OpenFFBoard",True) - if releasest: - print(GithubRelease.get_title(releasest[0])) + def open_updater(self): + """Opens the updatebrowser""" + self.close() + UpdateBrowser(self).exec()