Restructuration + init test system

This commit is contained in:
2022-09-11 11:52:41 +02:00
parent a3dd6698fc
commit 6b26b89c69
22 changed files with 60 additions and 82 deletions

View File

@@ -0,0 +1,18 @@
from enum import Enum
class Frames(Enum):
"""
Enumeration - Frames
Lists the different windows of the program in order to facilitate
their call during the execution. Each parameter of the enumeration
represents a Frame/Tab.
@author Jérémi Nihart / EndMove
@link https://git.endmove.eu/EndMove/WebPicDownloader
@version 1.0.0
@since 2022-08-30
"""
HOME = 1 # Home view
INFO = 2 # Info & copyright view

View File

@@ -0,0 +1,118 @@
from webpicdownloader.controller.MainController import MainController
from webpicdownloader.model.WebPicDownloader import MessageType, WebPicDownloader
class HomeController:
"""
Controller - HomeController
This controller handles all the interaction directly related to the download.
@author Jérémi Nihart / EndMove
@link https://git.endmove.eu/EndMove/WebPicDownloader
@version 1.0.0
@since 2022-08-30
"""
# Variables
__main_controller: MainController = None
__view = None
__webpic: WebPicDownloader = None
# Constructor
def __init__(self, controller: MainController, webpic: WebPicDownloader) -> None:
"""
Constructor
* :controller: -> The main application cpntroller.
* :webpic: -> The webpicdownloader instance.
"""
# Setub variables
self.__main_controller = controller
self.__webpic = webpic
# setup webpic event
webpic.set_messenger_callback(self.on_webpic_messenger)
webpic.set_success_callback(self.on_webpic_success)
webpic.set_failure_callback(self.on_webpic_failure)
# Subscribe to events
controller.subscribe_to_quite_event(self.on_quit)
# START View methods
def set_view(self, view) -> None:
"""
[function for view]
=> Define the view of this controller.
* :view: -> The view that this controller manage.
"""
self.__view = view
# END View method
# START View events
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.
* :name: -> The name of the folder in which put pictures.
"""
if url.strip() and name.strip():
self.__view.set_interface_state(True)
self.__view.clear_logs()
self.__webpic.start_downloading(url, name)
else:
self.__view.show_error_message("Opss, the url or folder name are not valid!")
# END View events
# START Webpic events
def on_webpic_messenger(self, message: str, type) -> None:
"""
[event function for webpic]
=> This event is called to communicate a message.
* :message: -> Message that webpic send to the controller.
* :type: -> Type of message that webpic send to the controller.
"""
match type:
case MessageType.LOG:
self.__view.add_log(message)
case MessageType.ERROR:
self.__view.show_error_message(message)
case MessageType.SUCCESS:
self.__view.show_success_message(message)
def on_webpic_success(self) -> None:
"""
[event function for webpic]
=> This event is called to indicate that the download has finished successfully.
"""
self.__view.show_success_message("The download has been successfully completed.")
self.__view.set_interface_state(False)
def on_webpic_failure(self) -> None:
"""
[event function for webpic]
=> This event is called to indicate that there was a problem during the download.
"""
self.__view.show_error_message("A critical error preventing the download occurred, check the logs.")
self.__view.set_interface_state(False)
# END Webpic events
# START Controller methods
def on_quit(self) -> bool:
"""
[event function for controller]
=> Call this event when a request to exit is thrown.
"""
if self.__webpic.is_download_running():
if self.__main_controller.show_question_dialog(
"Are you sure?",
"Do you really want to quit while the download is running?\nThis will stop the download."
):
self.__webpic.stop_downloading() # hot stop deamon
return False
return True
self.__webpic.stop_downloading(block=True)
# END Controller methods

View File

@@ -0,0 +1,54 @@
from webpicdownloader.controller.Frames import Frames
from webpicdownloader.controller.MainController import MainController
class InfoController:
"""
Controller - InfoController
This controller manages the display of information in the information view.
@author Jérémi Nihart / EndMove
@link https://git.endmove.eu/EndMove/WebPicDownloader
@version 1.0.0
@since 2022-08-30
"""
# Variables
__main_controller: MainController = None
__view = None
# Constructor
def __init__(self, controller: MainController) -> None:
"""
Constructor
* :controller: -> The main application cpntroller.
"""
# Setup variables
self.__main_controller = controller
# START View methods
def set_view(self, view) -> None:
"""
[function for view]
:view: -> The view that this controller manage.
"""
self.__view = view
self.__view.set_title(self.__main_controller.get_config('about_title'))
self.__view.set_content(self.__main_controller.get_config('about_content'))
self.__view.set_version(
f"version: {self.__main_controller.get_config('app_version')} - {self.__main_controller.get_config('app_version_date')}"
)
# END View method
# START View events
def on_change_view(self, frame: Frames) -> None:
"""
[event function for view]
=> Call this event method when the user requests to change the window.
* :frame: -> The frame we want to launch.
"""
self.__main_controller.change_frame(frame)
# END View events

View File

@@ -0,0 +1,134 @@
import os
from webpicdownloader.controller.Frames import Frames
class MainController:
"""
Controller - MainController
This controller manages all the main interaction, change of windows,
dialogs, stop... It is the main controller.
@author Jérémi Nihart / EndMove
@link https://git.endmove.eu/EndMove/WebPicDownloader
@version 1.0.0
@since 2022-08-30
"""
# Variables
__config: dict = None
__view = None
__quite_event_subscribers: list = None
# Constructor
def __init__(self, config: dict) -> None:
"""
Constructor
* :config: -> The application configuration (a dictionary).
"""
# Setup variables
self.__config = config
self.__quite_event_subscribers = []
# START View methods
def set_view(self, view) -> None:
"""
[function for view]
=> Allow to define the controller view.
* :view: -> The view that this controller manage and setup it.
"""
self.__view = view
view.set_window_title(self.get_config('app_name'))
def on_open_folder(self) -> None:
"""
[event function for view]
=> Event launch when you ask to open the current folder.
"""
os.startfile(self.get_config('app_folder')) # Open the file explorer on working dir
def on_quite(self) -> None:
"""
[event function for view]
=> Event launch when you ask to quit the program. This event is propagated
to the subscribers, they can eventually cancel the event
"""
for callback in self.__quite_event_subscribers:
if callback():
return
self.__view.close_window() # End the program
def on_check_for_update(self) -> None:
"""
[event function for view]
=> Event launched when a check for available updates is requested.
"""
# TODO write the function
self.show_information_dialog(self.get_config('app_name'), "Oupss, this functionality isn't available yet!\nTry it again later.")
def on_about(self) -> None:
"""
[event function for view]
=> Event launched when a request for more information arise.
"""
self.change_frame(Frames.INFO)
# END View methods
# START Controller methods
def change_frame(self, frame: Frames) -> None:
"""
[function for controller]
=> Allows you to request a frame change in the main window.
* :frame: -> The frame we want to display on the window instead of the current frame.
"""
self.__view.show_frame(frame)
def get_config(self, name: str) -> str|int:
"""
[function for controller]
=> Allows controllers to access the application's configuration.
* :name: -> The name of the configuration parameter for which we want to access the configured value.
"""
if self.__config.get(name):
return self.__config.get(name)
else:
raise ValueError("Unable to find a configuration with this name")
def show_question_dialog(self, title: str='title', message: str='question?', icon: str='question') -> bool:
"""
[function for controller]
=> Ask a question to the user and block until he answers with yes or no.
* :title: -> Title of the dialogue.
* :message: -> Message of the dialogue.
* :icon: -> Icon of the dialogue
"""
return self.__view.show_question_dialog(title, message, icon)
def show_information_dialog(self, title: str='title', message: str='informations!', icon: str='info') -> bool:
"""
[function for controller]
=> Display a pop-up information dialog to the user.
* :title: -> Title of the dialogue.
* :message: -> Message of the dialogue.
* :icon: -> Icon of the dialogue
"""
return self.__view.show_information_dialog(title, message, icon)
# END Controller methods
# START Controller events
def subscribe_to_quite_event(self, callback) -> None:
"""
[function for controller]
=> Subscription function allowing to be warned if a request to quit occurs.
In the case where the callback function returns False the process continues
but if the callback returns True the process is aborted.
* :callback: -> Callback function that will be called when a request to exit occurs.
"""
self.__quite_event_subscribers.append(callback)
# END Controller events