import misc import namearray import util import wx # NameArray, or None if not loaded nameArr = None # if not already loaded, read the name database from disk and store it. # returns False on errors. def readNames(frame): global nameArr if nameArr: # already loaded return True try: data = util.loadMaybeCompressedFile(u"names.txt", frame) if not data: return False res = namearray.NameArray() nameType = None for line in data.splitlines(): ch = line[0] if ch == "#": continue elif ch == "N": nameType = line[1:] elif ch in ("M", "F"): if not nameType: raise Exception("No name type set before line: '%s'" % line) res.append(line[1:], nameType, ch) else: raise Exception("Unknown linetype for line: '%s'" % line) nameArr = res return True except Exception, e: wx.MessageBox("Error loading name database: %s" % str(e), "Error", wx.OK, frame) return False class NamesDlg(wx.Dialog): def __init__(self, parent, ctrl): wx.Dialog.__init__(self, parent, -1, "Character name database", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) self.ctrl = ctrl hsizer = wx.BoxSizer(wx.HORIZONTAL) vsizer = wx.BoxSizer(wx.VERTICAL) vsizer.Add(wx.StaticText(self, -1, "Search in:")) self.typeList = wx.ListCtrl(self, -1, style = wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES) self.typeList.InsertColumn(0, "Count") self.typeList.InsertColumn(1, "Type") for i in range(len(nameArr.typeNamesById)): typeName = nameArr.typeNamesById[i] self.typeList.InsertStringItem(i, str(nameArr.typeNamesCnt[typeName])) self.typeList.SetStringItem(i, 1, typeName) self.typeList.SetItemData(i, i) self.typeList.SetColumnWidth(0, wx.LIST_AUTOSIZE) self.typeList.SetColumnWidth(1, wx.LIST_AUTOSIZE) w = 0 w += self.typeList.GetColumnWidth(0) w += self.typeList.GetColumnWidth(1) util.setWH(self.typeList, w + 15, 425) self.typeList.SortItems(self.CmpFreq) self.selectAllTypes() vsizer.Add(self.typeList, 1, wx.EXPAND | wx.BOTTOM, 5) selectAllBtn = wx.Button(self, -1, "Select all") vsizer.Add(selectAllBtn) hsizer.Add(vsizer, 0, wx.EXPAND) vsizer = wx.BoxSizer(wx.VERTICAL) hsizer2 = wx.BoxSizer(wx.HORIZONTAL) vsizer2 = wx.BoxSizer(wx.VERTICAL) searchBtn = wx.Button(self, -1, "Search") wx.EVT_BUTTON(self, searchBtn.GetId(), self.OnSearch) vsizer2.Add(searchBtn, 0, wx.BOTTOM | wx.TOP, 10) self.searchEntry = wx.TextCtrl(self, -1, style = wx.TE_PROCESS_ENTER) vsizer2.Add(self.searchEntry, 0, wx.EXPAND) tmp = wx.Button(self, -1, "Insert") wx.EVT_BUTTON(self, tmp.GetId(), self.OnInsertName) vsizer2.Add(tmp, 0, wx.BOTTOM | wx.TOP, 10) hsizer2.Add(vsizer2, 1, wx.RIGHT, 10) self.nameRb = wx.RadioBox(self, -1, "Name", style = wx.RA_SPECIFY_COLS, majorDimension = 1, choices = [ "begins with", "contains", "ends in" ]) hsizer2.Add(self.nameRb) self.sexRb = wx.RadioBox(self, -1, "Sex", style = wx.RA_SPECIFY_COLS, majorDimension = 1, choices = [ "Male", "Female", "Both" ]) self.sexRb.SetSelection(2) hsizer2.Add(self.sexRb, 0, wx.LEFT, 5) vsizer.Add(hsizer2, 0, wx.EXPAND | wx.ALIGN_CENTER) vsizer.Add(wx.StaticText(self, -1, "Results:")) self.list = MyListCtrl(self) vsizer.Add(self.list, 1, wx.EXPAND | wx.BOTTOM, 5) self.foundLabel = wx.StaticText(self, -1, "", style = wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE) vsizer.Add(self.foundLabel, 0, wx.EXPAND) hsizer.Add(vsizer, 20, wx.EXPAND | wx.LEFT, 10) wx.EVT_TEXT_ENTER(self, self.searchEntry.GetId(), self.OnSearch) wx.EVT_BUTTON(self, selectAllBtn.GetId(), self.selectAllTypes) wx.EVT_LIST_COL_CLICK(self, self.typeList.GetId(), self.OnHeaderClick) util.finishWindow(self, hsizer) self.OnSearch() self.searchEntry.SetFocus() def selectAllTypes(self, event = None): for i in range(len(nameArr.typeNamesById)): self.typeList.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) def OnHeaderClick(self, event): if event.GetColumn() == 0: self.typeList.SortItems(self.CmpFreq) else: self.typeList.SortItems(self.CmpType) def CmpFreq(self, i1, i2): return nameArr.typeNamesCnt[nameArr.typeNamesById[i2]] - nameArr.typeNamesCnt[nameArr.typeNamesById[i1]] def CmpType(self, i1, i2): return cmp(nameArr.typeNamesById[i1], nameArr.typeNamesById[i2]) def OnInsertName(self, event): item = self.list.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) if item == -1: return # this seems to return column 0's text, which is lucky, because I # don't see a way of getting other columns' texts... name = self.list.GetItemText(item) for ch in name: self.ctrl.OnKeyChar(util.MyKeyEvent(ord(ch))) def OnSearch(self, event = None): l = [] wx.BeginBusyCursor() s = util.lower(misc.fromGUI(self.searchEntry.GetValue())) sex = self.sexRb.GetSelection() nt = self.nameRb.GetSelection() selTypes = {} item = -1 while 1: item = self.typeList.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) if item == -1: break selTypes[self.typeList.GetItemData(item)] = True if len(selTypes) == len(nameArr.typeNamesCnt): doTypes = False else: doTypes = True for i in xrange(nameArr.count): if (sex != 2) and (sex == nameArr.sex[i]): continue if doTypes and nameArr.type[i] not in selTypes: continue if s: name = util.lower(nameArr.name[i]) if nt == 0: if not name.startswith(s): continue elif nt == 1: if name.find(s) == -1: continue elif nt == 2: if not name.endswith(s): continue l.append(i) self.list.items = l self.list.SetItemCount(len(l)) self.list.EnsureVisible(0) wx.EndBusyCursor() self.foundLabel.SetLabel("%d names found." % len(l)) class MyListCtrl(wx.ListCtrl): def __init__(self, parent): wx.ListCtrl.__init__(self, parent, -1, style = wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_SINGLE_SEL | wx.LC_HRULES | wx.LC_VRULES) self.sex = ["Female", "Male"] self.InsertColumn(0, "Name") self.InsertColumn(1, "Type") self.InsertColumn(2, "Sex") self.SetColumnWidth(0, 120) self.SetColumnWidth(1, 120) # we can't use wx.LIST_AUTOSIZE since this is a virtual control, # so calculate the size ourselves since we know the longest string # possible. w = util.getTextExtent(self.GetFont(), "Female")[0] + 15 self.SetColumnWidth(2, w) util.setWH(self, w = 120*2 + w + 25) def OnGetItemText(self, item, col): n = self.items[item] if col == 0: return nameArr.name[n] elif col == 1: return nameArr.typeNamesById[nameArr.type[n]] elif col == 2: return self.sex[nameArr.sex[n]] # shouldn't happen return "" # for some reason this must be overridden as well, otherwise we get # assert failures under windows. def OnGetItemImage(self, item): return -1