From 758d77fe4b9df0413c0f0e702f42f80165704ff9 Mon Sep 17 00:00:00 2001
From: RedDeadDepresso <94017243+RedDeadDepresso@users.noreply.github.com>
Date: Thu, 25 Jul 2024 01:03:06 +0100
Subject: [PATCH] feat: thread manager
---
app/common/logger.py | 49 +++++++++------
app/common/thread_manager.py | 41 +++++++++++++
app/components/navigation_action_buttons.py | 1 +
app/modules/handler.py | 3 +-
app/modules/request.py | 3 +
app/view/logger_interface.py | 1 +
app/view/main_window.py | 1 +
script.py | 67 +--------------------
8 files changed, 84 insertions(+), 82 deletions(-)
create mode 100644 app/common/thread_manager.py
diff --git a/app/common/logger.py b/app/common/logger.py
index b66f226..85d708c 100644
--- a/app/common/logger.py
+++ b/app/common/logger.py
@@ -19,12 +19,23 @@ class Logger:
# logger box signal is used to output log to logger box
self.logs = ""
self.logger_signal = signalBus.loggerSignal
- self.logger = logging.getLogger("BAAS_Logger")
- formatter = logging.Formatter("%(levelname)8s |%(asctime)20s | %(message)s ")
+ self.logger = logging.getLogger("KAFFIO_Logger")
+ formatter = logging.Formatter("%(levelname)8s |%(category)s | %(message)s ")
handler1 = logging.StreamHandler(stream=sys.stdout)
handler1.setFormatter(formatter)
self.logger.setLevel(logging.INFO)
self.logger.addHandler(handler1)
+ self.text = ['INFO', 'SUCCESS', 'ERROR', 'SKIPPED', 'REPLACED', 'RENAMED', 'REMOVED']
+ # Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
+ self.status = [' INFO', ' SUCCESS', ' ERROR',
+ ' SKIPPED', ' REPLACED', ' RENAMED', ' REMOVED']
+ # Status Color: Blue, Red, Green, Orange,
+ self.statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
+
+ # Status HTML: status
+ self.statusHtml = [
+ f'{status}'
+ for _color, status in zip(self.statusColor, self.status)]
def __out__(self, category: str, message: str, level: int = 1, raw_print=False) -> None:
"""
@@ -41,30 +52,34 @@ class Logger:
while len(logging.root.handlers) > 0:
logging.root.handlers.pop()
- # Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
- status = [' INFO', ' SUCCESS', ' ERROR',
- ' SKIPPED', ' REPLACED', ' RENAMED', ' REMOVED']
- # Status Color: Blue, Red, Green, Orange,
- statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
-
- # Status HTML: status
- statusHtml = [
- f'{status}'
- for _color, status in zip(statusColor, status)]
# If logger box is not None, output log to logger box
# else output log to console
- if self.logger_signal is not None:
+ if self.logger_signal is not None:
message = message.replace('\n', '
').replace(' ', ' ')
adding = (f'''
-
- {statusHtml[level - 1]} | {category} | {message}
+
+ {self.statusHtml[level - 1]} | {category} | {message}
''')
self.logs += adding
self.logger_signal.emit(adding)
else:
- print(f'{statusHtml[level - 1]} | {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | {message}')
+ print(f'{self.statusHtml[level - 1]} | {category} | {message}')
+
+ def colorize(self, line):
+ adding = line
+ for i, s in enumerate(self.text):
+ if s in line:
+ adding = (f'''
+
+ {line}
+
+
+ ''')
+ break
+ self.logs += adding
+ self.logger_signal.emit(adding)
def info(self, category: str, message: str) -> None:
"""
@@ -120,7 +135,7 @@ class Logger:
Output warn log
"""
- self.__out__(category, message, 6)
+ self.__out__(category, message, 7)
def line(self) -> None:
"""
diff --git a/app/common/thread_manager.py b/app/common/thread_manager.py
new file mode 100644
index 0000000..540ef0a
--- /dev/null
+++ b/app/common/thread_manager.py
@@ -0,0 +1,41 @@
+import os
+import subprocess
+import threading
+
+from app.common.signal_bus import signalBus
+from app.common.logger import logger
+
+
+class ThreadManager:
+ def __init__(self):
+ super().__init__()
+ self._script = None
+
+ def start(self):
+ if self._script is not None:
+ self.stop()
+ else:
+ args = []
+ if os.path.exists("script.exe"):
+ args = ["script.exe"]
+ elif os.path.exists("script.py"):
+ args = ["python", "script.py"]
+ self._script = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ threading.Thread(target=self.readOutput).start()
+
+ def readOutput(self):
+ while self._script is not None:
+ line = self._script.stdout.readline().decode('utf-8')
+ if not line:
+ signalBus.stopSignal.emit()
+ else:
+ logger.colorize(line)
+
+ def stop(self):
+ self._script.terminate()
+ self._script = None
+
+
+threadManager = ThreadManager()
+signalBus.startSignal.connect(threadManager.start)
+signalBus.stopSignal.connect(threadManager.stop)
\ No newline at end of file
diff --git a/app/components/navigation_action_buttons.py b/app/components/navigation_action_buttons.py
index 8f53a7a..9d32603 100644
--- a/app/components/navigation_action_buttons.py
+++ b/app/components/navigation_action_buttons.py
@@ -37,6 +37,7 @@ class NavigationActionButtons(QWidget):
def __connectSignalToSlot(self):
self.selectAllButton.clicked.connect(self.onSelectAllClicked)
self.clearAllButton.clicked.connect(self.onClearAllClicked)
+ self.startButton.clicked.connect(self.onStartClicked)
signalBus.startSignal.connect(lambda: self.startButton.setText("Stop"))
signalBus.stopSignal.connect(lambda: self.startButton.setText("Start"))
diff --git a/app/modules/handler.py b/app/modules/handler.py
index 1dbfa9c..3a719ff 100644
--- a/app/modules/handler.py
+++ b/app/modules/handler.py
@@ -4,7 +4,8 @@ class Handler:
def loadConfig(self, config):
self.gamePath = config.get("Core", "GamePath")
- self.config = config.get(str(self))
+ key = str(self).replace(" ", "")
+ self.config = config.get(key)
def handle(self, request):
pass
diff --git a/app/modules/request.py b/app/modules/request.py
index 438da0b..6a03058 100644
--- a/app/modules/request.py
+++ b/app/modules/request.py
@@ -19,6 +19,9 @@ class Request:
logger.info("SCRIPT", "Validating config")
self.validateGamepath()
self._handlers = [x for x in self.handlers if self.isTaskEnabled(x)]
+
+ if not self._handlers:
+ logger.error("SCRIPT", "No task enabled")
if not self._isValid:
raise Exception()
diff --git a/app/view/logger_interface.py b/app/view/logger_interface.py
index 1ba4686..3344f7b 100644
--- a/app/view/logger_interface.py
+++ b/app/view/logger_interface.py
@@ -20,6 +20,7 @@ class LoggerInterface(QFrame):
self.autoscrollButton = PushButton('Autoscroll Off')
self.loggerBox = TextEdit()
self.loggerBox.setReadOnly(True)
+ signalBus.guiMode = True
self.__initWidget()
diff --git a/app/view/main_window.py b/app/view/main_window.py
index 0974ae0..0b587a9 100644
--- a/app/view/main_window.py
+++ b/app/view/main_window.py
@@ -12,6 +12,7 @@ from .logger_interface import LoggerInterface
from .setting_interface import SettingInterface
from ..common.config import ZH_SUPPORT_URL, EN_SUPPORT_URL, cfg
from ..common.signal_bus import signalBus
+from ..common.thread_manager import threadManager
from ..common import resource
from ..components.navigation_checkbox import NavigationCheckBox
from ..components.navigation_action_buttons import NavigationActionButtons
diff --git a/script.py b/script.py
index 3ac79a6..5a44438 100644
--- a/script.py
+++ b/script.py
@@ -1,66 +1,5 @@
-import sys
-import traceback
-try:
- with open('traceback.log', 'w') as f:
- pass
+from app.modules.request import Request
- from app.common.logger import logger
- from app.modules.install_chara import InstallChara
- from app.modules.remove_chara import RemoveChara
- from app.modules.fc_kks import FilterConvertKKS
- from app.modules.create_backup import CreateBackup
-
- class Script:
- def __init__(self, config, file_manager):
- """Initializes the primary azurlane-auto instance with the passed in
- Config instance;
-
- Args:
- config (Config): BAAuto Config instance
- """
- self.config = config
- fileManager = file_manager
- self.modules = {
- 'InstallChara': None,
- 'RemoveChara': None,
- 'CreateBackup': None,
- 'FCKKS': None,
- }
- if self.config.install_chara['Enable']:
- self.modules['InstallChara'] = InstallChara(self.config, fileManager)
- if self.config.remove_chara['Enable']:
- self.modules['RemoveChara'] = RemoveChara(self.config, fileManager)
- if self.config.create_backup['Enable']:
- self.modules['CreateBackup'] = CreateBackup(self.config, fileManager)
- if self.config.fc_kks["Enable"]:
- self.modules['FCKKS'] = FilterConvertKKS(self.config, fileManager)
-
- def run(self):
- for task in self.config.tasks:
- if self.modules[task]:
- logger.info("SCRIPT", f'Start Task: {task}')
- try:
- self.modules[task].logic_wrapper()
- except:
- logger.error("SCRIPT", f'Task error: {task}. For more info, check the traceback.log file.')
- with open('traceback.log', 'a') as f:
- f.write(f'[{task}]\n')
- traceback.print_exc(None, f, True)
- f.write('\n')
- sys.exit(1)
- sys.exit(0)
-
-except:
- print(f'[ERROR] Script Initialisation Error. For more info, check the traceback.log file.')
- with open('traceback.log', 'w') as f:
- f.write(f'Script Initialisation Error\n')
- traceback.print_exc(None, f, True)
- f.write('\n')
- sys.exit(1)
-
-if __name__ == "__main__":
- config = Config('config.json')
- file_manager = FileManager(config)
- script = Script(config, file_manager)
- script.run()
+request = Request()
+request.process()
\ No newline at end of file