diff --git a/controller/Frames.py b/controller/Frames.py new file mode 100644 index 0000000..b677dff --- /dev/null +++ b/controller/Frames.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class Frames(Enum): + Home = 1 + Info = 2 \ No newline at end of file diff --git a/controller/HomeController.py b/controller/HomeController.py new file mode 100644 index 0000000..dab7f3f --- /dev/null +++ b/controller/HomeController.py @@ -0,0 +1,26 @@ + + +from controller.MainController import MainController + + +class HomeController: + """ + Controller - HomeController + + desc... + """ + # Variables + main_controller = None + view = None + + # Constructor + def __init__(self, controller: MainController) -> None: + self.main_controller = controller + + def set_view(self, view) -> None: + """ + [function for view] + + :view: -> The view that this controller manage. + """ + self.view = view \ No newline at end of file diff --git a/controller/MainController.py b/controller/MainController.py new file mode 100644 index 0000000..7e697cd --- /dev/null +++ b/controller/MainController.py @@ -0,0 +1,27 @@ +from controller.Frames import Frames + + +class MainController: + """ + Controller - MainController + + desc... + """ + # Variables + view = None + + # Constructor + def __init__(self) -> None: + pass + + def change_frame(self, frame: Frames.value) -> None: + """ + [function for controller] + """ + pass + + def set_view(self, view) -> None: + """ + [function for view] + """ + self.view = view \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..1e0665c --- /dev/null +++ b/main.py @@ -0,0 +1,42 @@ +# from controller.MainController import * +# from view.MainWindow import * + +# from view.View import View +# from controller.Controller import Controller +# from model.Email import Email + + +# import tkinter as tk + +# class App(tk.Tk): # windows manager +# def __init__(self): +# super().__init__() + +# self.title('Tkinter MVC Demo') + +# # create a model +# model = Email('hello@pythontutorial.net') + +# # create a view and place it on the root window +# view = View(self) +# view.grid(row=0, column=0, padx=10, pady=10) + +# # create a controller +# controller = Controller(model, view) + +# # set the controller to view +# view.set_controller(controller) + +from controller.MainController import MainController +from view.MainWindow import MainWindow +from view.View import View + + +if __name__ == '__main__': + controller = MainController() + + app = MainWindow(controller) + + app.set_view(View(app)) + + app.mainloop() \ No newline at end of file diff --git a/model/webpic.py b/model/webpic.py new file mode 100644 index 0000000..774e1f4 --- /dev/null +++ b/model/webpic.py @@ -0,0 +1,118 @@ +import os +from urllib import request +from urllib.error import HTTPError, URLError +from bs4 import BeautifulSoup, Tag, ResultSet + +class WebPicDownloader(): + """ + WebPicDownloader + + webpicdownloader is a simple tool able to + find and download all pictures on a webpage. + + @author EndMove + @version 1.0.0 + """ + # Variables + path: str + headers: dict = {'User-Agent': "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"} + + # Constructor + def __init__(self, path: str = os.getcwd()) -> None: + """Constructor""" + self.path = path + + # Internal functions + def __getHtml(self, url: str) -> str: + """Allow to retrieve the HTML content of a website""" + req = request.Request(url, headers=self.headers) + response = request.urlopen(req) + return response.read().decode('utf-8') + + def __findAllImg(self, html: str) -> ResultSet: + """Allow to retrieve all images of an html page""" + soup = BeautifulSoup(html, 'html.parser') + return soup.find_all('img') + + def __findImgLink(self, img: Tag) -> str: + """Allow to retrieve the link of a picture""" + if img.get('src'): + link = img.get('src') + elif img.get('data-src'): + link = img.get('data-src') + elif img.get('data-srcset'): + link = img.get('data-srcset') + elif img.get('data-fallback-src'): + link = img.get('data-fallback-src') + else: + raise ValueError("Unable to find image url") + if not 'http' in link: + raise ValueError("Bad image link") + return link + + def __findImageType(self, imgLink: str) -> str: + """Allow to retrieve the right image type""" + type = imgLink.split('.')[-1] + if '?' in type: + type = type.split('?')[0] + return type + + def __downloadImg(self, url: str, filename: str) -> None: + """Allow to download a picture from internet""" + req = request.Request(url, headers=self.headers) + rawImg = request.urlopen(req).read() + with open(filename, 'wb') as img: + img.write(rawImg) + + def __initializeFolder(self, folderPath: str) -> None: + """Init the folder on which put downloaded images""" + if not os.path.exists(folderPath): + os.mkdir(folderPath) + else: + raise ValueError("the folder already exists, it may already contain images") + + # Public functions + def download(self, url: str, folderName: str) -> None: + """ + Start downloading all pictures of a website + + :url: -> The url of the website to annalyse.\n + :folderName: -> The name of the folder in which to upload the photos. + """ + try: + count = 0 + folderPath = f"{self.path}/{folderName}/" + html = self.__getHtml(url) + images = self.__findAllImg(html) + + self.__initializeFolder(folderPath) + print(f"\nWebPicDownload found {len(images)} images on the website.") + + for i, img in enumerate(images): + try: + imgLink = self.__findImgLink(img) + self.__downloadImg(imgLink, f"{folderPath}image-{i}.{self.__findImageType(imgLink)}") + print(f"SUCCESS: File n°{i} successfuly downloaded.") + count += 1 + except ValueError as err: + print(f"ERROR: Unable to process image n°{i} -> [{err}].") + except Exception as err: + print(f"ERROR: Unable to process image n°{i}, an unknown error occured -> [{err}].") + + print(f"WebPicDownloader has processed {count} images out of {len(images)}.") + except HTTPError as err: + print(f"ERROR: An http error occured -> [{err}].") + except (ValueError, URLError) as err: + print(f"ERROT: An error occured with the url -> [{err}].") + except Exception as err: + print(f"ERROR: An unknown error occured -> [{err}]") + +if __name__ == "__main__": + wpd = WebPicDownloader() + while True: + url = input("Website URL ? ") + name = input("Folder name ? ") + wpd.download(url, name) + if "n" == input("Do you want to continue [Y/n] ? ").lower(): + break + print("Good bye !") \ No newline at end of file diff --git a/view/HomeView.py b/view/HomeView.py new file mode 100644 index 0000000..96b5ac0 --- /dev/null +++ b/view/HomeView.py @@ -0,0 +1,75 @@ +import tkinter as tk +from tkinter import ttk + +class View(ttk.Frame): + def __init__(self, parent): + super().__init__(parent) + + # create widgets + # label + self.label = ttk.Label(self, text='Email:') + self.label.grid(row=1, column=0) + + # email entry + self.email_var = tk.StringVar() + self.email_entry = ttk.Entry(self, textvariable=self.email_var, width=30) + self.email_entry.grid(row=1, column=1, sticky=tk.NSEW) + + # save button + self.save_button = ttk.Button(self, text='Save', command=self.save_button_clicked) + self.save_button.grid(row=1, column=3, padx=10) + + # message + self.message_label = ttk.Label(self, text='', foreground='red') + self.message_label.grid(row=2, column=1, sticky=tk.W) + + # set the controller + self.controller = None + + def set_controller(self, controller): + """ + Set the controller + :param controller: + :return: + """ + self.controller = controller + + def save_button_clicked(self): + """ + Handle button click event + :return: + """ + if self.controller: + self.controller.save(self.email_var.get()) + + def show_error(self, message): + """ + Show an error message + :param message: + :return: + """ + self.message_label['text'] = message + self.message_label['foreground'] = 'red' + self.message_label.after(3000, self.hide_message) + self.email_entry['foreground'] = 'red' + + def show_success(self, message): + """ + Show a success message + :param message: + :return: + """ + self.message_label['text'] = message + self.message_label['foreground'] = 'green' + self.message_label.after(3000, self.hide_message) + + # reset the form + self.email_entry['foreground'] = 'black' + self.email_var.set('') + + def hide_message(self): + """ + Hide the message + :return: + """ + self.message_label['text'] = '' \ No newline at end of file diff --git a/view/MainWindow.py b/view/MainWindow.py new file mode 100644 index 0000000..b0a3e0d --- /dev/null +++ b/view/MainWindow.py @@ -0,0 +1,31 @@ +from controller.MainController import MainController +import tkinter as tk + +class MainWindow(tk.Tk): + """ + View - MainWindow + + dec... + """ + # Variables + controller: MainController + + # Constructor + def __init__(self, controller: MainController): + super().__init__() + + # Init main window + self.title('Tkinter MVC Demo') + + # Save and setup main controller + self.controller = controller + controller.set_view(self) + + def set_view(self, view): + self.view = view + self.view.grid(row=0, column=0, padx=10, pady=10) + + # Section Interface + def show_frame(self, frame): + pass + # End Section Interface \ No newline at end of file