--- /dev/null
+import wx, os
+from . import filer, tools, wxcustom, datas
+
+###########
+# opet.py #
+###########
+
+# This file contains:
+# 1. The OPET class, which is the main application object
+# 2. The PrimeFrame class, which represents the dominant OPET frame and is managed by OPET
+
+##########################
+# Section 1 - OPET class #
+##########################
+
+class OPET(object):
+ """
+ OPET is the main application object. It
+ manages the other constituent objects
+ and controls the application's entire
+ operation.
+ """
+ def __init__(self):
+
+ # Various tools
+ self.filer = filer.Filer(self, "environment.json")
+ self.environment = self.filer.get_environment()
+ self.esp_tool = tools.DataPackTool(self)
+
+ # Data
+ rel = self.filer.read_raw_file(os.path.join(os.path.expanduser(self.environment["OblivionPrefixAppdata"]), "Plugins.txt"))
+ enabled_list = []
+ for l in rel:
+ if l[0] not in ['#', '\n']:
+ if l[len(l) - 1] == '\n':
+ l = l[0:len(l) - 1]
+ enabled_list.append(l)
+ self.esp_data = datas.OrderList(self, self.esp_tool.get_load_order_list(os.path.expanduser(self.environment["OblivionDataPath"])), enabled_list)
+
+ # Load up app and frame components
+ self.app = wx.App()
+ self.app_frame = OPETFrame(self, None, title = "OPET", size = (1200, 800))
+ self.app_frame.Show()
+ self.app.MainLoop()
+
+################################
+# Section 2 - PrimeFrame class #
+################################
+
+class OPETFrame(wx.Frame):
+ """
+ The wxWidget frame representing the
+ application's main window.
+ """
+
+ def __init__(self, manager, *args, **kwargs):
+
+ # Parent initialization
+ super(OPETFrame, self).__init__(*args, **kwargs)
+
+ # Important vals
+ self.manager = manager
+
+ # Frame geometry
+ self.main_panel = wx.Panel(self)
+ self.main_sizer = wx.BoxSizer(wx.VERTICAL)
+ self.main_panel.SetSizer(self.main_sizer)
+
+ # Construct menu bar
+ # .. File menu
+ self.file_menu = wx.Menu()
+ self.new_profile_item = self.file_menu.Append(-1, "&New Profile...\tCtrl-N", "Create a new empty mod list profile")
+ self.Bind(wx.EVT_MENU, self.on_new_profile, self.new_profile_item)
+ self.open_profile_item = self.file_menu.Append(-1, "&Open Profile...\tCtrl-O", "Open an existing mod list profile")
+ self.Bind(wx.EVT_MENU, self.on_open_profile, self.open_profile_item)
+ self.close_profile_item = self.file_menu.Append(-1, "Close Profile...\tCtrl-Q", "Close current mod list profile")
+ self.Bind(wx.EVT_MENU, self.on_close_profile, self.close_profile_item)
+ self.file_menu.AppendSeparator()
+ self.save_profile_item = self.file_menu.Append(-1, "&Save Profile...\tCtrl-S", "Save current mod list")
+ self.Bind(wx.EVT_MENU, self.on_save_profile, self.save_profile_item)
+ self.save_profile_as_item = self.file_menu.Append(-1, "&Save Profile As...\tCtrl-Shift-S", "Save current mod list as...")
+ self.Bind(wx.EVT_MENU, self.on_save_profile_as, self.save_profile_as_item)
+ self.file_menu.AppendSeparator()
+ self.exit_item = self.file_menu.Append(wx.ID_EXIT)
+ self.Bind(wx.EVT_MENU, self.on_exit, self.exit_item)
+ # .. Edit menu
+ self.edit_menu = wx.Menu()
+ # .. Tools menu
+ self.tools_menu = wx.Menu()
+ # .. Help menu
+ self.help_menu = wx.Menu()
+ self.about_item = self.help_menu.Append(wx.ID_ABOUT)
+ self.Bind(wx.EVT_MENU, self.on_about, self.about_item)
+ # Menu bar itself
+ self.menu_bar = wx.MenuBar()
+ self.menu_bar.Append(self.file_menu, "&File")
+ self.menu_bar.Append(self.edit_menu, "&Edit")
+ self.menu_bar.Append(self.tools_menu, "&Tools")
+ self.menu_bar.Append(self.help_menu, "&Help")
+ self.SetMenuBar(self.menu_bar)
+
+ # Construct sub-panel
+ self.sub_panel = wx.Panel(self.main_panel)
+ self.sub_panel_sizer = wx.BoxSizer(wx.VERTICAL)
+ self.sub_panel.SetSizer(self.sub_panel_sizer)
+ self.sub_panel.SetSize(4, 4, 1200, 800)
+
+ # Construct esp list
+ self.esp_list_panel = wx.Panel(self.sub_panel)
+ self.esp_list_sizer = wx.BoxSizer(wx.VERTICAL)
+ self.esp_list_panel.SetSizer(self.esp_list_sizer)
+ self.esp_list_ctrl = wxcustom.ESPListCtrl(self.esp_list_panel, size = (800, 500))
+ self.esp_list_ctrl.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
+ self.esp_list_ctrl.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndLabelEdit)
+ self.update_esp_list(self.manager.esp_data.get_data())
+ self.esp_buttons_panel = wx.Panel(self.sub_panel)
+ self.esp_buttons_panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.esp_buttons_panel.SetSizer(self.esp_buttons_panel_sizer)
+ self.esp_apply_button = wxcustom.ESPApplyButton(self.esp_buttons_panel)
+ self.esp_apply_button.Bind(wx.EVT_BUTTON, self.OnApplyChanges)
+ self.esp_list_panel.SetSize(8, 8, 800, 1100)
+ self.esp_buttons_panel.SetSize(8, 600, 800, 100)
+
+ def update_esp_list(self, data):
+ self.esp_list_ctrl.DeleteAllItems()
+ for e in data:
+ entry = ["", e["order"], e["name"], e["comments"]]
+ self.esp_list_ctrl.Append(entry)
+ if e["enabled"]:
+ self.esp_list_ctrl.CheckItem(int(e["order"]), True)
+ self.manager.esp_data.set_data(data)
+
+ def sort_esp_data_by_order(self, data):
+ # TODO: This is terrible and inefficient
+ simsor = sorted(data, key=lambda k: k["order"])
+ j = None
+ for i in simsor:
+ if i["just_changed"]:
+ if j["order"] == i["order"]:
+ j["order"] += 1
+ elif j != None and j["just_changed"]:
+ if i["order"] == j["order"]:
+ i["order"] -= 1
+ j = i
+ simsor = sorted(data, key=lambda k: k["order"])
+ oldor = -1
+ for i in simsor:
+ if i["order"] != oldor + 1:
+ i["order"] = oldor + 1
+ oldor = i["order"]
+ return simsor
+
+ # TODO: Cross-object binding issues indicate larger program construction problems???
+ def OnApplyChanges(self, event):
+ data = []
+ for row in range(self.esp_list_ctrl.GetItemCount()):
+ n = self.esp_list_ctrl.GetItem(row, col = 2).GetText()
+ o = int(self.esp_list_ctrl.GetItem(row, col = 1).GetText())
+ e = self.esp_list_ctrl.IsItemChecked(row)
+ c = self.esp_list_ctrl.GetItem(row, col = 3).GetText()
+ dd = { "name" : n, "order" : o, "enabled" : e, "comments" : c, "just_changed" : False }
+ data.append(dd)
+ self.update_esp_list(self.sort_esp_data_by_order(data))
+ self.manager.esp_tool.assign_load_order(self.manager.esp_data.get_data(), self.manager.environment)
+ self.manager.esp_tool.enable_esps(self.manager.esp_data.get_data(), self.manager.environment)
+ def OnBeginLabelEdit(self, event):
+ col = event.GetColumn()
+ fi = self.esp_list_ctrl.GetFocusedItem()
+ if col == 0:
+ event.Veto()
+ if fi != -1:
+ self.esp_list_ctrl.CheckItem(fi, not self.esp_list_ctrl.IsItemChecked(fi))
+ elif col == 1:
+ if fi != -1:
+ self.esp_list_ctrl.last_order_value = int(self.esp_list_ctrl.GetItem(fi, 1).GetText())
+ event.Skip()
+ elif col == 2:
+ event.Veto()
+ else:
+ event.Skip()
+ def OnEndLabelEdit(self, event):
+ if event.GetColumn() == 1:
+ try:
+ lbint = int(event.GetLabel())
+ except ValueError:
+ lbint = int(self.esp_list_ctrl.GetItem(event.GetItem(), event.GetColumn()))
+ if lbint < 0:
+ lbint = 0
+ if self.esp_list_ctrl.last_order_value != None and lbint != self.esp_list_ctrl.last_order_value:
+ self.esp_list_ctrl.SetItem(event.GetIndex(), event.GetColumn(), str(lbint))
+ # TODO: This is a bit fragile and relies on file names...
+ entry = self.esp_list_ctrl.GetItem(event.GetIndex(), col = 2).GetText()
+ data = []
+ for row in range(self.esp_list_ctrl.GetItemCount()):
+ n = self.esp_list_ctrl.GetItem(row, col = 2).GetText()
+ o = int(self.esp_list_ctrl.GetItem(row, col = 1).GetText())
+ e = self.esp_list_ctrl.IsItemChecked(row)
+ c = self.esp_list_ctrl.GetItem(row, col = 3).GetText()
+ j = True if n == entry else False
+ dd = { "name" : n, "order" : o, "enabled" : e, "comments" : c, "just_changed" : j }
+ data.append(dd)
+ self.update_esp_list(self.sort_esp_data_by_order(data))
+ for i in self.manager.esp_data.get_data():
+ if i["just_changed"]:
+ #self.esp_list_ctrl.EnsureVisible(int(i["order"]))
+ self.esp_list_ctrl.Focus(int(i["order"]))
+ break
+ event.Veto()
+
+ def on_new_profile(self, event):
+ pass
+ def on_open_profile(self, event):
+ pass
+ def on_close_profile(self, event):
+ pass
+ def on_save_profile(self, event):
+ pass
+ def on_save_profile_as(self, event):
+ pass
+ def on_exit(self, event):
+ self.Close(True)
+ def on_about(self, event):
+ wx.MessageBox("Test", "Test test", wx.OK|wx.ICON_INFORMATION)
--- /dev/null
+import wx
+from wx.lib.mixins import listctrl
+
+###############
+# wxcustom.py #
+###############
+
+# This file contains:
+# 1. Various custom classes derived from wx elements
+
+#################################
+# Section 1 - Custom wx classes #
+#################################
+
+class ESPListCtrl(wx.ListCtrl, listctrl.TextEditMixin, listctrl.ListCtrlAutoWidthMixin):
+ """
+ ListCtrl object that is used to edit
+ the list of esp files that should be
+ enabled and also their load order.
+ """
+
+ def __init__(self, parent, size = (400, 300)):
+
+ # Parent initialization
+ wx.ListCtrl.__init__(self, parent, size = size, style = wx.LC_REPORT)
+ listctrl.TextEditMixin.__init__(self)
+ listctrl.ListCtrlAutoWidthMixin.__init__(self)
+
+ # Set values
+ self.setResizeColumn(3)
+ self.EnableCheckBoxes(True)
+
+ # Dynamics
+ # TODO: Maybe this should be in the parent object instead???
+ # Depends on how to solve the problem of where to bind...
+ self.last_order_value = None
+
+ # Columns
+ self.InsertColumn(0, "Enabled")
+ self.InsertColumn(1, "Order")
+ self.InsertColumn(2, "File")
+ self.InsertColumn(3, "Comment")
+
+class ESPApplyButton(wx.Button):
+ """
+ The ESPApplyButton is used to apply
+ any changes made to the esp list
+ to the actual file system.
+ """
+
+ def __init__(self, parent, label = "Apply"):
+
+ # Parent initialization
+ wx.Button.__init__(self, parent, label = label)