From 5c6609ff0a81a6fa5c2203a49f5c88b231c2695f Mon Sep 17 00:00:00 2001 From: EndMove Date: Thu, 1 Sep 2022 11:47:34 +0200 Subject: [PATCH] fixing bugs with the textarea and background task --- controller/HomeController.py | 23 +++++++++++++++------ util/AsyncTask.py | 40 ++++++++++++++++++++++++++++++++++++ view/HomeView.py | 3 ++- 3 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 util/AsyncTask.py diff --git a/controller/HomeController.py b/controller/HomeController.py index c1a6ae5..40f0d59 100644 --- a/controller/HomeController.py +++ b/controller/HomeController.py @@ -1,5 +1,5 @@ -import time from controller.MainController import MainController +from util.AsyncTask import AsyncTask class HomeController: @@ -20,6 +20,12 @@ class HomeController: # Constructor def __init__(self, controller: MainController, webpic) -> None: + """ + Constructor + + :controller: -> The main application cpntroller. + :webpic: -> The webpicdownloader instance. + """ self.__main_controller = controller self.__webpic = webpic @@ -27,6 +33,7 @@ class HomeController: def set_view(self, view) -> None: """ [function for view] + => Define the view of this controller. :view: -> The view that this controller manage. """ @@ -38,6 +45,7 @@ class HomeController: def on_change_view(self, frame) -> None: """ [event function for view] + => Call this event method when the user requests to change the window. :frame: -> The frame we want to launch. """ @@ -49,19 +57,22 @@ class HomeController: def on_download_requested(self, url: str, name: str) -> None: """ [event function for view] + => Call this event method when the user requests to download :url: -> The url of the website to use for pic-download.\n :name: -> The name of the folder in which put pictures. """ - if url.strip() and name.strip() : - # TODO use webpic here to download files - print(f"url : {url} -- name : {name}") - - self.__view.clear_logs() # BUG this process must be asynchrone ... + # Define the download task function (to call in a AsyncTask) + def download_task(): + self.__view.clear_logs() if self.__webpic.download(url, name): self.__view.show_success_message("The download has been successfully completed.") else: self.__view.show_error_message("A critical error preventing the download occurred, check the logs.") + + # Verify variable and start AsyncTask + if url.strip() and name.strip() : + AsyncTask(download_task).start() else: self.__view.show_error_message("Opss, the url or folder name are not valid!") # END View events diff --git a/util/AsyncTask.py b/util/AsyncTask.py new file mode 100644 index 0000000..c843da1 --- /dev/null +++ b/util/AsyncTask.py @@ -0,0 +1,40 @@ +import threading + + +class AsyncTask(threading.Thread): + """ + AsyncTask + + AsyncTask is a utility class allowing to execute a task asynchronously in a thread. + For more informations read the constructor documentation. + + @author Jérémi Nihart / EndMove + @link https://git.endmove.eu/EndMove/WebPicDownloader + @version 1.0.0 + @since 2022-09-01 + """ + # Variables + __callback = None + __args: list = None + + # Constructor + def __init__(self, callback, args=()) -> None: + """ + Constructor + => Spacify here the function that should be launched asynchronously. Then use the + function {AsyncTask.start()} to start the thread and the processing. + [!]: The function {AsyncTask.run()} is reserved for the thread and should not be run + from outside. + + :callback: -> Is the function to launch asynchronously. + :args: -> Argument to pass to the function when executing it. + """ + super().__init__() + self.__callback = callback + self.__args = args + + def run(self) -> None: + """ + [!] : This function should not be used! Start the task with {AsyncTask.start()}! + """ + self.__callback(*self.__args) \ No newline at end of file diff --git a/view/HomeView.py b/view/HomeView.py index 013a4da..1fd2904 100644 --- a/view/HomeView.py +++ b/view/HomeView.py @@ -78,6 +78,7 @@ class HomeView(ttk.Frame): """ self.log_textarea.configure(state=tk.NORMAL) self.log_textarea.insert(tk.END, f"~ {line}\n") + self.log_textarea.see(tk.END) self.log_textarea.configure(state=tk.DISABLED) def clear_logs(self) -> None: @@ -86,7 +87,7 @@ class HomeView(ttk.Frame): TODO desc """ self.log_textarea.configure(state=tk.NORMAL) - self.log_textarea.delete("1.0", tk.END) + self.log_textarea.delete('1.0', tk.END) self.log_textarea.configure(state=tk.DISABLED) def show_error_message(self, message) -> None: