class NewItems(object): def __init__(self, root): self.window = Toplevel(root) self.window.wm_title("Paste types") self.window.grab_set() self.config = ConfigManager("config.xml") self.mod_frame = Frame(self.window) self.mod_frame.grid(row=2, pady=3, sticky="w") Label(self.mod_frame, text="Enter Mod name:").grid(row=0, column=0, padx=3, pady=3) self.modSelector = ttk.Combobox(self.mod_frame, values=self.config.get_mods()) self.modSelector.set(self.config.get_mods()[0]) self.modSelector.grid(row=0, column=1) self.ini_manger = INIManager("app.ini") self.database = DAO(self.ini_manger.read_ini("Database", "Database_Name")) self.duplicate = IntVar() self.duplicate.set(0) Checkbutton(self.mod_frame, text="Use Values of Duplicate Items", variable=self.duplicate) \ .grid(row=0, column=2, padx=10) self.text_area = Text(self.window) self.text_area.grid(row=1, padx=3, pady=3) self.buttons = Frame(self.window) self.buttons.grid(row=3, sticky="w") Button(self.buttons, text="OK", height=1, width=10, command=self.__add_items) \ .grid(padx=10, pady=10) self.window.wait_window() def __add_items(self): string_data = self.text_area.get(1.0, END).strip() if string_data == "": messagebox.showerror(title="Error", message="Empty Data", parent=self.window) else: if self.__check_xml(string_data) == 1: messagebox.showerror(title="Parsing Error", message="Beginning of type is wrong. type has to start " "with <type", parent=self.window) elif self.__check_xml(string_data) == 2: messagebox.showerror(title="Parsing Error", message="Beginning of type is wrong. types has to start " "with <types", parent=self.window) else: if string_data.startswith("<type n"): string_data = "<types>\n " + string_data + "\n</types>" xml_parser = XMLParser(string_data) items = xml_parser.get_items() for i in items: i.mod = self.modSelector.get() self.database.create_item(item=i, duplicate=self.duplicate.get()) self.window.destroy() def __check_xml(self, text): if text.startswith("<type"): if text.endswith("</type>"): return 0 else: return 2 elif text.startswith("<types>"): if text.endswith("</types>"): return 0 else: return 2 else: return 1
class GUI(object): def __init__(self, main_container: Tk): # self.config = ConfigManager('config.xml') self.ini_manger = INIManager("app.ini") self.database = DAO( self.ini_manger.read_ini("Database", "Database_Name")) # self.window = main_container self.window.wm_title("Loot Editor v0.98.6") self.window.grid_rowconfigure(0, weight=1) self.window.grid_columnconfigure(1, weight=1) self.menu_bar = Menu(self.window) # self.__create_menu_bar() self.__create_entry_frame() self.__create_tree_view() self.__create_side_bar() self.__populate_items() # self.tree.bind("<ButtonRelease-1>", self.__fill_entry_frame) def __create_menu_bar(self): # file menus builder file_menu = Menu(self.menu_bar, tearoff=0) file_menu.add_command(label="Setup Database", command=self.__open_db_window) file_menu.add_separator() file_menu.add_command(label="Add Items", command=self.__open_items_window) file_menu.add_command(label="Export XML File", command=self.__export_xml) file_menu.add_separator() file_menu.add_command(label="Exit", command=self.window.destroy) # database menus builder # mod menus builder mods_menu = Menu(self.menu_bar, tearoff=0) mods_menu.add_command(label="Deselect All") mods_menu.add_command(label="Select All") mods_menu.add_separator() for mod in self.config.get_mods(): int_var = IntVar() mods_menu.add_checkbutton(label=mod, variable=int_var) int_var.set(1) # help menus builder help_menu = Menu(self.menu_bar, tearoff=0) help_menu.add_command(label="visit the loot editor github for ") # building menu bar self.menu_bar.add_cascade(label="File", menu=file_menu) self.menu_bar.add_cascade(label="Mods In Use", menu=mods_menu) self.menu_bar.add_cascade(label="Help", menu=help_menu) # configuring menu bar self.window.config(menu=self.menu_bar) def __create_entry_frame(self): self.entryFrameHolder = Frame(self.window) self.entryFrameHolder.grid(row=0, column=0, sticky="nw") self.entryFrame = Frame(self.entryFrameHolder) self.entryFrame.grid(padx=8, pady=6) # labels Label(self.entryFrame, text="Name").grid(row=0, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Nominal").grid(row=1, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Min").grid(row=2, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Restock").grid(row=3, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Lifetime").grid(row=4, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Usages").grid(row=5, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Tiers").grid(row=6, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Type").grid(row=7, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Sub Type").grid(row=8, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Rarity").grid(row=9, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Mod").grid(row=10, column=0, sticky="w", pady=5) Label(self.entryFrame, text="Trader").grid(row=11, column=0, sticky="w", pady=5) # input variables self.id = IntVar() self.name = StringVar() self.nominal = StringVar() self.min = StringVar() self.restock = StringVar() self.lifetime = StringVar() self.usages = StringVar() self.tires = StringVar() self.type = StringVar() self.sub_type = StringVar() self.rarity = StringVar() self.mod = StringVar() self.trader = StringVar() self.dynamic_event = IntVar() self.count_in_cargo = IntVar() self.count_in_hoarder = IntVar() self.count_in_map = IntVar() self.count_in_player = IntVar() # form fields self.nameField = Entry(self.entryFrame, textvariable=self.name) self.nameField.grid(row=0, column=1, sticky="w") self.nominalField = Entry(self.entryFrame, textvariable=self.nominal) self.nominalField.grid(row=1, column=1, sticky="w") self.minField = Entry(self.entryFrame, textvariable=self.min) self.minField.grid(row=2, column=1, sticky="w") self.restockField = Entry(self.entryFrame, textvariable=self.restock) self.restockField.grid(row=3, column=1, sticky="w") self.lifetimeField = Entry(self.entryFrame, textvariable=self.lifetime) self.lifetimeField.grid(row=4, column=1, sticky="w") self.usagesListBox = Listbox( self.entryFrame, height=4, selectmode="multiple", exportselection=False, ) self.usagesListBox.grid(row=5, column=1, pady=5, sticky="w") usages = self.config.get_usages() for i in usages: self.usagesListBox.insert(END, i) self.tiersListBox = Listbox( self.entryFrame, height=4, selectmode="multiple", exportselection=False, ) self.tiersListBox.grid(row=6, column=1, pady=5, sticky="w") tires = self.config.get_tires() for i in tires: self.tiersListBox.insert(END, i) self.typeOption = OptionMenu(self.entryFrame, self.type, *self.config.get_types()[1:]) self.typeOption.grid(row=7, column=1, sticky="w", pady=5) self.subtypeAutoComp = ComboBoxManager(self.entryFrame, self.config.get_sub_types(), highlightthickness=1) self.subtypeAutoComp.grid(row=8, column=1, sticky="w", pady=5) self.rarityOption = OptionMenu(self.entryFrame, self.rarity, *self.config.get_rarities()) self.rarityOption.grid(row=9, column=1, sticky="w", pady=5) self.modField = Entry(self.entryFrame, textvariable=self.mod) self.modField.grid(row=10, column=1, sticky="w", pady=5) self.traderField = Entry(self.entryFrame, textvariable=self.trader) self.traderField.grid(row=11, column=1, sticky="w") # check boxes frame self.checkBoxFrame = Frame(self.entryFrameHolder) self.checkBoxFrame.grid(row=1, column=0, columnspan=2, sticky="w") self.dynamic_event_check = Checkbutton(self.checkBoxFrame, text="Dynamic Event", variable=self.dynamic_event) self.dynamic_event_check.grid(row=0, column=0, sticky="w") self.count_in_cargo_check = Checkbutton(self.checkBoxFrame, text="Count in Cargo", variable=self.count_in_cargo) self.count_in_cargo_check.grid(row=1, column=0, sticky="w") self.count_in_hoarder_check = Checkbutton( self.checkBoxFrame, text="Count in Hoarder", variable=self.count_in_hoarder) self.count_in_hoarder_check.grid(row=2, column=0, sticky="w") self.count_in_map_check = Checkbutton(self.checkBoxFrame, text="Count in Map", variable=self.count_in_map) self.count_in_map_check.grid(row=3, column=0, sticky="w") self.count_in_player_check = Checkbutton(self.checkBoxFrame, text="Count in Player", variable=self.count_in_player) self.count_in_player_check.grid(row=4, column=0, sticky="w") Button(self.checkBoxFrame, text="Update", width=8, command=self.__update_item). \ grid(row=5, column=0, pady=5, sticky="w") Button(self.checkBoxFrame, text="Delete", width=8, command=self.__delete_item). \ grid(row=5, column=1, pady=5, sticky="w") def __create_tree_view(self): self.treeFrame = Frame(self.window) self.treeFrame.grid(row=0, column=1, sticky="nsew") self.treeFrame.grid_rowconfigure(0, weight=1) self.treeFrame.grid_columnconfigure(0, weight=1) self.column_info = self.config.get_tree_heading() self.tree = ttk.Treeview(self.treeFrame, columns=self.column_info[0], height=40) for col in self.column_info[1]: self.tree.heading( col[2], text=col[0], command=lambda _col=col[0]: self.tree_view_sort_column( self.tree, _col, False), ) self.tree.column(col[2], width=col[1], stretch=0) self.tree.grid(row=0, column=0, sticky="nsew") self.treeView = self.tree vertical = ttk.Scrollbar(self.treeFrame, orient=VERTICAL) horizontal = ttk.Scrollbar(self.treeFrame, orient=HORIZONTAL) vertical.grid(row=0, column=1, sticky="ns") horizontal.grid(row=1, column=0, sticky="we") self.tree.config(yscrollcommand=vertical.set) self.tree.config(xscrollcommand=horizontal.set) vertical.config(command=self.tree.yview) horizontal.config(command=self.tree.xview) def __create_side_bar(self): self.filterFrameHolder = Frame(self.window) self.filterFrameHolder.grid(row=0, column=2, sticky="n") self.filterFrame = LabelFrame(self.filterFrameHolder, text="Filter") self.filterFrame.grid(row=1, column=0, pady=5) Label(self.filterFrame, text="Type").grid(row=1, column=0, sticky="w") Label(self.filterFrame, text="Subtype").grid(row=2, column=0, sticky="w") self.type_for_filter = StringVar() self.type_for_filter.set("all") OptionMenu(self.filterFrame, self.type_for_filter, *self.config.get_types()). \ grid(row=1, column=1, sticky="w", padx=5) self.sub_type_combo_for_filter = ComboBoxManager( self.filterFrame, self.config.get_sub_types(), highlightthickness=1, width=15) self.sub_type_combo_for_filter.grid(row=2, column=1, sticky="w", pady=5, padx=5) Button(self.filterFrame, text="Filter", width=12, command=self.__filter_items).grid(columnspan=2, pady=5, padx=10, sticky='nesw') self.buttons_frame = Frame(self.filterFrame) self.buttons_frame.grid(row=4, columnspan=2) # Button(self.buttons, text="view linked items", width=12).grid(row=3) Button(self.buttons_frame, text="Search by Name", width=12, command=self.__search_by_name).grid(row=4) def __update_item(self): updated_item = Item() updated_item.id = self.id.get() updated_item.name = self.name.get() updated_item.nominal = self.nominal.get() updated_item.min = self.min.get() updated_item.lifetime = self.lifetime.get() updated_item.restock = self.restock.get() usages = self.usagesListBox.curselection() values = [self.usagesListBox.get(i) for i in usages] usages = ",".join(values) updated_item.usage = usages tires = self.tiersListBox.curselection() tire_values = [self.tiersListBox.get(i) for i in tires] tires = ",".join(tire_values) updated_item.tire = tires updated_item.rarity = self.rarity.get() updated_item.item_type = self.type.get() updated_item.sub_type = self.subtypeAutoComp.get() updated_item.mod = self.mod.get() print(updated_item.mod) updated_item.trader = self.trader.get() updated_item.dynamic_event = self.dynamic_event.get() updated_item.count_in_hoarder = self.count_in_hoarder.get() updated_item.count_in_cargo = self.count_in_cargo.get() updated_item.count_in_map = self.count_in_map.get() updated_item.count_in_player = self.count_in_player.get() self.database.update_item(updated_item) self.__populate_items() def __delete_item(self): self.database.delete_item(self.id.get()) self.__populate_items() def __populate_items(self, items=None): if items is None: items = self.database.all_items() if self.tree.get_children() != (): self.tree.delete(*self.tree.get_children()) for i in items: self.tree.insert("", "end", text=i[0], value=i[1:13]) def __search_by_name(self): if self.name.get() != "": self.__populate_items(self.database.search_by_name( self.name.get())) def __filter_items(self): item_type = self.type_for_filter.get() if item_type == "all": self.__populate_items(self.database.all_items()) else: if self.sub_type_combo_for_filter.get() != "": sub_type = self.sub_type_combo_for_filter.get() else: sub_type = None self.__populate_items( self.database.search_by_name(item_type, sub_type)) def __fill_entry_frame(self, event): tree_row = self.tree.item(self.tree.focus()) id = tree_row['text'] item = self.database.get_item(id) self.id.set(id) self.name.set(item.name) self.nominal.set(item.nominal) self.min.set(item.min) self.lifetime.set(item.lifetime) self.restock.set(item.restock) self.mod.set(item.mod) self.trader.set(item.trader) usages = self.config.get_usages() _usages = str(item.usage).split(',') for i in range(len(usages)): self.usagesListBox.select_clear(i) for i in range(len(usages)): for j in _usages: if usages[i] == j: self.usagesListBox.select_set(i) tires = self.config.get_tires() _tires = str(item.tire).split(',') for i in range(len(tires)): self.tiersListBox.select_clear(i) for i in range(len(tires)): for j in _tires: if tires[i] == j: self.tiersListBox.select_set(i) self.rarity.set(item.rarity) self.type.set(item.item_type) self.subtypeAutoComp.set_value(item.sub_type) self.dynamic_event.set(item.dynamic_event) self.count_in_hoarder.set(item.count_in_hoarder) self.count_in_cargo.set(item.count_in_cargo) self.count_in_map.set(item.count_in_map) self.count_in_player.set(item.count_in_player) def __open_db_window(self): DB(self.window) def __open_items_window(self): NewItems(self.window) self.__populate_items() def __export_xml(self): file = filedialog.asksaveasfile(mode="a", defaultextension=".xml") xml_writer = XMLWriter(filename=file.name) items = self.database.get_items() xml_writer.export_xml(items) def tree_view_sort_column(self, tv, col, reverse): l = [(tv.set(k, col), k) for k in tv.get_children('')] l.sort(reverse=reverse) # rearrange items in sorted positions for index, (val, k) in enumerate(l): tv.move(k, '', index) # reverse sort next time tv.heading(col, command=lambda _col=col: self.tree_view_sort_column( tv, _col, not reverse))