diff --git a/res/update_checker.ui b/res/update_checker.ui
index 12ffade1..a2f767ae 100644
--- a/res/update_checker.ui
+++ b/res/update_checker.ui
@@ -49,9 +49,9 @@
- 17
+ 20
10
- 281
+ 218
16
@@ -62,13 +62,13 @@
-
+ There is an update available for AutoSplit.
- 17
+ 20
30
91
16
@@ -81,7 +81,7 @@
- 17
+ 20
50
81
16
@@ -94,14 +94,14 @@
- 17
- 76
- 241
+ 20
+ 80
+ 119
16
-
+ Open download page?
@@ -117,7 +117,7 @@
Qt::NoFocus
-
+ Open
@@ -130,7 +130,7 @@
-
+ Later
@@ -162,9 +162,9 @@
- 17
- 100
- 141
+ 20
+ 102
+ 131
20
diff --git a/src/AutoSplit.py b/src/AutoSplit.py
index 40e81aea..ff8f476e 100644
--- a/src/AutoSplit.py
+++ b/src/AutoSplit.py
@@ -31,13 +31,13 @@
import split_parser
from AutoControlledWorker import AutoControlledWorker
from capture_windows import capture_region, Rect
-from gen import design
+from compare import checkIfImageHasTransparency, compareImage
+from gen import about, design, update_checker
from hotkeys import send_command, afterSettingHotkey, setSplitHotkey, setResetHotkey, setSkipSplitHotkey, \
setUndoSplitHotkey, setPauseHotkey
-from menu_bar import AboutWidget, VERSION, UpdateCheckerWidget, about, viewHelp, checkForUpdates
+from menu_bar import open_about, VERSION, viewHelp, checkForUpdates, open_update_checker
from screen_region import selectRegion, selectWindow, alignRegion, validateBeforeComparison
from split_parser import BELOW_FLAG, DUMMY_FLAG, PAUSE_FLAG
-from compare import checkIfImageHasTransparency, compareImage
# Resize to these width and height so that FPS performance increases
@@ -67,6 +67,7 @@ class AutoSplit(QMainWindow, design.Ui_MainWindow):
undoSplitSignal = QtCore.pyqtSignal()
pauseSignal = QtCore.pyqtSignal()
afterSettingHotkeySignal = QtCore.pyqtSignal()
+ updateCheckerWidgetSignal = QtCore.pyqtSignal(str, bool)
# Use this signal when trying to show an error from outside the main thread
showErrorSignal = QtCore.pyqtSignal(FunctionType)
@@ -75,8 +76,9 @@ class AutoSplit(QMainWindow, design.Ui_MainWindow):
timerStartImage = QtCore.QTimer()
# Windows
- aboutWidget: AboutWidget
- updateCheckerWidget: UpdateCheckerWidget
+ AboutWidget: about.Ui_aboutAutoSplitWidget
+ UpdateCheckerWidget: update_checker.Ui_UpdateChecker
+ CheckForUpdatesThread: QtCore.QThread
# Settings
split_image_directory = ""
@@ -155,7 +157,7 @@ def __init__(self, parent: Optional[QWidget] = None):
# close all processes when closing window
self.actionView_Help.triggered.connect(viewHelp)
- self.actionAbout.triggered.connect(lambda: about(self))
+ self.actionAbout.triggered.connect(lambda: open_about(self))
self.actionCheck_for_Updates.triggered.connect(lambda: checkForUpdates(self))
self.actionSave_Settings.triggered.connect(lambda: settings.saveSettings(self))
self.actionSave_Settings_As.triggered.connect(lambda: settings.saveSettingsAs(self))
@@ -210,6 +212,9 @@ def __init__(self, parent: Optional[QWidget] = None):
self.alignregionButton.clicked.connect(lambda: alignRegion(self))
self.selectwindowButton.clicked.connect(lambda: selectWindow(self))
self.startImageReloadButton.clicked.connect(lambda: self.loadStartImage(True, True))
+ self.actionCheck_for_Updates_on_Open.changed.connect(lambda: self.set_check_for_updates_on_open(
+ self.actionCheck_for_Updates_on_Open.isChecked())
+ )
# update x, y, width, and height when changing the value of these spinbox's are changed
self.xSpinBox.valueChanged.connect(self.updateX)
@@ -221,6 +226,8 @@ def __init__(self, parent: Optional[QWidget] = None):
self.updateCurrentSplitImage.connect(self.updateSplitImageGUI)
self.afterSettingHotkeySignal.connect(lambda: afterSettingHotkey(self))
self.startAutoSplitterSignal.connect(self.autoSplitter)
+ self.updateCheckerWidgetSignal.connect(lambda latest_version, check_on_open:
+ open_update_checker(self, latest_version, check_on_open))
self.resetSignal.connect(self.reset)
self.skipSplitSignal.connect(self.skipSplit)
self.undoSplitSignal.connect(self.undoSplit)
@@ -1107,10 +1114,6 @@ def updateSplitImage(self, custom_image_file: str = "", from_start_image: bool =
# exit safely when closing the window
def closeEvent(self, a0: Optional[QtGui.QCloseEvent] = None):
- # save global setting values here
- self.setting_check_for_updates_on_open.setValue("check_for_updates_on_open",
- self.actionCheck_for_Updates_on_Open.isChecked())
-
def exitProgram():
if a0 is not None:
a0.accept()
@@ -1161,7 +1164,7 @@ def main():
main_window.show()
# Needs to be after main_window.show() to be shown over
if main_window.actionCheck_for_Updates_on_Open.isChecked():
- checkForUpdates(main_window, check_for_updates_on_open=True)
+ checkForUpdates(main_window, check_on_open=True)
# Kickoff the event loop every so often so we can handle KeyboardInterrupt (^C)
timer = QtCore.QTimer()
diff --git a/src/gen/design.pyi b/src/gen/design.pyi
index 6d951853..a7a38ee1 100644
--- a/src/gen/design.pyi
+++ b/src/gen/design.pyi
@@ -1,6 +1,9 @@
+from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import QMainWindow
class Ui_MainWindow():
+ actionCheck_for_Updates_on_Open: QAction
+
def setupUi(self, MainWindow: QMainWindow) -> None:
...
diff --git a/src/menu_bar.py b/src/menu_bar.py
index cf67f09d..cb156f24 100644
--- a/src/menu_bar.py
+++ b/src/menu_bar.py
@@ -4,18 +4,25 @@
from AutoSplit import AutoSplit
import os
+
import requests
-from PyQt6 import QtWidgets
+from simplejson.errors import JSONDecodeError
from packaging import version
-from gen import about as about_, resources_rc, update_checker # noqa: F401
+from PyQt6 import QtWidgets
+from PyQt6.QtCore import QThread
+from requests.exceptions import RequestException
+
import error_messages
+import settings_file
+from gen import about, design, resources_rc, update_checker # noqa: F401
+
# AutoSplit Version number
VERSION = "1.6.1"
# About Window
-class AboutWidget(QtWidgets.QWidget, about_.Ui_aboutAutoSplitWidget):
+class __AboutWidget(QtWidgets.QWidget, about.Ui_aboutAutoSplitWidget):
def __init__(self):
super().__init__()
self.setupUi(self)
@@ -25,57 +32,64 @@ def __init__(self):
self.show()
-class UpdateCheckerWidget(QtWidgets.QWidget, update_checker.Ui_UpdateChecker):
- def __init__(self, latest_version: str, autosplit: AutoSplit, check_for_updates_on_open: bool = False):
+def open_about(self: AutoSplit):
+ self.AboutWidget = __AboutWidget()
+
+
+class __UpdateCheckerWidget(QtWidgets.QWidget, update_checker.Ui_UpdateChecker):
+ def __init__(self, latest_version: str, design_window: design.Ui_MainWindow, check_on_open: bool = False):
super().__init__()
self.setupUi(self)
self.labelCurrentVersionNumber.setText(VERSION)
self.labelLatestVersionNumber.setText(latest_version)
self.pushButtonLeft.clicked.connect(self.openUpdate)
- self.pushButtonRight.clicked.connect(self.closeWindow)
- self.autosplit = autosplit
+ self.checkBoxDoNotAskMeAgain.stateChanged.connect(self.doNotAskMeAgainStateChanged)
+ self.design_window = design_window
if version.parse(latest_version) > version.parse(VERSION):
- self.labelUpdateStatus.setText("There is an update available for AutoSplit.")
- self.labelGoToDownload.setText("Open download page?")
- self.pushButtonLeft.setVisible(True)
- self.pushButtonLeft.setText("Open")
- self.pushButtonRight.setText("Later")
- if not check_for_updates_on_open:
- self.checkBoxDoNotAskMeAgain.setVisible(False)
+ self.checkBoxDoNotAskMeAgain.setVisible(check_on_open)
self.show()
- elif not check_for_updates_on_open:
+ elif not check_on_open:
self.labelUpdateStatus.setText("You are on the latest AutoSplit version.")
+ self.labelGoToDownload.setVisible(False)
self.pushButtonLeft.setVisible(False)
self.pushButtonRight.setText("OK")
self.checkBoxDoNotAskMeAgain.setVisible(False)
self.show()
def openUpdate(self):
- if self.checkBoxDoNotAskMeAgain.isChecked():
- self.autosplit.actionCheck_for_Updates_on_Open.setChecked(False)
os.system('start "" https://github.com/Toufool/Auto-Split/releases/latest')
self.close()
- def closeWindow(self):
- if self.checkBoxDoNotAskMeAgain.isChecked():
- self.autosplit.actionCheck_for_Updates_on_Open.setChecked(False)
- self.close()
+ def doNotAskMeAgainStateChanged(self):
+ settings_file.set_check_for_updates_on_open(
+ self.design_window,
+ self.checkBoxDoNotAskMeAgain.isChecked())
+
+
+def open_update_checker(autosplit: AutoSplit, latest_version: str, check_on_open: bool):
+ autosplit.UpdateCheckerWidget = __UpdateCheckerWidget(latest_version, autosplit, check_on_open)
def viewHelp():
os.system('start "" https://github.com/Toufool/Auto-Split#tutorial')
-def about(autosplit: AutoSplit):
- autosplit.aboutWidget = AboutWidget()
+class __CheckForUpdatesThread(QThread):
+ def __init__(self, autosplit: AutoSplit, check_on_open: bool):
+ super().__init__()
+ self.autosplit = autosplit
+ self.check_on_open = check_on_open
+
+ def run(self):
+ try:
+ response = requests.get("https://duckduckgo.com/?q=pyright+generate+stub+file&t=opera&ia=web")
+ latest_version = response.json()["name"].split("v")[1]
+ self.autosplit.updateCheckerWidgetSignal.emit(latest_version, self.check_on_open)
+ except (RequestException, KeyError, JSONDecodeError):
+ if not self.check_on_open:
+ self.autosplit.showErrorSignal.emit(error_messages.checkForUpdatesError)
-def checkForUpdates(autosplit: AutoSplit, check_for_updates_on_open: bool = False):
- try:
- response = requests.get("https://api.github.com/repos/Toufool/Auto-Split/releases/latest")
- latest_version = response.json()["name"].split("v")[1]
- except requests.exceptions.RequestException:
- if not check_for_updates_on_open:
- error_messages.checkForUpdatesError()
- else:
- autosplit.updateCheckerWidget = UpdateCheckerWidget(latest_version, autosplit, check_for_updates_on_open)
+def checkForUpdates(autosplit: AutoSplit, check_on_open: bool = False):
+ autosplit.CheckForUpdatesThread = __CheckForUpdatesThread(autosplit, check_on_open)
+ autosplit.CheckForUpdatesThread.start()
diff --git a/src/settings_file.py b/src/settings_file.py
index 55636563..1a6322c2 100644
--- a/src/settings_file.py
+++ b/src/settings_file.py
@@ -8,8 +8,9 @@
import pickle
import keyboard # https://github.com/boppreh/keyboard/issues/505
from win32 import win32gui
-from PyQt6 import QtWidgets
+from PyQt6 import QtCore, QtWidgets
+from gen import design
import error_messages
# TODO with settings refactoring
from hotkeys import _hotkey_action # type: ignore
@@ -21,7 +22,7 @@
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module: str, name: str):
- raise pickle.UnpicklingError("'%s.%s' is forbidden" % (module, name))
+ raise pickle.UnpicklingError(f"'{module}.{name}' is forbidden")
def loadPyQtSettings(autosplit: AutoSplit):
@@ -319,3 +320,26 @@ def loadSettings(autosplit: AutoSplit, load_settings_on_open: bool = False, load
autosplit.last_successfully_loaded_settings_file_path = autosplit.load_settings_file_path
autosplit.checkLiveImage()
autosplit.loadStartImage()
+
+
+def load_check_for_updates_on_open(designWindow: design.Ui_MainWindow):
+ """
+ Retrieve the "Check For Updates On Open" QSettings and set the checkbox state
+ These are only global settings values. They are not *pkl settings values.
+ """
+
+ value = QtCore \
+ .QSettings("AutoSplit", "Check For Updates On Open") \
+ .value("check_for_updates_on_open", True, type=bool)
+ designWindow.actionCheck_for_Updates_on_Open.setChecked(value)
+
+
+def set_check_for_updates_on_open(designWindow: design.Ui_MainWindow, value: bool):
+ """
+ Sets the "Check For Updates On Open" QSettings value and the checkbox state
+ """
+
+ designWindow.actionCheck_for_Updates_on_Open.setChecked(value)
+ QtCore \
+ .QSettings("AutoSplit", "Check For Updates On Open") \
+ .setValue("check_for_updates_on_open", value)
diff --git a/typings/simplejson/errors.pyi b/typings/simplejson/errors.pyi
new file mode 100644
index 00000000..d98b7495
--- /dev/null
+++ b/typings/simplejson/errors.pyi
@@ -0,0 +1,34 @@
+"""
+This type stub file was generated by pyright.
+"""
+
+"""Error classes used by simplejson
+"""
+__all__ = ['JSONDecodeError']
+def linecol(doc, pos): # -> tuple[Unknown, Unknown]:
+ ...
+
+def errmsg(msg, doc, pos, end=...): # -> str:
+ ...
+
+class JSONDecodeError(ValueError):
+ """Subclass of ValueError with the following additional properties:
+
+ msg: The unformatted error message
+ doc: The JSON document being parsed
+ pos: The start index of doc where parsing failed
+ end: The end index of doc where parsing failed (may be None)
+ lineno: The line corresponding to pos
+ colno: The column corresponding to pos
+ endlineno: The line corresponding to end (may be None)
+ endcolno: The column corresponding to end (may be None)
+
+ """
+ def __init__(self, msg, doc, pos, end=...) -> None:
+ ...
+
+ def __reduce__(self): # -> tuple[Type[Self@JSONDecodeError], tuple[Unknown, Unknown, Unknown, Unknown]]:
+ ...
+
+
+