Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 47 additions & 14 deletions src/AutoSplit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/python3.9
# -*- coding: utf-8 -*-
from typing import Callable, List, Optional
import traceback
from types import FunctionType, TracebackType
from typing import Callable, List, Optional, Type

from copy import copy
from PyQt6 import QtCore, QtGui, QtTest, QtWidgets
Expand Down Expand Up @@ -51,6 +53,8 @@ class AutoSplit(QtWidgets.QMainWindow, design.Ui_MainWindow):
undoSplitSignal = QtCore.pyqtSignal()
pauseSignal = QtCore.pyqtSignal()
afterSettingHotkeySignal = QtCore.pyqtSignal()
# Use this signal when trying to show an error from outside the main thread
showErrorSignal = QtCore.pyqtSignal(FunctionType)

def __init__(self, parent=None):
super(AutoSplit, self).__init__(parent)
Expand Down Expand Up @@ -104,7 +108,7 @@ def run(self):
try:
line = input()
except RuntimeError:
# stdin not supported or lost, stop looking for inputs
self.autosplit.showErrorSignal.emit(error_messages.stdinLostError)
break
# TODO: "AutoSplit Integration" needs to call this and wait instead of outright killing the app.
# TODO: See if we can also get LiveSplit to wait on Exit in "AutoSplit Integration"
Expand Down Expand Up @@ -169,6 +173,7 @@ def run(self):
self.resetSignal.connect(self.reset)
self.skipSplitSignal.connect(self.skipSplit)
self.undoSplitSignal.connect(self.undoSplit)
self.showErrorSignal.connect(lambda errorMessageBox: errorMessageBox())

# live image checkbox
self.liveimageCheckBox.clicked.connect(self.checkLiveImage)
Expand Down Expand Up @@ -1193,22 +1198,50 @@ def exit():

def main():
app = QtWidgets.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon(':/resources/icon.ico'))

main_window = AutoSplit()
main_window.show()
if main_window.actionCheck_for_Updates_on_Open.isChecked():
checkForUpdates(main_window, check_for_updates_on_open=True)
try:
app.setWindowIcon(QtGui.QIcon(':/resources/icon.ico'))
main_window = AutoSplit()
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)

# Kickoff the event loop every so often so we can handle KeyboardInterrupt (^C)
timer = QtCore.QTimer()
timer.timeout.connect(lambda: None)
timer.start(500)

exit_code = app.exec()
except Exception as exception:
# Print error to console if not running in executable
if getattr(sys, 'frozen', False):
error_messages.exceptionTraceback(
"AutoSplit encountered an unrecoverable exception and will now close itself.<br/>"
"Please copy the following message over at<br/>"
"<a href='https://github.com/Toufool/Auto-Split/issues'>github.com/Toufool/Auto-Split/issues</a>",
exception)
else:
traceback.print_exception(type(exception), exception, exception.__traceback__)
sys.exit(1)

# Kickoff the event loop every so often so we can handle KeyboardInterrupt (^C)
timer = QtCore.QTimer()
timer.timeout.connect(lambda: None)
timer.start(500)
# Catch Keyboard Interrupts for a clean close
signal.signal(signal.SIGINT, lambda _, __: sys.exit(app))
signal.signal(signal.SIGINT, lambda code, _: sys.exit(code))

sys.exit(exit_code)

sys.exit(app.exec())

def excepthook(exceptionType: Type[BaseException], exception: BaseException, traceback: Optional[TracebackType]):
# Catch Keyboard Interrupts for a clean close
if exceptionType is KeyboardInterrupt:
sys.exit(0)
error_messages.exceptionTraceback(
"AutoSplit encountered an unhandled exception and will try to recover, "
"however, things may not work quite right.<br/>"
"Please copy the following message over at<br/>"
"<a href='https://github.com/Toufool/Auto-Split/issues'>github.com/Toufool/Auto-Split/issues</a>",
exception)


if __name__ == '__main__':
sys.excepthook = excepthook
main()
31 changes: 25 additions & 6 deletions src/error_messages.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# Error messages
from PyQt6 import QtWidgets
import traceback
from PyQt6 import QtCore, QtWidgets


def setTextMessage(message: str):
msgBox = QtWidgets.QMessageBox()
msgBox.setWindowTitle('Error')
msgBox.setText(message)
msgBox.exec()
def setTextMessage(message: str, details: str = ''):
messageBox = QtWidgets.QMessageBox()
messageBox.setWindowTitle('Error')
messageBox.setTextFormat(QtCore.Qt.TextFormat.RichText)
messageBox.setText(message)
if details:
messageBox.setDetailedText(details)
for button in messageBox.buttons():
if messageBox.buttonRole(button) == QtWidgets.QMessageBox.ButtonRole.ActionRole:
button.click()
break
messageBox.exec()


def splitImageDirectoryError():
Expand Down Expand Up @@ -76,5 +84,16 @@ def noSettingsFileOnOpenError():
def tooManySettingsFilesOnOpenError():
setTextMessage("Too many settings files found. Only one can be loaded on open if placed in the same folder as AutoSplit.exe")


def checkForUpdatesError():
setTextMessage("An error occurred while attempting to check for updates. Please check your connection.")


def stdinLostError():
setTextMessage("stdin not supported or lost, external control like LiveSplit integration will not work.")


def exceptionTraceback(message: str, exception: Exception):
setTextMessage(
message,
"\n".join(traceback.format_exception(None, exception, exception.__traceback__)))
21 changes: 8 additions & 13 deletions src/settings_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,11 @@ def saveSettingsAs(self: AutoSplit):
def loadSettings(self: AutoSplit, load_settings_on_open: bool = False, load_settings_from_livesplit: bool = False):
if load_settings_on_open:

settings_files = []
for file in os.listdir(auto_split_directory):
if file.endswith(".pkl"):
settings_files.append(file)
settings_files = [
file for file
in os.listdir(auto_split_directory)
if file.endswith(".pkl")
]

# find all .pkls in AutoSplit folder, error if there is none or more than 1
if len(settings_files) < 1:
Expand Down Expand Up @@ -190,17 +191,15 @@ def loadSettings(self: AutoSplit, load_settings_on_open: bool = False, load_sett
settings: List[Union[str, int]] = pickle.load(f)
settings_count = len(settings)
if settings_count < 18:
if not load_settings_from_livesplit:
error_messages.oldVersionSettingsFileError()
self.showErrorSignal.emit(error_messages.oldVersionSettingsFileError)
return
# v1.3-1.4 settings. Add default pause_key and auto_start_on_reset_setting
if settings_count == 18:
settings.insert(9, '')
settings.insert(20, 0)
# v1.5 settings
elif settings_count != 20:
if not load_settings_from_livesplit:
error_messages.invalidSettingsError()
self.showErrorSignal.emit(error_messages.invalidSettingsError)
return
self.last_loaded_settings = [
self.split_image_directory,
Expand All @@ -224,11 +223,7 @@ def loadSettings(self: AutoSplit, load_settings_on_open: bool = False, load_sett
self.loop_setting,
self.auto_start_on_reset_setting] = settings
except (FileNotFoundError, MemoryError, pickle.UnpicklingError):
# HACK / Workaround: Executing the error QMessageBox from the auto-controlled Worker Thread makes it hangs.
# I don't like this solution as we should probably ensure the Worker works nicely with PyQt instead,
# but in the mean time, this will do.
if not load_settings_from_livesplit:
error_messages.invalidSettingsError()
self.showErrorSignal.emit(error_messages.invalidSettingsError)
return

self.splitimagefolderLineEdit.setText(self.split_image_directory)
Expand Down