Пример #1
0
class Display:
    """This class will be used for any render"""
    def __init__(self):
        """Create the window with basic settings"""
        self.database = Database()
        self.bg_color = '#dbe6f0'
        self.config_window()
        self.set_frames()

    @staticmethod
    def open_url(url):
        """function that open the user's browser to the url"""
        webbrowser.open_new(url)

    @staticmethod
    def get_image(image_url):
        """to insert it into a canvas, we need to convert the wanted image
        into a tkimage Object
        """
        response = requests.get(image_url, stream=True)
        image = Image.open(response.raw)
        tkimage = ImageTk.PhotoImage(image)
        return tkimage

    def config_window(self):
        """Create and set the main window"""
        self.window = tk.Tk()
        self.window.title('ChangeYourFood')
        self.window.geometry('1080x720')
        self.window.minsize(480, 360)
        self.window.config(bg=self.bg_color)
        menu_bar = tk.Menu(self.window)
        file_menu = tk.Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="Quitter", command=self.window.quit)
        file_menu.add_command(label="Importer des produits",
                              command=self.database.insert_products_from_api)
        menu_bar.add_cascade(label="Fichier", menu=file_menu)
        self.window.config(menu=menu_bar)

    def set_frames(self):
        """Create the differents frames
        I'm configuring main window col and row to create a skeleton
        interface with header/body/footer
        """
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)
        self.window.rowconfigure(1, weight=10)
        self.window.rowconfigure(2, weight=1)
        self.header_frame = tk.Frame(self.window,
                                     bg=self.bg_color,
                                     bd=2,
                                     relief='groove')
        self.body_frame = tk.Frame(self.window, bg=self.bg_color)
        self.footer_frame = tk.Frame(self.window, bg=self.bg_color)
        self.header_frame.grid(row=0, sticky='news')
        self.body_frame.grid(row=1, sticky='news')
        self.content_frame = tk.Frame(self.body_frame, bg=self.bg_color)
        self.content_frame.pack(expand='YES')
        self.footer_frame.grid(row=2)
        self.footer_frame.rowconfigure(0, weight=1)
        self.footer_frame.columnconfigure(0, weight=5)
        self.footer_frame.columnconfigure(1, weight=1)
        self.footer_frame.columnconfigure(2, weight=5)
        self.footer_frame_left = tk.Frame(self.footer_frame)
        self.footer_frame_center = tk.Frame(self.footer_frame)
        self.footer_frame_right = tk.Frame(self.footer_frame)
        self.footer_frame_left.grid(row=0, column=0, sticky='nesw')
        self.footer_frame_center.grid(row=0, column=1, sticky='nesw')
        self.footer_frame_right.grid(row=0, column=2, sticky='nesw')

    def destroy_frames(self):
        """Destroy the frames"""
        self.header_frame.destroy()
        self.body_frame.destroy()
        self.footer_frame.destroy()

    def set_pagination_product(self, category, page):
        """We need a pagination for the selected category for the products"""
        prev_page = tk.Button(
            self.footer_frame_left,
            text='Précédente',
            font=("Open Sans", 20),
            bg=self.bg_color,
            fg="#222923",
            command=lambda: self.find_select_product(category, page - 1))
        pagination = tk.Label(
            self.footer_frame_center,
            text='Page' + str(page),
            fg="#222923",
            font=("Open Sans", 20),
        )
        next_page = tk.Button(
            self.footer_frame_right,
            text='Suivante',
            font=("Open Sans", 20),
            bg=self.bg_color,
            fg="#222923",
            command=lambda: self.find_select_product(category, page + 1))
        if page > 1:
            prev_page.grid(row=0, column=0, sticky='nesw')
            pagination.grid(row=0, column=1, sticky='nesw')
            next_page.grid(row=0, column=2, sticky='nesw')
        elif page == 1:
            pagination.grid(row=0, column=1, sticky='nesw')
            next_page.grid(row=0, column=2, sticky='nesw')

    def set_pagination_alternative(self, category, page):
        """We need a pagination for the selected category for the alternative"""
        prev_page = tk.Button(
            self.footer_frame_left,
            text='Précédente',
            font=("Open Sans", 20),
            bg=self.bg_color,
            fg="#222923",
            command=lambda: self.get_select_alternative(category, page - 1))
        pagination = tk.Label(
            self.footer_frame_center,
            text='Page' + str(page),
            fg="#222923",
            font=("Open Sans", 20),
        )
        next_page = tk.Button(
            self.footer_frame_right,
            text='Suivante',
            font=("Open Sans", 20),
            bg=self.bg_color,
            fg="#222923",
            command=lambda: self.get_select_alternative(category, page + 1))
        if page > 1:
            prev_page.grid(row=0, column=0, sticky='nesw')
            pagination.grid(row=0, column=1, sticky='nesw')
            next_page.grid(row=0, column=2, sticky='nesw')
        elif page == 1:
            pagination.grid(row=0, column=1, sticky='nesw')
            next_page.grid(row=0, column=2, sticky='nesw')

    def set_title(self, title):
        """Display the title of the page"""
        tk.Label(self.header_frame,
                 text=title,
                 font=("Courrier", 25),
                 bg=self.bg_color,
                 fg="#222923").pack(expand='YES')

    def set_home_return(self):
        """Display a button to come back to home menu"""
        tk.Button(self.header_frame,
                  text="Retourner au menu principal",
                  font=("Courrier", 20),
                  bg=self.bg_color,
                  fg="#222923",
                  command=self.home).pack(expand='YES')

    def home(self):
        """Home menu with 2 paths :
        FIND products : every method of this path will start with 'find'
        GET saved products : every method of this path will start with 'get'
        """
        self.destroy_frames()
        self.set_frames()
        self.set_title('Bonjour, bienvenue sur ChangeYourFood')
        find_path = tk.Button(self.content_frame,
                              text="Trouver un produit de substitution",
                              font=("Open Sans", 20),
                              bg=self.bg_color,
                              fg="#222923",
                              command=self.find_select_category)
        get_path = tk.Button(self.content_frame,
                             text="Voir vos produits de substitution",
                             font=("Open Sans", 20),
                             bg=self.bg_color,
                             fg="#222923",
                             command=self.get_select_category)
        find_path.grid(row=0, column=0, padx=15)
        get_path.grid(row=0, column=1, padx=15)
        self.window.mainloop()

    ######
    #FIND PATH METHODS
    ######

    def find_select_category(self):
        """Select category"""
        self.destroy_frames()
        self.set_frames()
        self.set_title("Selectionner une categorie")
        self.set_home_return()
        for row, category in enumerate(CATEGORIES):
            tk.Button(
                self.content_frame,
                text=category[0],
                font=("Open Sans", 20),
                bg=self.bg_color,
                fg="#222923",
                command=lambda category=category[0]: self.find_select_product(
                    category, 1)).grid(row=math.floor(row / 4),
                                       column=row % 4,
                                       padx=25,
                                       sticky='news')

    def find_select_product(self, category, page):
        """Select the product from the selected category"""
        self.destroy_frames()
        self.set_frames()
        self.set_title("Selectionner un produit")
        self.set_home_return()
        products = self.database.get_products_by_category(category, page)
        if products:
            for row, product in enumerate(products):
                tk.Button(self.content_frame,
                          text=product[1],
                          font=("Open Sans", 15),
                          bg=self.bg_color,
                          fg="#222923",
                          wraplength=400,
                          command=lambda product=product: self.
                          find_save_product(product)).grid(row=math.floor(row /
                                                                          2),
                                                           column=row % 2,
                                                           padx=25,
                                                           pady=15,
                                                           sticky='ew')
            self.set_pagination_product(category, page)
        else:
            tk.Label(self.content_frame,
                     text="Aucun produit trouvé",
                     font=('Courrier', 35),
                     bg=self.bg_color,
                     fg="#222923").grid(row=0)
            tk.Button(self.content_frame,
                      text="Retourner au menu principal",
                      font=("Courrier", 20),
                      bg=self.bg_color,
                      fg="#222923",
                      command=self.home).grid(row=1)

    def find_save_product(self, product):
        """Show the selected product, and a alternative product for it"""
        self.destroy_frames()
        self.set_frames()
        self.set_title('Voici le produit selectionné et son subsitut')
        self.set_home_return()
        alternative = self.database.get_best_alternative(product)
        if not alternative:
            tk.Label(self.content_frame,
                     text='Ce produit est parfait, aucun subtitut trouvé',
                     bg=self.bg_color).pack(expand='YES')
        else:
            self.content_frame.destroy()
            self.set_product_frame(product)
            self.set_product_frame(alternative)
            self.save_button = tk.Button(
                self.footer_frame_center,
                text='Sauvegarder',
                bg=self.bg_color,
                font=('Open Sans', 18),
                command=lambda: self.save_product(alternative, product))
            self.save_button.pack()

    def save_product(self, alternative, product):
        """When the user click to save the product, well, we do it
        return a positive message if it successed
        """
        self.save_button.destroy()
        data = (alternative[1], alternative[2], alternative[3], alternative[4],
                product[0])
        result = self.database.insert_alternative(data)
        if result:
            tk.Label(self.footer_frame_center,
                     bg=self.bg_color,
                     font=('Open Sans', 18),
                     text='Produit enregistré').pack()
        else:
            tk.Label(self.footer_frame_center,
                     bg=self.bg_color,
                     font=('Open Sans', 18),
                     text='Ce Produit est déjà enregistré').pack()

    def set_product_frame(self, product):
        """Display the product selected with his infos"""
        #Create the widget first
        product_frame = tk.LabelFrame(self.body_frame,
                                      text=product[1],
                                      bg=self.bg_color)
        product_name = tk.Label(product_frame,
                                text="Nom : " + str(product[1]),
                                bg=self.bg_color)
        product_nutriscore = tk.Label(product_frame,
                                      text='Nutriscore : ' + str(product[2]),
                                      bg=self.bg_color)
        product_url = tk.Label(product_frame,
                               text='Lien vers la fiche OpenFoodFact',
                               cursor='hand2',
                               bg=self.bg_color)
        product_image = tk.Canvas(product_frame,
                                  bg=self.bg_color,
                                  width=400,
                                  height=400)
        tkimage = self.get_image(product[3])
        product_image.create_image(200, 200, image=tkimage)
        product_image.image = tkimage
        #Display the widgets
        product_frame.pack(expand='YES', fill='both', side='left', padx=15)
        product_name.grid(row=0, column=0, sticky='W')
        product_nutriscore.grid(row=1, column=0, sticky='W')
        product_url.grid(row=2, column=0, sticky='W')
        product_image.grid(row=3, column=0, sticky='NESW')

        #Add a event to the Label to make it open the OFF url
        product_url.bind("<Button-1>", lambda e: self.open_url(product[4]))

    #######
    #GET PATH METHODS
    #######

    def get_select_category(self):
        """Display every categories containing saved product"""
        self.destroy_frames()
        self.set_frames()
        self.set_title("Selectionner une categorie")
        self.set_home_return()
        categories = self.database.get_saved_categories()
        if categories:
            for row, category in enumerate(categories):
                tk.Button(self.content_frame,
                          text=category[1],
                          font=("Open Sans", 20),
                          bg=self.bg_color,
                          fg="#222923",
                          command=lambda category=category[1]: self.
                          get_select_alternative(category, 1)).grid(
                              row=math.floor(row / 4),
                              column=row % 4,
                              padx=25,
                              sticky='news')
        else:
            tk.Label(self.content_frame,
                     text='Aucun subsitut enregistré',
                     font=('Open Sans', 20),
                     bg=self.bg_color).pack()

    def get_select_alternative(self, category, page):
        """Select the product from the selected category"""
        self.destroy_frames()
        self.set_frames()
        self.set_title("Selectionner un produit")
        self.set_home_return()
        products = self.database.get_alternatives_by_category(category, page)
        if products:
            for row, product in enumerate(products):
                tk.Button(self.content_frame,
                          text=product[1],
                          font=("Open Sans", 15),
                          bg=self.bg_color,
                          fg="#222923",
                          wraplength=400,
                          command=lambda product=product: self.
                          get_saved_alternative(product)).grid(row=math.floor(
                              row / 2),
                                                               column=row % 2,
                                                               padx=25,
                                                               pady=15,
                                                               sticky='ew')
            if products > 19:
                self.set_pagination_alternative(category, page)
        else:
            tk.Label(self.content_frame,
                     text="Aucun produit trouvé",
                     font=('Courrier', 35),
                     bg=self.bg_color,
                     fg="#222923").grid(row=0)
            tk.Button(self.content_frame,
                      text="Retourner au menu principal",
                      font=("Courrier", 20),
                      bg=self.bg_color,
                      fg="#222923",
                      command=self.home).grid(row=1)

    def get_saved_alternative(self, alternative):
        """Select the product from the selected category"""
        self.destroy_frames()
        self.set_frames()
        self.set_title("Voici votre produit de substitution")
        self.set_home_return()
        self.content_frame.destroy()
        self.set_product_frame(alternative)