#!/usr/bin/env python # -*- coding: utf-8 -*- # # seven_mods_gui.py # # Copyright 2023 Patrick Marsee # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # from tkinter import * from tkinter import ttk from tkinter import messagebox from tkinter import filedialog import seven_mods import os.path import xml.etree.ElementTree as et # I don't need anything powerful for this class AppFrame(ttk.Frame): def __init__(self, root): super(AppFrame, self).__init__(root) self.grid(column = 0, row = 0) self.cfg = None try: self.cfg = seven_mods.load_config() except: # no config or invalid config print("Should be making a new window") self.prompt_configuration_window() self.profiles = seven_mods.ModProfiles() self.profiles.load_mod_profiles() self.initialize_widgets() self.refresh_mod_list() def initialize_widgets(self): self.columnconfigure(1, weight = 1) self.configure_button = ttk.Button(self, text = "Configure", command = self.prompt_configuration_window) self.configure_button.grid(column = 0, row = 0) self.profile_var = StringVar() self.profile_box = ttk.Combobox(self, textvariable = self.profile_var) self.refresh_profile_list() self.profile_box.grid(column = 1, row = 0, sticky = (E, W)) self.profile_load_btn = ttk.Button(self, text = "Load", command = self.command_load_button) self.profile_load_btn.grid(column = 2, row = 0) self.profile_save_btn = ttk.Button(self, text = "Save", command = self.command_save_button) self.profile_save_btn.grid(column = 3, row = 0) self.mod_list = ttk.Treeview(self, columns = ("name", "version", "author", "enabled"), height = 20, selectmode = "browse") self.mod_list.heading("name", text = "Name") self.mod_list.heading("version", text = "Version") self.mod_list.heading("author", text = "Author") self.mod_list.heading("enabled", text = "Enabled") self.mod_list.tag_configure("DISABLED", foreground = "red") self.mod_list.tag_configure("ENABLED", foreground = "green") self.mod_list.tag_bind("DISABLED", '<>', lambda e: self.command_enable(self.mod_list.selection()[0])) self.mod_list.tag_bind("ENABLED", '<>', lambda e: self.command_disable(self.mod_list.selection()[0])) self.mod_list.grid(column = 0, row = 1, columnspan = 4, sticky = (N, E, S, W)) def prompt_configuration_window(self): SEVEN_DIR = "" MODS_DIR = "" if self.cfg == None: SEVEN_DIR = seven_mods.get_seven_days_install_path() MODS_DIR = seven_mods.MODS_DIR else: SEVEN_DIR = self.cfg.seven_dir MODS_DIR = self.cfg.mods_dir t = Toplevel(self) t.title("Configuration") t.columnconfigure(1, weight = 1) t.geometry("800x90") ttk.Label(t, text = "Mod folder").grid(column = 0, row = 0) mod_path_var = StringVar() mod_path_var.set(MODS_DIR) mod_path_entry = ttk.Entry(t, textvariable = mod_path_var) mod_path_entry.grid(column = 1, row = 0, sticky = (E, W)) mod_path_button = ttk.Button(t, text = "Browse...", command = lambda: mod_path_var.set(filedialog.askdirectory(initialdir = MODS_DIR))) mod_path_button.grid(column = 2, row = 0, sticky = (E, W)) ttk.Label(t, text = "7D2D installation folder").grid(column = 0, row = 1) seven_path_var = StringVar() seven_path_var.set(SEVEN_DIR) seven_path_entry = ttk.Entry(t, textvariable = seven_path_var) seven_path_entry.grid(column = 1, row = 1, sticky = (E, W)) seven_path_button = ttk.Button(t, text = "Browse...", command = lambda: seven_path_var.set(filedialog.askdirectory(initialdir = SEVEN_DIR))) seven_path_button.grid(column = 2, row = 1, sticky = (E, W)) save_button = ttk.Button(t, text = "Save", command = lambda: self.save_config(mod_path_var.get(), seven_path_var.get())) save_button.grid(column = 2, row = 2) def save_config(self, mods_dir: str, seven_dir: str): self.cfg = seven_mods.Config(mods_dir = mods_dir, seven_dir = seven_dir) seven_mods.save_config(self.cfg) self.refresh_mod_list() def get_mod_data(self, mod: str) -> tuple: mod_info_path = os.path.join(self.cfg.mods_dir, mod, "ModInfo.xml") try: tree = et.parse(mod_info_path) except: return "", "", "" root = tree.getroot() name = "" author = "" version = "" for node in root[0]: if node.tag == "Name": name = node.attrib["value"] elif node.tag == "Author": author = node.attrib["value"] elif node.tag == "Version": version = node.attrib["value"] return name, version, author def refresh_mod_list(self): if self.cfg == None: return available_mods = seven_mods.get_available_mods(self.cfg) loaded_mods = seven_mods.get_loaded_mods(self.cfg) # remove the current list items for item in self.mod_list.get_children(""): self.mod_list.delete(item) # add the new ones for mod in available_mods: enabled_text = "DISABLED" if mod in loaded_mods: enabled_text = "ENABLED" values = *self.get_mod_data(mod), enabled_text self.mod_list.insert("", "end", mod, text = mod, values = values, tags = (enabled_text)) def refresh_profile_list(self): prof_list = [p for p in self.profiles.profiles] self.profile_box["values"] = prof_list def command_enable(self, mod): try: seven_mods.enable_mod(self.cfg, mod) self.mod_list.item(mod, tags = ("ENABLED")) self.mod_list.set(mod, "enabled", "ENABLED") except seven_mods.SevenModsError as e: messagebox.showerror(message = str(e)) def command_disable(self, mod): try: seven_mods.disable_mod(self.cfg, mod) self.mod_list.item(mod, tags = ("DISABLED")) self.mod_list.set(mod, "enabled", "DISABLED") except seven_mods.SevenModsError as e: messagebox.showerror(message = str(e)) def command_load_button(self): prof = self.profile_var.get() if prof in self.profiles.profiles: try: seven_mods.command_disable(["", "", "*"], self.cfg, self.profiles) seven_mods.command_enable(["", ""] + self.profiles.profiles[prof], self.cfg, self.profiles) self.refresh_mod_list() except seven_mods.SevenModsError as e: messagebox.showerror(message = str(e)) else: messagebox.showerror(message = "Must load an existing profile.") def command_save_button(self): prof = self.profile_var.get() try: self.profiles.profiles[prof] = seven_mods.get_loaded_mods(cfg) self.profiles.save_mod_profiles() self.refresh_profile_list() except seven_mods.SevenModsError as e: messagebox.showerror(message = str(e)) def main(args): root = Tk() root.title("Seven Mods") root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) AppFrame(root) root.mainloop() return 0 if __name__ == '__main__': import sys sys.exit(main(sys.argv))