def repopulate(self, old_id, r_id): if old_id in self.id_list: self.id_list = [r_id if x == old_id else x for x in self.id_list] else: self.id_list.append(r_id) book = RecipeBook(self.database) next_index = book.select_index(r_id, self.id_list) self.index = next_index if next_index else self.index self.populate()
def create_recipe(self): w = RecipeCreationWindow(Toplevel(self), self.manager, self.database, self.root, None) w.master.focus() self.wait_window(w.master) if w.final != None: old_id = w.old_id book = RecipeBook(self.database) book.cursor.execute( """ SELECT r.id FROM Recipe r WHERE r.name = ? """, [w.final]) r_id = book.cursor.fetchone()[0] book.close() self.manager.my_gui.repopulate(old_id, r_id)
def remove_recipe(self): book = RecipeBook(self.database) recipe, r_id, index = book.select_recipe(self.index, self.id_list) d = ModalWindow( self, "Delete Recipe", "Are you sure you want to delete {}?".format(recipe[0][1])) d.modalWindow.focus() self.wait_window(d.modalWindow) if d.choice == 'Yes': book.delete(r_id) book.close() self.id_list.remove(r_id) self.populate() else: book.close()
def populate(self, search=None): self.ingredient_list.delete(0, END) book = RecipeBook(self.database) columns = ["Ingredient", "Recipe Occurrences"] self.ingredient_list.config(columns=columns) self.sort_dict = [] for col in range(len(columns)): self.sort_dict.append('decreasing') self.ingredient_list.column_config(0, width=180) search_format = " WHERE {}".format(search) if search!=None else "" book.cursor.execute(""" SELECT i.id, i.name, ( SELECT COUNT(*) FROM RecipeIngredient ri WHERE ri.ingredient_id = i.id ) FROM Ingredient i{}""".format(search_format)) results = book.cursor.fetchall() self.id_list = [] self.orig_index_list = [] self.id_dict = {} self.orig_index_dict = {} index = 0 for r in results: if r[2]==0: book.cursor.execute("""DELETE FROM Ingredient WHERE id = ?""", [r[0]]) else: self.id_list.append(r[0]) self.orig_index_dict[r[1]] = index self.orig_index_list.append(index) self.id_dict[r[1]] = r[0] r = r[1:] r_str = r[0] if len(r)>1: for i in range(len(r)-1): r_str+=(u"; {}".format(r[i+1])) item = self.ingredient_list.insert(END, *(r)) index+=1 self.ingredient_list.yview(MOVETO, 0) book.close(True)
def populate(self, search=None, grouped=True): self.load_json() self.recipe_list.delete(0, END) book = RecipeBook(self.database) formatting = [] columns = [] for k, v in sorted(self.recipe_format.items(), key=lambda x: (x[1], x[0])): if v > 0: formatting.append("r." + k.replace(' ', '')) columns.append(k.replace(' ', '').replace('_', ' ').title()) self.recipe_list.column_config(0, width=180) self.recipe_list.config(columns=columns) self.sort_dict = [] for col in range(len(columns)): self.sort_dict.append('decreasing') str_format = ','.join(formatting) search_format = " WHERE {}".format(search) if search != None else "" if grouped: book.cursor.execute(""" SELECT r.id,{} FROM Recipe r LEFT JOIN (SELECT ri.recipe_id as recipe_id, GROUP_CONCAT(ing.name) as name FROM RecipeIngredient ri JOIN Ingredient ing on ing.id = ri.ingredient_id GROUP BY ri.recipe_id) i on i.recipe_id = r.id{} GROUP BY r.id""".format(str_format, search_format)) else: book.cursor.execute(""" SELECT r.id,{} FROM Recipe r LEFT JOIN (SELECT ri.recipe_id as recipe_id, ing.name as name FROM RecipeIngredient ri JOIN Ingredient ing on ing.id = ri.ingredient_id) i on i.recipe_id = r.id{} GROUP BY r.id""".format(str_format, search_format)) results = book.cursor.fetchall() self.id_list = [] self.orig_index_list = [] self.id_dict = {} self.orig_index_dict = {} index = 0 for r in results: self.id_list.append(r[0]) self.orig_index_dict[r[1]] = index self.orig_index_list.append(index) self.id_dict[r[1]] = r[0] r = [r[i] for i in range(1, len(r))] cook_index = self.recipe_format["cook_time"] prep_index = self.recipe_format["prep_time"] serve_index = self.recipe_format["yield"] for i in range(len(r)): if cook_index > 0 and i == cook_index - 1 or prep_index > 0 and i == prep_index - 1: r[i] = "{} min.".format(r[i]) if serve_index > 0 and i == serve_index - 1 and r[i] == 0: r[i] = "-" r_str = r[0] if len(r) > 1: for i in range(len(r) - 1): r_str += (u"; {}".format(r[i + 1])) item = self.recipe_list.insert(END, *(r)) index += 1 self.recipe_list.yview(MOVETO, 0)
def combine_databases(self, source_file, dest_file): source = RecipeBook(source_file) dest = RecipeBook(dest_file) source.cursor.execute(""" SELECT * FROM Recipe""") results = source.cursor.fetchall() if results: force = None for r in results: result = source.cursor.execute( """ SELECT ri.amount AS 'Amount', mu.name AS 'Unit of Measure', i.name AS 'Ingredient', ri.order_num AS 'Order' FROM Recipe r JOIN RecipeIngredient ri on r.id = ri.recipe_id JOIN Ingredient i on i.id = ri.ingredient_id LEFT OUTER JOIN Measure mu on mu.id = measure_id WHERE r.id = ?""", [r[0]]) ingredients = [] for i in sorted(result, key=lambda tup: tup[3]): ingredients.append(i) dest.cursor.execute( """ SELECT * FROM Recipe r WHERE r.name = ?""", [r[1]]) result = dest.cursor.fetchone() if result: if force == None: d = ModalWindow( self.my_gui, "Overwrite All", "Warning: Duplicate recipe names exist.\nDo you want to overwrite all duplicates?\n(Choosing 'No' will result in a prompt for each duplicate case)" ) self.my_gui.wait_window(d.modalWindow) force = (d.choice == 'Yes') if not force: d = ModalWindow( self.my_gui, "Overwrite Recipe", "Warning: Recipe name already exists.\nDo you want to overwrite {}?" .format(r[1])) self.my_gui.wait_window(d.modalWindow) if d.choice == 'Yes': dest.add(r[1], r[2], r[3], r[4], r[5], r[6], r[7], ingredients, True) else: dest.add(r[1], r[2], r[3], r[4], r[5], r[6], r[7], ingredients, force) else: dest.add(r[1], r[2], r[3], r[4], r[5], r[6], r[7], ingredients, False) source.close() dest.renumber() dest.close(True)
preference_file = "recipe_manager_preferences.json" current_dir = os.getcwd() show_tips = True if not os.path.isfile(os.path.join(current_dir, preference_file)): if __platform__ == "win32": database = os.path.join(current_dir, "recipe_data.db") else: database = os.path.join(os.path.expanduser("~"), "Documents/recipe_data.db") else: with open(os.path.join(current_dir, preference_file), "r") as f: recipe_format = json.load(f) database = recipe_format.get("database", None) show_tips = recipe_format.get("show_tips", True) if not database or not os.path.isfile(database): if __platform__ == "win32": database = os.path.join(current_dir, "recipe_data.db") else: database = os.path.join(os.path.expanduser("~"), "Documents/recipe_data.db") with open(os.path.join(current_dir, preference_file), "w") as f: recipe_format["database"] = database json.dump(recipe_format, f) book = RecipeBook(database) book.renumber() book.close(True) root = Tk() manager = RecipeManager(root, database, preference_file, show_tips)
def populate(self): self.canvas.yview(MOVETO, 0) self.canvas.xview(MOVETO, 0) book = RecipeBook(self.database) recipe, r_id, self.index = book.select_recipe(self.index, self.id_list) book.close() name = recipe[0][1] if r_id and recipe[0] else "<Name>" description = recipe[0][2] if r_id and recipe[0] else "<Description>" directions = recipe[0][3] if r_id and recipe[0] else "<Directions>" servings = recipe[0][4] if r_id and recipe[0] else "<Servings>" if r_id and recipe[0] and int(servings) == 0: servings = "-" notes = recipe[0][5] if r_id and recipe[0] else "<Notes>" prep_time = recipe[0][6] if r_id and recipe[0] else "<Prep Time>" cook_time = recipe[0][7] if r_id and recipe[0] else "<Cook Time>" ingredients = [] if r_id and recipe: for i in sorted(recipe[1], key=lambda tup: tup[3]): ingredients.append(i) else: ingredients.append( ("<Amount>", "<Unit>", "<Ingredient>", "<Order>")) self.name_label.destroy() self.name_label = Label(self.frame, text=name, bg="white", font=("Times", 18, "bold"), wraplength=self.canvas_width) self.name_label.grid(row=0, column=0, columnspan=6, sticky=W) self.serv_label.config(text="Serves {} ".format(servings)) self.prep_label.config(text=" Prep: {} min. ".format(prep_time)) self.cook_label.config(text=" Cook: {} min.".format(cook_time)) self.desc_label.destroy() self.desc_label = Label(self.frame, text=description, bg="white", font=("Times", 12, "italic"), justify=LEFT, wraplength=self.canvas_width) self.desc_label.grid(row=2, column=0, columnspan=6, sticky=W) for i in self.ingr_label_list: i[0].destroy() i[1].destroy() i[2].destroy() row = 5 self.ingr_label_list = [] for i in ingredients: if r_id and recipe: prec = 1e4 amount = (int(i[0]), int(float(i[0]) * prec) % prec / prec) val = None for frac in [(.5, "1/2"), (.25, "1/4"), (.125, "1/8"), (.333, "1/3"), (.3333, "1/3"), (.3334, "1/3"), (.75, "3/4"), (.0625, "1/16"), (.666, "2/3"), (.6666, "2/3"), (.6667, "2/3")]: if amount[1] == frac[0]: val = "{} {}".format( amount[0], frac[1]) if amount[0] else frac[1] if i[0] == 0: val = "-" else: val = i[0] self.ingr_label_list.append( (Label(self.frame, text=(val if val else str(amount[0])), bg="white", font=("Times", 10, ""), justify=LEFT, wraplength=80), Label(self.frame, text=i[1], bg="white", font=("Times", 10, ""), justify=LEFT, wraplength=135), Label(self.frame, text=i[2], bg="white", font=("Times", 10, ""), justify=LEFT, wraplength=135))) self.ingr_label_list[row - 5][0].grid(row=row, column=0, sticky=W + N) self.ingr_label_list[row - 5][1].grid(row=row, column=1, sticky=W + N) self.ingr_label_list[row - 5][2].grid(row=row, column=2, columnspan=2, sticky=W + N) row += 1 self.blank_label_2.destroy() self.blank_label_2 = Label(self.frame, text="", bg="white", height=1) self.blank_label_2.grid(row=row, column=1, sticky=W) self.dir_label_title.destroy() self.dir_label_title = Label(self.frame, text="Directions", bg="white", font=("Times", 12, "bold")) self.dir_label_title.grid(row=row + 1, column=0, columnspan=3, sticky=W) self.dir_label.destroy() self.dir_label = Label(self.frame, text=directions, bg="white", font=("Times", 10, ""), justify=LEFT, wraplength=self.canvas_width) self.dir_label.grid(row=row + 2, column=0, columnspan=3, sticky=W) self.blank_label_3.destroy() self.blank_label_3 = Label(self.frame, text="", bg="white", height=1) self.blank_label_3.grid(row=row + 3, column=1, sticky=W) self.note_label_title.destroy() self.note_label_title = Label(self.frame, text="Notes", bg="white", font=("Times", 12, "bold")) self.note_label_title.grid(row=row + 4, column=0, columnspan=3, sticky=W) self.note_label.destroy() self.note_label = Label(self.frame, text=notes, bg="white", font=("Times", 10, ""), justify=LEFT, wraplength=self.canvas_width) self.note_label.grid(row=row + 5, column=0, columnspan=3, sticky=W)
def save_recipe(self): self.name_text.config(bg="white") self.serv_text.config(bg="white") self.prep_text.config(bg="white") self.cook_text.config(bg="white") self.ingr_amount.config(bg="white") self.ingr_text.config(bg="white") if len(self.name_text.get("1.0", END).strip()) == 0: self.name_text.config(bg="red") self.name_text.focus() return servings = self.serv_text.get("1.0", END) if servings.strip() == "-": servings = "0" try: servings = int(servings) if servings < 0: raise ValueError() except ValueError as e: self.serv_text.config(bg="red") self.serv_text.focus() return try: prep = float(self.prep_text.get("1.0", END)) if prep < 0: raise ValueError() except ValueError as e: self.prep_text.config(bg="red") self.prep_text.focus() return try: cook = float(self.cook_text.get("1.0", END)) if cook < 0: raise ValueError() except ValueError as e: self.cook_text.config(bg="red") self.cook_text.focus() return force = False book = RecipeBook(self.database) name = self.name_text.get("1.0", END).strip() book.cursor.execute( """ SELECT * FROM Recipe r WHERE r.name = ?""", [name]) result = book.cursor.fetchone() if result: d = ModalWindow( self, "Overwrite Recipe", "Warning: Recipe name already exists.\nDo you want to overwrite?" ) self.wait_window(d.modalWindow) if d.choice == 'Yes': force = True self.old_id = result[0] else: book.close() return book.add(name, self.desc_text.get("1.0", END).strip(), self.inst_text.get("1.0", END).strip().replace('^o', u'°'), servings, self.note_text.get("1.0", END).strip(), prep, cook, [(ingr[0], ingr[1].strip(), ingr[2].strip()) for ingr in self.ingr_list.get(0, END)], force) book.close(True) self.master.destroy() self.final = name