From fba31cf3e6f531531e70783ddeb955812ec83a8f Mon Sep 17 00:00:00 2001 From: Mr Finchum Date: Fri, 31 Jan 2025 14:58:14 +0000 Subject: [PATCH 01/41] feat: Added updater Added updater window and option to check for new version and update via pip. --- pyproject.toml | 7 +- src/OptimaLab35/gui.py | 136 ++++++++++++++++++++++- src/OptimaLab35/ui/main_window.py | 10 +- src/OptimaLab35/ui/main_window.ui | 14 ++- src/OptimaLab35/ui/updater_window.py | 147 ++++++++++++++++++++++++ src/OptimaLab35/ui/updater_window.ui | 160 +++++++++++++++++++++++++++ src/OptimaLab35/update_ui.sh | 2 + src/pyproject.toml | 2 +- 8 files changed, 473 insertions(+), 5 deletions(-) create mode 100644 src/OptimaLab35/ui/updater_window.py create mode 100644 src/OptimaLab35/ui/updater_window.ui diff --git a/pyproject.toml b/pyproject.toml index b9e2577..a9e3c18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,12 @@ authors = [{ name = "Mr Finchum" }] description = "User interface for optima35." readme = "pip_README.md" requires-python = ">=3.8" -dependencies = ["optima35>=1.0.0, <2.0.0", "pyside6", "PyYAML"] +dependencies = [ + "optima35>=1.0.0, <2.0.0", + "PyPyUpdater>=0.3.0, <1.0.0", + "pyside6", + "PyYAML", +] classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", diff --git a/src/OptimaLab35/gui.py b/src/OptimaLab35/gui.py index 1194845..e2d9384 100644 --- a/src/OptimaLab35/gui.py +++ b/src/OptimaLab35/gui.py @@ -2,10 +2,12 @@ import sys import os from datetime import datetime +from PyPiUpdater import PyPiUpdater from optima35.core import OptimaManager from OptimaLab35.utils.utility import Utilities from OptimaLab35.ui.main_window import Ui_MainWindow from OptimaLab35.ui.preview_window import Ui_Preview_Window +from OptimaLab35.ui.updater_window import Ui_Updater_Window from OptimaLab35.ui.exif_handler_window import ExifEditor from OptimaLab35.ui.simple_dialog import SimpleDialog # Import the SimpleDialog class from OptimaLab35 import __version__ @@ -48,7 +50,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui = Ui_MainWindow() self.ui.setupUi(self) self.sd = SimpleDialog() - self.preview_window = PreviewWindow() + # Change UI elements self.change_statusbar(f"Using {self.o.name} v{self.o.version}", 5000) self.setWindowTitle(f"{self.name} v{self.version}") @@ -76,6 +78,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui.actionAbout.triggered.connect(self.info_window) self.ui.preview_Button.clicked.connect(self.open_preview_window) + self.ui.actionUpdate.triggered.connect(self.open_updater_window) regex = QRegularExpression(r"^\d{1,2}\.\d{1,6}$") validator = QRegularExpressionValidator(regex) @@ -86,9 +89,14 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): # UI related function, changing parts, open, etc. def open_preview_window(self): + self.preview_window = PreviewWindow() self.preview_window.values_selected.connect(self.update_values) self.preview_window.showMaximized() + def open_updater_window(self): + self.updater_window = UpdaterWindow(self.version, self.o.version) + self.updater_window.show() + def update_values(self, value1, value2, checkbox_state): # Update main window's widgets with the received values # ChatGPT @@ -454,6 +462,132 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): elif do == "write": self.u.write_yaml(self.exif_file, self.available_exif_data) +class UpdaterWindow(QMainWindow, Ui_Updater_Window): + # Mixture of code by me, code/functions refactored by ChatGPT and code directly from ChatGPT + def __init__(self, optimalab35_localversion, optima35_localversion): + super(UpdaterWindow, self).__init__() + self.ui = Ui_Updater_Window() + self.ui.setupUi(self) + from PyPiUpdater import PyPiUpdater + # Update log file location + self.update_log_file = os.path.expanduser("~/.config/OptimaLab35/update.log") + # Store local versions + self.optimalab35_localversion = optimalab35_localversion + self.optima35_localversion = optima35_localversion + + # Create PyPiUpdater instances + self.ppu_ol35 = PyPiUpdater("OptimaLab35", self.optimalab35_localversion, self.update_log_file) + self.ppu_o35 = PyPiUpdater("optima35", self.optima35_localversion, self.update_log_file) + + self.last_update = self.ppu_o35.last_update_date_string() + + # Track which packages need an update + self.updates_available = {"OptimaLab35": False, "optima35": False} + + self.define_gui_interaction() + + def define_gui_interaction(self): + """Setup UI interactions.""" + if self.optimalab35_localversion == "0.0.1": + self.dev_mode() + return + else: + self.ui.label_dev.setVisible(False) + self.ui.label_optimalab35_localversion.setText(self.optimalab35_localversion) + self.ui.label_optima35_localversion.setText(self.optima35_localversion) + self.ui.update_and_restart_Button.setEnabled(False) + + # Connect buttons to functions + self.ui.check_for_update_Button.clicked.connect(self.check_for_updates) + self.ui.update_and_restart_Button.clicked.connect(self.update_and_restart) + self.ui.label_last_check_2.setText(self.last_update) + + def dev_mode(self): + self.ui.update_and_restart_Button.setEnabled(False) + self.ui.check_for_update_Button.setEnabled(False) + self.ui.label_dev.setStyleSheet("QLabel { background-color : red; color : black; }") + + def check_for_updates(self): + """Check for updates and update the UI.""" + self.ui.check_for_update_Button.setEnabled(False) + self.ui.label_optimalab35_latestversion.setText("Checking...") + self.ui.label_optima35_latestversion.setText("Checking...") + + # Check OptimaLab35 update + is_newer_ol35, latest_version_ol35 = self.ppu_ol35.check_for_update(True) + if is_newer_ol35 is None: + self.ui.label_optimalab35_latestversion.setText("Error") + else: + self.ui.label_optimalab35_latestversion.setText(latest_version_ol35) + self.updates_available["OptimaLab35"] = is_newer_ol35 + + # Check optima35 update + is_newer_o35, latest_version_o35 = self.ppu_o35.check_for_update(True) + if is_newer_o35 is None: + self.ui.label_optima35_latestversion.setText("Error") + else: + self.ui.label_optima35_latestversion.setText(latest_version_o35) + self.updates_available["optima35"] = is_newer_o35 + + # Enable update button if any update is available + if any(self.updates_available.values()): + self.ui.update_and_restart_Button.setEnabled(True) + + self.ppu_o35.record_update_check() + self.ui.label_last_check_2.setText(self.ppu_o35.last_update_date_string()) + self.ui.check_for_update_Button.setEnabled(True) + + def update_and_restart(self): + """Update selected packages and restart the application.""" + packages_to_update = [pkg for pkg, update in self.updates_available.items() if update] + + if not packages_to_update: + QMessageBox.information(self, "Update", "No updates available.") + return + + # Confirm update + msg = QMessageBox() + msg.setWindowTitle("Update Available") + msg.setText(f"Updating: {', '.join(packages_to_update)}\nRestart after update?") + msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + result = msg.exec() + + if result == QMessageBox.Yes: + update_results = [] # Store results + + for package in packages_to_update: + if package == "OptimaLab35": + success, message = self.ppu_ol35.update_package() + elif package == "optima35": + success, message = self.ppu_o35.update_package() + + update_results.append(f"{package}: {'✔ Success' if success else '❌ Failed'}\n{message}") + + # Show summary of updates + # Show update completion message + msg = QMessageBox() + msg.setWindowTitle("Update Complete") + msg.setText("\n\n".join(update_results)) + msg.setStandardButtons(QMessageBox.Ok) + msg.exec() + + # Restart the application after user clicks "OK" + self.ppu_ol35.restart_program() + + def restart_program(self): + """Restart the Python program after an update.""" + print("Restarting the application...") + + # Close all running Qt windows before restarting + app = QApplication.instance() + if app: + app.quit() + + python = sys.executable + os.execl(python, python, *sys.argv) + + + class PreviewWindow(QMainWindow, Ui_Preview_Window): values_selected = Signal(int, int, bool) diff --git a/src/OptimaLab35/ui/main_window.py b/src/OptimaLab35/ui/main_window.py index 5af0bc9..bca1e18 100644 --- a/src/OptimaLab35/ui/main_window.py +++ b/src/OptimaLab35/ui/main_window.py @@ -37,6 +37,8 @@ class Ui_MainWindow(object): self.actionPreview.setObjectName(u"actionPreview") self.actionAbout = QAction(MainWindow) self.actionAbout.setObjectName(u"actionAbout") + self.actionUpdate = QAction(MainWindow) + self.actionUpdate.setObjectName(u"actionUpdate") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -555,10 +557,14 @@ class Ui_MainWindow(object): self.menuBar.setGeometry(QRect(0, 0, 440, 27)) self.menuHelp = QMenu(self.menuBar) self.menuHelp.setObjectName(u"menuHelp") + self.menuSettings = QMenu(self.menuBar) + self.menuSettings.setObjectName(u"menuSettings") MainWindow.setMenuBar(self.menuBar) + self.menuBar.addAction(self.menuSettings.menuAction()) self.menuBar.addAction(self.menuHelp.menuAction()) self.menuHelp.addAction(self.actionAbout) + self.menuSettings.addAction(self.actionUpdate) self.retranslateUi(MainWindow) self.rename_checkbox.toggled.connect(self.filename.setEnabled) @@ -596,6 +602,7 @@ class Ui_MainWindow(object): self.actionInfo.setText(QCoreApplication.translate("MainWindow", u"About", None)) self.actionPreview.setText(QCoreApplication.translate("MainWindow", u"Preview image", None)) self.actionAbout.setText(QCoreApplication.translate("MainWindow", u"About", None)) + self.actionUpdate.setText(QCoreApplication.translate("MainWindow", u"Update", None)) self.input_folder_button.setText(QCoreApplication.translate("MainWindow", u"Input", None)) self.output_path.setText("") self.output_path.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Output folder", None)) @@ -604,7 +611,7 @@ class Ui_MainWindow(object): self.output_folder_button.setText(QCoreApplication.translate("MainWindow", u"Output", None)) self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"Essential group", None)) self.quality_label_2.setText(QCoreApplication.translate("MainWindow", u"Quality", None)) - self.label_11.setText(QCoreApplication.translate("MainWindow", u"Export Format", None)) + self.label_11.setText(QCoreApplication.translate("MainWindow", u"Format ", None)) self.optimize_checkBox.setText(QCoreApplication.translate("MainWindow", u"optimize", None)) self.quality_label_1.setText(QCoreApplication.translate("MainWindow", u"Quality", None)) @@ -658,5 +665,6 @@ class Ui_MainWindow(object): self.add_date_checkBox.setText(QCoreApplication.translate("MainWindow", u"add date", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("MainWindow", u"EXIF", None)) self.menuHelp.setTitle(QCoreApplication.translate("MainWindow", u"Help", None)) + self.menuSettings.setTitle(QCoreApplication.translate("MainWindow", u"Settings", None)) # retranslateUi diff --git a/src/OptimaLab35/ui/main_window.ui b/src/OptimaLab35/ui/main_window.ui index 3779add..62acda5 100644 --- a/src/OptimaLab35/ui/main_window.ui +++ b/src/OptimaLab35/ui/main_window.ui @@ -142,7 +142,7 @@ - Export Format + Format @@ -841,6 +841,13 @@ + + + Settings + + + + @@ -858,6 +865,11 @@ About + + + Update + + diff --git a/src/OptimaLab35/ui/updater_window.py b/src/OptimaLab35/ui/updater_window.py new file mode 100644 index 0000000..13a2eb4 --- /dev/null +++ b/src/OptimaLab35/ui/updater_window.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'updater_window.ui' +## +## Created by: Qt User Interface Compiler version 6.8.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel, + QMainWindow, QPushButton, QSizePolicy, QWidget) + +class Ui_Updater_Window(object): + def setupUi(self, Updater_Window): + if not Updater_Window.objectName(): + Updater_Window.setObjectName(u"Updater_Window") + Updater_Window.setEnabled(True) + Updater_Window.resize(372, 224) + self.centralwidget = QWidget(Updater_Window) + self.centralwidget.setObjectName(u"centralwidget") + self.gridLayout_2 = QGridLayout(self.centralwidget) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.label_last_check = QLabel(self.centralwidget) + self.label_last_check.setObjectName(u"label_last_check") + + self.gridLayout_2.addWidget(self.label_last_check, 0, 0, 1, 1) + + self.label_last_check_2 = QLabel(self.centralwidget) + self.label_last_check_2.setObjectName(u"label_last_check_2") + self.label_last_check_2.setEnabled(True) + + self.gridLayout_2.addWidget(self.label_last_check_2, 0, 1, 1, 1) + + self.widget_2 = QWidget(self.centralwidget) + self.widget_2.setObjectName(u"widget_2") + self.gridLayout = QGridLayout(self.widget_2) + self.gridLayout.setObjectName(u"gridLayout") + self.label_6 = QLabel(self.widget_2) + self.label_6.setObjectName(u"label_6") + self.label_6.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_6, 0, 1, 1, 1) + + self.label_optimalab35_latestversion = QLabel(self.widget_2) + self.label_optimalab35_latestversion.setObjectName(u"label_optimalab35_latestversion") + self.label_optimalab35_latestversion.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_optimalab35_latestversion, 1, 2, 1, 1) + + self.label_2 = QLabel(self.widget_2) + self.label_2.setObjectName(u"label_2") + + self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1) + + self.label_optima35_latestversion = QLabel(self.widget_2) + self.label_optima35_latestversion.setObjectName(u"label_optima35_latestversion") + self.label_optima35_latestversion.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_optima35_latestversion, 3, 2, 1, 1) + + self.label_3 = QLabel(self.widget_2) + self.label_3.setObjectName(u"label_3") + self.label_3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_3, 0, 2, 1, 1) + + self.label = QLabel(self.widget_2) + self.label.setObjectName(u"label") + + self.gridLayout.addWidget(self.label, 1, 0, 1, 1) + + self.label_9 = QLabel(self.widget_2) + self.label_9.setObjectName(u"label_9") + + self.gridLayout.addWidget(self.label_9, 0, 0, 1, 1) + + self.label_optimalab35_localversion = QLabel(self.widget_2) + self.label_optimalab35_localversion.setObjectName(u"label_optimalab35_localversion") + self.label_optimalab35_localversion.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_optimalab35_localversion, 1, 1, 1, 1) + + self.label_optima35_localversion = QLabel(self.widget_2) + self.label_optima35_localversion.setObjectName(u"label_optima35_localversion") + self.label_optima35_localversion.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.gridLayout.addWidget(self.label_optima35_localversion, 3, 1, 1, 1) + + self.label_dev = QLabel(self.widget_2) + self.label_dev.setObjectName(u"label_dev") + self.label_dev.setAlignment(Qt.AlignCenter) + + self.gridLayout.addWidget(self.label_dev, 2, 0, 1, 3) + + + self.gridLayout_2.addWidget(self.widget_2, 1, 0, 1, 2) + + self.widget = QWidget(self.centralwidget) + self.widget.setObjectName(u"widget") + self.horizontalLayout = QHBoxLayout(self.widget) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.check_for_update_Button = QPushButton(self.widget) + self.check_for_update_Button.setObjectName(u"check_for_update_Button") + + self.horizontalLayout.addWidget(self.check_for_update_Button) + + self.update_and_restart_Button = QPushButton(self.widget) + self.update_and_restart_Button.setObjectName(u"update_and_restart_Button") + + self.horizontalLayout.addWidget(self.update_and_restart_Button) + + + self.gridLayout_2.addWidget(self.widget, 2, 0, 1, 2) + + Updater_Window.setCentralWidget(self.centralwidget) + + self.retranslateUi(Updater_Window) + + QMetaObject.connectSlotsByName(Updater_Window) + # setupUi + + def retranslateUi(self, Updater_Window): + Updater_Window.setWindowTitle(QCoreApplication.translate("Updater_Window", u"OptimaLab35 - Updater", None)) + self.label_last_check.setText(QCoreApplication.translate("Updater_Window", u"Last update check ago:", None)) + self.label_last_check_2.setText(QCoreApplication.translate("Updater_Window", u"TextLabel", None)) + self.label_6.setText(QCoreApplication.translate("Updater_Window", u"Local Version", None)) + self.label_optimalab35_latestversion.setText(QCoreApplication.translate("Updater_Window", u"unknown", None)) + self.label_2.setText(QCoreApplication.translate("Updater_Window", u"optima35", None)) + self.label_optima35_latestversion.setText(QCoreApplication.translate("Updater_Window", u"unknown", None)) + self.label_3.setText(QCoreApplication.translate("Updater_Window", u"Latest version", None)) + self.label.setText(QCoreApplication.translate("Updater_Window", u"OptimaLab35", None)) + self.label_9.setText(QCoreApplication.translate("Updater_Window", u"Package", None)) + self.label_optimalab35_localversion.setText(QCoreApplication.translate("Updater_Window", u"0.0.0", None)) + self.label_optima35_localversion.setText(QCoreApplication.translate("Updater_Window", u"0.0.0", None)) + self.label_dev.setText(QCoreApplication.translate("Updater_Window", u"Detected dev env. updater disabled", None)) + self.check_for_update_Button.setText(QCoreApplication.translate("Updater_Window", u"Check for update", None)) + self.update_and_restart_Button.setText(QCoreApplication.translate("Updater_Window", u"Update and restart", None)) + # retranslateUi + diff --git a/src/OptimaLab35/ui/updater_window.ui b/src/OptimaLab35/ui/updater_window.ui new file mode 100644 index 0000000..0e74e74 --- /dev/null +++ b/src/OptimaLab35/ui/updater_window.ui @@ -0,0 +1,160 @@ + + + Updater_Window + + + true + + + + 0 + 0 + 372 + 224 + + + + OptimaLab35 - Updater + + + + + + + Last update check ago: + + + + + + + true + + + TextLabel + + + + + + + + + + Local Version + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + unknown + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + optima35 + + + + + + + unknown + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Latest version + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + OptimaLab35 + + + + + + + Package + + + + + + + 0.0.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.0.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Detected dev env. updater disabled + + + Qt::AlignCenter + + + + + + + + + + + + + Check for update + + + + + + + Update and restart + + + + + + + + + + + + diff --git a/src/OptimaLab35/update_ui.sh b/src/OptimaLab35/update_ui.sh index d533d7a..95cda5f 100755 --- a/src/OptimaLab35/update_ui.sh +++ b/src/OptimaLab35/update_ui.sh @@ -4,3 +4,5 @@ echo "Update main window." pyside6-uic OptimaLab35/ui/main_window.ui -o OptimaLab35/ui/main_window.py echo "Update preview window." pyside6-uic OptimaLab35/ui/preview_window.ui -o OptimaLab35/ui/preview_window.py +echo "Update updater window." +pyside6-uic OptimaLab35/ui/updater_window.ui -o OptimaLab35/ui/updater_window.py diff --git a/src/pyproject.toml b/src/pyproject.toml index 0b86791..4e3097a 100644 --- a/src/pyproject.toml +++ b/src/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] authors = [{ name = "Mr Finchum" }] description = "User interface for optima35." requires-python = ">=3.8" -dependencies = ["optima35>=1.0.0, <2.0.0", "PyYAML"] +dependencies = ["optima35>=1.0.0, <2.0.0", "PyYAML", "PyPyUpdater"] classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", From 2476dd8b1f6cd7f139e03a8442613fd202b8888a Mon Sep 17 00:00:00 2001 From: CodeByMrFinchum Date: Fri, 31 Jan 2025 16:42:50 +0100 Subject: [PATCH 02/41] fix: misspelled dependency --- CHANGELOG.md | 17 ++++++++++++++--- pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c103ff4..bf1de6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,22 @@ # Changelog -## 0.7.x -### 0.7.0: Enhanced Preview +## 0.8.x +### 0.8.1: Fix +- Fixed a misspelling of `PyPiUpdater` in the build file, which prevented v0.8.0 from being installed. + +### 0.8.0: Updater Feature +- Added an updater function utilizing my new package [PyPiUpdater](https://gitlab.com/CodeByMrFinchum/PyPiUpdater). +- New updater window displaying the local version and checking for updates online. +- Added an option to update and restart the app from the menu. + +--- + +## 0.7.0: Enhanced Preview - Images loaded into the preview window are now scaled while maintaining aspect ratio. - Added live updates: changes to brightness, contrast, or grayscale are applied immediately. - - ⚠ This may crush the system depending on image size and system specifications. + - This may crush the system depending on image size and system specifications. - Removed Settings from menuBar, and extended the about window. + --- ## 0.6.0: Initial Flatpak Support diff --git a/pyproject.toml b/pyproject.toml index a9e3c18..fbfdbfb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ readme = "pip_README.md" requires-python = ">=3.8" dependencies = [ "optima35>=1.0.0, <2.0.0", - "PyPyUpdater>=0.3.0, <1.0.0", + "PyPiUpdater>=0.3.0, <1.0.0", "pyside6", "PyYAML", ] From 21f1d9fc012dcea18ecbb40ff53b9990aa84f00c Mon Sep 17 00:00:00 2001 From: Mr Finchum Date: Fri, 31 Jan 2025 16:31:20 +0000 Subject: [PATCH 03/41] patch: support for ppu04 ppu = PyPiUpdater 0.4.0 --- CHANGELOG.md | 5 +++++ pyproject.toml | 2 +- src/OptimaLab35/gui.py | 19 +++++++++++++++---- src/OptimaLab35/ui/updater_window.py | 10 +++++----- src/OptimaLab35/ui/updater_window.ui | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf1de6d..4a5375a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## 0.8.x +### 0.8.2: Patch for New PyPiUpdater Version +- Updated to support **PyPiUpdater 0.4.0**. +- Now stores version information locally, preventing an "unknown" state on the first updater launch. + - Users still need to press the **Update** button to verify the latest version, ensuring an internet connection is available. + ### 0.8.1: Fix - Fixed a misspelling of `PyPiUpdater` in the build file, which prevented v0.8.0 from being installed. diff --git a/pyproject.toml b/pyproject.toml index fbfdbfb..a3f237f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ readme = "pip_README.md" requires-python = ">=3.8" dependencies = [ "optima35>=1.0.0, <2.0.0", - "PyPiUpdater>=0.3.0, <1.0.0", + "PyPiUpdater>=0.4.0, <1.0.0", "pyside6", "PyYAML", ] diff --git a/src/OptimaLab35/gui.py b/src/OptimaLab35/gui.py index e2d9384..6fda769 100644 --- a/src/OptimaLab35/gui.py +++ b/src/OptimaLab35/gui.py @@ -470,7 +470,7 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): self.ui.setupUi(self) from PyPiUpdater import PyPiUpdater # Update log file location - self.update_log_file = os.path.expanduser("~/.config/OptimaLab35/update.log") + self.update_log_file = os.path.expanduser("~/.config/OptimaLab35/update_log.json") # Store local versions self.optimalab35_localversion = optimalab35_localversion self.optima35_localversion = optima35_localversion @@ -478,8 +478,10 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): # Create PyPiUpdater instances self.ppu_ol35 = PyPiUpdater("OptimaLab35", self.optimalab35_localversion, self.update_log_file) self.ppu_o35 = PyPiUpdater("optima35", self.optima35_localversion, self.update_log_file) + self.ol35_last_state = self.ppu_ol35.get_last_state() + self.o35_last_state = self.ppu_o35.get_last_state() - self.last_update = self.ppu_o35.last_update_date_string() + #self.last_update = self.ppu_o35.last_update_date_string() # Track which packages need an update self.updates_available = {"OptimaLab35": False, "optima35": False} @@ -493,14 +495,20 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): return else: self.ui.label_dev.setVisible(False) + self.ui.label_optimalab35_localversion.setText(self.optimalab35_localversion) self.ui.label_optima35_localversion.setText(self.optima35_localversion) + + self.ui.label_latest_version.setText("Latest version") + self.ui.label_optimalab35_latestversion.setText(self.ol35_last_state[1]) + self.ui.label_optima35_latestversion.setText(self.o35_last_state[1]) + self.ui.update_and_restart_Button.setEnabled(False) # Connect buttons to functions self.ui.check_for_update_Button.clicked.connect(self.check_for_updates) self.ui.update_and_restart_Button.clicked.connect(self.update_and_restart) - self.ui.label_last_check_2.setText(self.last_update) + self.ui.label_last_check_2.setText(str(self.ol35_last_state[0])) def dev_mode(self): self.ui.update_and_restart_Button.setEnabled(False) @@ -534,7 +542,10 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): self.ui.update_and_restart_Button.setEnabled(True) self.ppu_o35.record_update_check() - self.ui.label_last_check_2.setText(self.ppu_o35.last_update_date_string()) + self.ppu_ol35.record_update_check() + last_date = self.ppu_ol35.get_last_state() + self.ui.label_last_check_2.setText(last_date[0]) + self.ui.label_latest_version.setText("Online version") self.ui.check_for_update_Button.setEnabled(True) def update_and_restart(self): diff --git a/src/OptimaLab35/ui/updater_window.py b/src/OptimaLab35/ui/updater_window.py index 13a2eb4..8ea230e 100644 --- a/src/OptimaLab35/ui/updater_window.py +++ b/src/OptimaLab35/ui/updater_window.py @@ -66,11 +66,11 @@ class Ui_Updater_Window(object): self.gridLayout.addWidget(self.label_optima35_latestversion, 3, 2, 1, 1) - self.label_3 = QLabel(self.widget_2) - self.label_3.setObjectName(u"label_3") - self.label_3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + self.label_latest_version = QLabel(self.widget_2) + self.label_latest_version.setObjectName(u"label_latest_version") + self.label_latest_version.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) - self.gridLayout.addWidget(self.label_3, 0, 2, 1, 1) + self.gridLayout.addWidget(self.label_latest_version, 0, 2, 1, 1) self.label = QLabel(self.widget_2) self.label.setObjectName(u"label") @@ -135,7 +135,7 @@ class Ui_Updater_Window(object): self.label_optimalab35_latestversion.setText(QCoreApplication.translate("Updater_Window", u"unknown", None)) self.label_2.setText(QCoreApplication.translate("Updater_Window", u"optima35", None)) self.label_optima35_latestversion.setText(QCoreApplication.translate("Updater_Window", u"unknown", None)) - self.label_3.setText(QCoreApplication.translate("Updater_Window", u"Latest version", None)) + self.label_latest_version.setText(QCoreApplication.translate("Updater_Window", u"Latest version", None)) self.label.setText(QCoreApplication.translate("Updater_Window", u"OptimaLab35", None)) self.label_9.setText(QCoreApplication.translate("Updater_Window", u"Package", None)) self.label_optimalab35_localversion.setText(QCoreApplication.translate("Updater_Window", u"0.0.0", None)) diff --git a/src/OptimaLab35/ui/updater_window.ui b/src/OptimaLab35/ui/updater_window.ui index 0e74e74..4d8210d 100644 --- a/src/OptimaLab35/ui/updater_window.ui +++ b/src/OptimaLab35/ui/updater_window.ui @@ -76,7 +76,7 @@ - + Latest version From 0c450328b3d4d710b03ace2b405e8a9d5340956d Mon Sep 17 00:00:00 2001 From: CodeByMrFinchum Date: Fri, 31 Jan 2025 17:42:02 +0100 Subject: [PATCH 04/41] fix: Fixed app not closing after update --- CHANGELOG.md | 3 +++ src/OptimaLab35/gui.py | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a5375a..4505e0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## 0.8.x +### 0.8.3: Fix – OptimaLab35 Not Closing After Update +- Fixed an issue where **OptimaLab35** would not close properly when updating, resulting in an unresponsive instance and multiple running processes. + ### 0.8.2: Patch for New PyPiUpdater Version - Updated to support **PyPiUpdater 0.4.0**. - Now stores version information locally, preventing an "unknown" state on the first updater launch. diff --git a/src/OptimaLab35/gui.py b/src/OptimaLab35/gui.py index 6fda769..24c2871 100644 --- a/src/OptimaLab35/gui.py +++ b/src/OptimaLab35/gui.py @@ -490,7 +490,7 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): def define_gui_interaction(self): """Setup UI interactions.""" - if self.optimalab35_localversion == "0.0.1": + if self.optimalab35_localversion == "0.0.2": self.dev_mode() return else: @@ -583,7 +583,8 @@ class UpdaterWindow(QMainWindow, Ui_Updater_Window): msg.exec() # Restart the application after user clicks "OK" - self.ppu_ol35.restart_program() + #self.ppu_ol35.restart_program() + self.restart_program() def restart_program(self): """Restart the Python program after an update.""" From 1bba7f8bbce3909f5391a15e753aeb1d9a2a0247 Mon Sep 17 00:00:00 2001 From: Mr Finchum Date: Sat, 1 Feb 2025 14:58:32 +0000 Subject: [PATCH 05/41] patch: Minor Enhancements --- CHANGELOG.md | 5 +++++ src/OptimaLab35/gui.py | 23 ++++++++++++++++------- src/OptimaLab35/ui/updater_window.py | 6 +++--- src/OptimaLab35/ui/updater_window.ui | 6 +++--- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4505e0d..a6b9068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## 0.8.x +### 0.8.4: Minor Enhancements & Cleanup +- Updated window titles. +- Improved error handling for updater: now displays the specific error message instead of just **"error"** when an issue occurs during update checks. +- Ensured all child windows close when the main window is closed. + ### 0.8.3: Fix – OptimaLab35 Not Closing After Update - Fixed an issue where **OptimaLab35** would not close properly when updating, resulting in an unresponsive instance and multiple running processes. diff --git a/src/OptimaLab35/gui.py b/src/OptimaLab35/gui.py index 24c2871..1f8e5ed 100644 --- a/src/OptimaLab35/gui.py +++ b/src/OptimaLab35/gui.py @@ -53,7 +53,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): # Change UI elements self.change_statusbar(f"Using {self.o.name} v{self.o.version}", 5000) - self.setWindowTitle(f"{self.name} v{self.version}") + self.set_title() self.default_ui_layout() self.define_gui_interaction() @@ -63,6 +63,13 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): self.ui.png_quality_Slider.setVisible(False) self.ui.quality_label_2.setVisible(False) + def set_title(self): + if self.version == "0.0.1": + title = f"{self.name} DEV MODE" + else: + title = self.name + self.setWindowTitle(title) + def define_gui_interaction(self): self.ui.input_folder_button.clicked.connect(self.browse_input_folder) self.ui.output_folder_button.clicked.connect(self.browse_output_folder) @@ -108,7 +115,7 @@ class OptimaLab35(QMainWindow, Ui_MainWindow): info_text = f"""

{self.name} v{self.version}

(C) 2024-2025 Mr Finchum aka CodeByMrFinchum

-

{self.name} is a GUI for {self.o.name} (v{self.o.version}), enhancing its functionality with a\nuser-friendly interface for efficient image and metadata management.

+

{self.name} is a GUI for {self.o.name} (v{self.o.version}), enhancing its functionality with a user-friendly interface for efficient image and metadata management.

Features: