Merge branch 'refactor-entityEditor' into charImplants

This commit is contained in:
blitzmann
2016-03-30 00:04:44 -04:00
16 changed files with 596 additions and 854 deletions

View File

@@ -37,6 +37,7 @@ characters_table = Table("characters", saveddata_meta,
mapper(Character, characters_table,
properties = {
"savedName": characters_table.c.name,
"_Character__owner": relation(
User,
backref = "characters"),

View File

@@ -154,7 +154,7 @@ def getCharacter(lookfor, eager=None):
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(Character.name == lookfor).first()
character = saveddata_session.query(Character).options(*eager).filter(Character.savedName == lookfor).first()
else:
raise TypeError("Need integer or string as argument")
return character

View File

@@ -90,7 +90,7 @@ class Character(object):
return all0
def __init__(self, name, defaultLevel=None, initSkills=True):
self.name = name
self.savedName = name
self.__owner = None
self.defaultLevel = defaultLevel
self.__skills = []
@@ -129,6 +129,14 @@ class Character(object):
def owner(self, owner):
self.__owner = owner
@property
def name(self):
return self.savedName if not self.isDirty else "{} *".format(self.savedName)
@name.setter
def name(self, name):
self.savedName = name
@property
def skills(self):
return self.__skills

View File

@@ -0,0 +1,173 @@
import wx
from gui.bitmapLoader import BitmapLoader
import service
class BaseValidator(wx.PyValidator):
def __init__(self):
wx.PyValidator.__init__(self)
def Validate(self, win):
raise NotImplementedError()
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
class TextEntryValidatedDialog(wx.TextEntryDialog):
def __init__(self, parent, validator=None, *args, **kargs):
wx.TextEntryDialog.__init__(self, parent, *args, **kargs)
self.parent = parent
self.txtctrl = self.FindWindowById(3000)
if validator:
self.txtctrl.SetValidator(validator())
class EntityEditor (wx.Panel):
"""
Entity Editor is a panel that takes some sort of list as a source and populates a drop down with options to add/
rename/clone/delete an entity. Comes with dialogs that take user input. Classes that derive this class must override
functions that get the list from the source, what to do when user does an action, and how to validate the input.
"""
def __init__(self, parent, entityName):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
self.entityName = entityName
self.validator = None
self.navSizer = wx.BoxSizer(wx.HORIZONTAL)
self.choices = []
self.choices.sort(key=lambda p: p.name)
self.entityChoices = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
self.navSizer.Add(self.entityChoices, 1, wx.ALL, 5)
buttons = (("new", wx.ART_NEW, self.OnNew),
("rename", BitmapLoader.getBitmap("rename", "gui"), self.OnRename),
("copy", wx.ART_COPY, self.OnCopy),
("delete", wx.ART_DELETE, self.OnDelete))
size = None
for name, art, func in buttons:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
btn.SetToolTipString("{} {}".format(name.capitalize(), self.entityName))
btn.Bind(wx.EVT_BUTTON, func)
setattr(self, "btn%s" % name.capitalize(), btn)
self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
self.SetSizer(self.navSizer)
self.Layout()
self.refreshEntityList()
def SetEditorValidator(self, validator=None):
""" Sets validator class (not an instance of the class) """
self.validator = validator
def getEntitiesFromContext(self):
""" Gets list of entities from current context """
raise NotImplementedError()
def DoNew(self, name):
"""Override method to do new entity logic. Must return the new entity"""
raise NotImplementedError()
def DoCopy(self, entity, name):
"""Override method to copy entity. Must return the copy"""
raise NotImplementedError()
def DoRename(self, entity, name):
"""Override method to rename an entity"""
raise NotImplementedError()
def DoDelete(self, entity):
"""Override method to delete entity"""
raise NotImplementedError()
def OnNew(self, event):
dlg = TextEntryValidatedDialog(self, self.validator,
"Enter a name for your new {}:".format(self.entityName),
"New {}".format(self.entityName))
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_OK:
new = self.DoNew(dlg.GetValue().strip())
self.refreshEntityList(new)
wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
else:
return False
def OnCopy(self, event):
dlg = TextEntryValidatedDialog(self, self.validator,
"Enter a name for your {} copy:".format(self.entityName),
"Copy {}".format(self.entityName))
active = self.getActiveEntity()
dlg.SetValue("{} Copy".format(active.name))
dlg.txtctrl.SetInsertionPointEnd()
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_OK:
copy = self.DoCopy(active, dlg.GetValue().strip())
self.refreshEntityList(copy)
wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
def OnRename(self, event):
dlg = TextEntryValidatedDialog(self, self.validator,
"Enter a new name for your {}:".format(self.entityName),
"Rename {}".format(self.entityName))
active = self.getActiveEntity()
dlg.SetValue(active.name)
dlg.txtctrl.SetInsertionPointEnd()
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_OK:
self.DoRename(active, dlg.GetValue().strip())
self.refreshEntityList(active)
wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
def OnDelete(self, event):
dlg = wx.MessageDialog(self,
"Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_YES:
self.DoDelete(self.getActiveEntity())
self.refreshEntityList()
wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
def refreshEntityList(self, selected=None):
self.choices = self.getEntitiesFromContext()
self.entityChoices.Clear()
self.entityChoices.AppendItems(map(lambda p: p.name, self.choices))
if selected:
idx = self.choices.index(selected)
self.entityChoices.SetSelection(idx)
else:
self.entityChoices.SetSelection(0)
def getActiveEntity(self):
if len(self.choices) == 0:
return None
return self.choices[self.entityChoices.GetSelection()]
def setActiveEntity(self, entity):
self.entityChoices.SetSelection(self.choices.index(entity))
def checkEntitiesExist(self):
if len(self.choices) == 0:
self.Parent.Hide()
if self.OnNew(None) is False:
return False
self.Parent.Show()
return True

View File

@@ -110,7 +110,7 @@ class BaseImplantEditorView (wx.Panel):
""" Adds implant to the current context"""
raise NotImplementedError()
def removeImplantFromContext(self, pos):
def removeImplantFromContext(self, implant):
""" Removes implant from the current context"""
raise NotImplementedError()
@@ -191,7 +191,7 @@ class BaseImplantEditorView (wx.Panel):
def removeItem(self, event):
pos = self.pluggedImplantsTree.GetFirstSelected()
if pos != -1:
self.removeImplantFromContext(pos)
self.removeImplantFromContext(self.implants[pos])
self.update()
class AvailableImplantsView(d.Display):

View File

@@ -26,6 +26,73 @@ import service
from gui.contextMenu import ContextMenu
import gui.globalEvents as GE
from gui.builtinViews.implantEditor import BaseImplantEditorView
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
class CharacterTextValidor(BaseValidator):
def __init__(self):
BaseValidator.__init__(self)
def Clone(self):
return CharacterTextValidor()
def Validate(self, win):
profileEditor = win.Parent
textCtrl = self.GetWindow()
text = textCtrl.GetValue().strip()
try:
if len(text) == 0:
raise ValueError("You must supply a name for the Character!")
elif text in [x.name for x in profileEditor.entityEditor.choices]:
raise ValueError("Character name already in use, please choose another.")
return True
except ValueError, e:
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
class CharacterEntityEditor(EntityEditor):
def __init__(self, parent):
EntityEditor.__init__(self, parent, "Character")
self.SetEditorValidator(CharacterTextValidor)
def getEntitiesFromContext(self):
sChar = service.Character.getInstance()
charList = sorted(sChar.getCharacterList(), key=lambda c: c.name)
# Do some processing to ensure that we have All 0 and All 5 at the top
all5 = sChar.all5()
all0 = sChar.all0()
charList.remove(all5)
charList.remove(all0)
charList.insert(0, all5)
charList.insert(0, all0)
return charList
def DoNew(self, name):
sChar = service.Character.getInstance()
return sChar.new(name)
def DoRename(self, entity, name):
sChar = service.Character.getInstance()
sChar.rename(entity, name)
def DoCopy(self, entity, name):
sChar = service.Character.getInstance()
copy = sChar.copy(entity)
sChar.rename(copy, name)
return copy
def DoDelete(self, entity):
sChar = service.Character.getInstance()
sChar.delete(entity)
class CharacterEditor(wx.Frame):
def __init__(self, parent):
@@ -37,57 +104,16 @@ class CharacterEditor(wx.Frame):
self.mainFrame = parent
#self.disableWin = wx.WindowDisabler(self)
sFit = service.Fit.getInstance()
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.navSizer = wx.BoxSizer(wx.HORIZONTAL)
sChar = service.Character.getInstance()
self.btnSave = wx.Button(self, wx.ID_SAVE)
self.btnSave.Hide()
self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
self.characterRename = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
self.characterRename.Hide()
self.characterRename.Bind(wx.EVT_TEXT_ENTER, self.processRename)
self.charChoice = wx.Choice(self, wx.ID_ANY, style=0)
self.navSizer.Add(self.charChoice, 1, wx.ALL | wx.EXPAND, 5)
charList = sChar.getCharacterList()
for id, name, active in charList:
i = self.charChoice.Append(name, id)
if active:
self.charChoice.SetSelection(i)
self.navSizer.Add(self.btnSave, 0, wx.ALL , 5)
buttons = (("new", wx.ART_NEW),
("rename", BitmapLoader.getBitmap("rename", "gui")),
("copy", wx.ART_COPY),
("delete", wx.ART_DELETE))
size = None
for name, art in buttons:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
btn.SetToolTipString("%s character" % name.capitalize())
btn.Bind(wx.EVT_BUTTON, getattr(self, name))
setattr(self, "btn%s" % name.capitalize(), btn)
self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
mainSizer.Add(self.navSizer, 0, wx.ALL | wx.EXPAND, 5)
self.entityEditor = CharacterEntityEditor(self)
mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
# Default drop down to current fit's character
self.entityEditor.setActiveEntity(sFit.character)
self.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
@@ -114,7 +140,6 @@ class CharacterEditor(wx.Frame):
bSizerButtons.AddStretchSpacer()
bSizerButtons.Add(self.btnOK, 0, wx.ALL, 5)
self.btnSaveChar.Bind(wx.EVT_BUTTON, self.saveChar)
self.btnSaveAs.Bind(wx.EVT_BUTTON, self.saveCharAs)
self.btnRevert.Bind(wx.EVT_BUTTON, self.revertChar)
@@ -129,16 +154,12 @@ class CharacterEditor(wx.Frame):
self.Centre(wx.BOTH)
charID = self.getActiveCharacter()
if sChar.getCharName(charID) in ("All 0", "All 5"):
self.restrict()
self.registerEvents()
self.Bind(wx.EVT_CLOSE, self.closeEvent)
self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
self.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
def btnRestrict(self):
sChar = service.Character.getInstance()
charID = self.getActiveCharacter()
char = sChar.getCharacter(charID)
char = self.entityEditor.getActiveEntity()
# enable/disable character saving stuff
self.btnSaveChar.Enable(not char.ro and char.isDirty)
@@ -146,46 +167,34 @@ class CharacterEditor(wx.Frame):
self.btnRevert.Enable(char.isDirty)
def refreshCharacterList(self, event=None):
sChar = service.Character.getInstance()
charList = sChar.getCharacterList()
active = self.getActiveCharacter()
self.charChoice.Clear()
for id, name, _ in charList:
i = self.charChoice.Append(name, id)
if active == id:
self.charChoice.SetSelection(i)
"""This is only called when we save a modified character"""
active = self.entityEditor.getActiveEntity()
self.entityEditor.refreshEntityList(active)
self.btnRestrict()
if event:
event.Skip()
def editingFinished(self, event):
#del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
def registerEvents(self):
self.Bind(wx.EVT_CLOSE, self.closeEvent)
self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
self.charChoice.Bind(wx.EVT_CHOICE, self.charChanged)
def saveChar(self, event):
sChr = service.Character.getInstance()
charID = self.getActiveCharacter()
sChr.saveCharacter(charID)
self.sview.populateSkillTree()
char = self.entityEditor.getActiveEntity()
sChr.saveCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
def saveCharAs(self, event):
charID = self.getActiveCharacter()
dlg = SaveCharacterAs(self, charID)
char = self.entityEditor.getActiveEntity()
dlg = SaveCharacterAs(self, char.ID)
dlg.ShowModal()
self.sview.populateSkillTree()
def revertChar(self, event):
sChr = service.Character.getInstance()
charID = self.getActiveCharacter()
sChr.revertCharacter(charID)
self.sview.populateSkillTree()
char = self.entityEditor.getActiveEntity()
sChr.revertCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
@@ -194,109 +203,25 @@ class CharacterEditor(wx.Frame):
self.Destroy()
def restrict(self):
self.btnRename.Enable(False)
self.btnDelete.Enable(False)
self.iview.Enable(False)
self.aview.Enable(False)
self.entityEditor.btnRename.Enable(False)
self.entityEditor.btnDelete.Enable(False)
def unrestrict(self):
self.btnRename.Enable(True)
self.btnDelete.Enable(True)
self.iview.Enable(True)
self.aview.Enable(True)
self.entityEditor.btnRename.Enable()
self.entityEditor.btnDelete.Enable()
def charChanged(self, event):
self.sview.populateSkillTree()
sChar = service.Character.getInstance()
charID = self.getActiveCharacter()
if sChar.getCharName(charID) in ("All 0", "All 5"):
char = self.entityEditor.getActiveEntity()
if char.name in ("All 0", "All 5"):
self.restrict()
else:
self.unrestrict()
wx.PostEvent(self, GE.CharChanged())
self.btnRestrict()
if event is not None:
event.Skip()
def getActiveCharacter(self):
selection = self.charChoice.GetCurrentSelection()
return self.charChoice.GetClientData(selection) if selection is not None else None
def new(self, event):
sChar = service.Character.getInstance()
charID = sChar.new()
id = self.charChoice.Append(sChar.getCharName(charID), charID)
self.charChoice.SetSelection(id)
self.unrestrict()
self.btnSave.SetLabel("Create")
self.rename(None)
self.charChanged(None)
def rename(self, event):
if event is not None:
self.btnSave.SetLabel("Rename")
self.charChoice.Hide()
self.characterRename.Show()
self.navSizer.Replace(self.charChoice, self.characterRename)
self.characterRename.SetFocus()
for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete):
btn.Hide()
self.btnSave.Show()
self.navSizer.Layout()
sChar = service.Character.getInstance()
currName = sChar.getCharName(self.getActiveCharacter())
self.characterRename.SetValue(currName)
self.characterRename.SetSelection(0, len(currName))
def processRename(self, event):
sChar = service.Character.getInstance()
newName = self.characterRename.GetLineText(0)
if newName == "All 0" or newName == "All 5":
newName = newName + " bases are belong to us"
charID = self.getActiveCharacter()
sChar.rename(charID, newName)
self.charChoice.Show()
self.characterRename.Hide()
self.navSizer.Replace(self.characterRename, self.charChoice)
for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete):
btn.Show()
self.btnSave.Hide()
self.navSizer.Layout()
self.refreshCharacterList()
def copy(self, event):
sChar = service.Character.getInstance()
charID = sChar.copy(self.getActiveCharacter())
id = self.charChoice.Append(sChar.getCharName(charID), charID)
self.charChoice.SetSelection(id)
self.unrestrict()
self.btnSave.SetLabel("Copy")
self.rename(None)
wx.PostEvent(self, GE.CharChanged())
def delete(self, event):
dlg = wx.MessageDialog(self,
"Do you really want to delete this character?",
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
sChar = service.Character.getInstance()
sChar.delete(self.getActiveCharacter())
sel = self.charChoice.GetSelection()
self.charChoice.Delete(sel)
self.charChoice.SetSelection(sel - 1)
newSelection = self.getActiveCharacter()
if sChar.getCharName(newSelection) in ("All 0", "All 5"):
self.restrict()
wx.PostEvent(self, GE.CharChanged())
def Destroy(self):
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
@@ -308,7 +233,8 @@ class CharacterEditor(wx.Frame):
class SkillTreeView (wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -335,6 +261,10 @@ class SkillTreeView (wx.Panel):
tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.scheduleMenu)
# bind the Character selection event
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.populateSkillTree)
self.charEditor.Bind(GE.CHAR_LIST_UPDATED, self.populateSkillTree)
srcContext = "skillItem"
itemContext = "Skill"
context = (srcContext, itemContext)
@@ -365,11 +295,10 @@ class SkillTreeView (wx.Panel):
self.Layout()
def populateSkillTree(self):
def populateSkillTree(self, event=None):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
dirtySkills = sChar.getDirtySkills(charID)
dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
char = self.charEditor.entityEditor.getActiveEntity()
dirtyGroups = set([skill.item.group.ID for skill in char.dirtySkills])
groups = sChar.getSkillGroups()
imageId = self.skillBookImageId
@@ -386,6 +315,9 @@ class SkillTreeView (wx.Panel):
tree.SortChildren(root)
if event:
event.Skip()
def expandLookup(self, event):
root = event.Item
tree = self.skillTreeListCtrl
@@ -395,11 +327,11 @@ class SkillTreeView (wx.Panel):
#Get the real intrestin' stuff
sChar = service.Character.getInstance()
char = self.Parent.Parent.getActiveCharacter()
char = self.charEditor.entityEditor.getActiveEntity()
for id, name in sChar.getSkills(tree.GetPyData(root)):
iconId = self.skillBookImageId
childId = tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id))
level, dirty = sChar.getSkillLevel(char, id)
level, dirty = sChar.getSkillLevel(char.ID, id)
tree.SetItemText(childId, "Level %d" % level if isinstance(level, int) else level, 1)
if dirty:
tree.SetItemTextColour(childId, wx.BLUE)
@@ -415,10 +347,9 @@ class SkillTreeView (wx.Panel):
if self.skillTreeListCtrl.GetChildrenCount(item) > 0:
return
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
char = self.charEditor.entityEditor.getActiveEntity()
sMkt = service.Market.getInstance()
if sChar.getCharName(charID) not in ("All 0", "All 5"):
if char.name not in ("All 0", "All 5"):
self.levelChangeMenu.selection = sMkt.getItem(self.skillTreeListCtrl.GetPyData(item))
self.PopupMenu(self.levelChangeMenu)
else:
@@ -429,21 +360,21 @@ class SkillTreeView (wx.Panel):
level = self.levelIds.get(event.Id)
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
char = self.charEditor.entityEditor.getActiveEntity()
selection = self.skillTreeListCtrl.GetSelection()
skillID = self.skillTreeListCtrl.GetPyData(selection)
if level is not None:
self.skillTreeListCtrl.SetItemText(selection, "Level %d" % level if isinstance(level, int) else level, 1)
sChar.changeLevel(charID, skillID, level, persist=True)
sChar.changeLevel(char.ID, skillID, level, persist=True)
elif event.Id == self.revertID:
sChar.revertLevel(charID, skillID)
sChar.revertLevel(char.ID, skillID)
elif event.Id == self.saveID:
sChar.saveSkill(charID, skillID)
sChar.saveSkill(char.ID, skillID)
self.skillTreeListCtrl.SetItemTextColour(selection, None)
dirtySkills = sChar.getDirtySkills(charID)
dirtySkills = sChar.getDirtySkills(char.ID)
dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
parentID = self.skillTreeListCtrl.GetItemParent(selection)
@@ -452,7 +383,6 @@ class SkillTreeView (wx.Panel):
if groupID not in dirtyGroups:
self.skillTreeListCtrl.SetItemTextColour(parentID, None)
wx.PostEvent(self.Parent.Parent, GE.CharListUpdated())
event.Skip()
@@ -460,31 +390,37 @@ class ImplantEditorView(BaseImplantEditorView):
def __init__(self, parent):
BaseImplantEditorView.__init__ (self, parent)
if "__WXGTK__" in wx.PlatformInfo:
self.determineEnabled()
if "__WXGTK__" in wx.PlatformInfo:
self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def bindContext(self):
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.contextChanged)
self.Parent.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged)
def contextChanged(self, event):
BaseImplantEditorView.contextChanged(self, event)
self.determineEnabled()
def getImplantsFromContext(self):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
char = self.Parent.Parent.entityEditor.getActiveEntity()
return sChar.getImplants(charID)
return sChar.getImplants(char.ID)
def addImplantToContext(self, item):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
char = self.Parent.Parent.entityEditor.getActiveEntity()
sChar.addImplant(charID, item.ID)
sChar.addImplant(char.ID, item.ID)
def removeImplantFromContext(self, pos):
def removeImplantFromContext(self, implant):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
char = self.Parent.Parent.entityEditor.getActiveEntity()
sChar.removeImplant(charID, self.implants[pos])
sChar.removeImplant(char.ID, implant)
def scheduleMenu(self, event):
event.Skip()
@@ -497,11 +433,19 @@ class ImplantEditorView(BaseImplantEditorView):
menu = ContextMenu.getMenu((self.Parent.Parent,), *context)
self.PopupMenu(menu)
def determineEnabled(self):
char = self.Parent.Parent.entityEditor.getActiveEntity()
if char.name in ("All 0", "All 5"):
self.Enable(False)
else:
self.Enable()
class APIView (wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
self.apiUrlCreatePredefined = u"https://community.eveonline.com/support/api-key/CreatePredefined?accessMask=8"
@@ -585,13 +529,17 @@ class APIView (wx.Panel):
self.hlEveAPI2 = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI2, 0, wx.ALL, 2 )
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
self.SetSizer(pmainSizer)
self.Layout()
self.charChanged(None)
def charChanged(self, event):
sChar = service.Character.getInstance()
ID, key, char, chars = sChar.getApiDetails(self.Parent.Parent.getActiveCharacter())
activeChar = self.charEditor.entityEditor.getActiveEntity()
ID, key, char, chars = sChar.getApiDetails(activeChar.ID)
self.inputID.SetValue(str(ID))
self.inputKey.SetValue(key)
@@ -609,6 +557,14 @@ class APIView (wx.Panel):
self.charChoice.Enable(False)
self.btnFetchSkills.Enable(False)
if activeChar.name in ("All 0", "All 5"):
self.Enable(False)
self.stDisabledTip.Show()
self.Layout()
else:
self.Enable()
self.stDisabledTip.Hide()
self.Layout()
if event is not None:
event.Skip()

View File

@@ -83,9 +83,9 @@ class CharacterSelection(wx.Panel):
charList = sChar.getCharacterList()
picked = False
for id, name, active in charList:
currId = choice.Append(name, id)
if id == activeChar:
for char in charList:
currId = choice.Append(char.name, char.ID)
if char.ID == activeChar:
choice.SetSelection(currId)
self.charChanged(None)
picked = True

View File

@@ -346,9 +346,8 @@ class GangView ( ScrolledPanel ):
choice.Clear()
currSelFound = False
for char in charList:
id,name,_ = char
choice.Append(name, id)
if chCurrData == id:
choice.Append(char.name, char.ID)
if chCurrData == char.ID:
currSelFound = True
if chCurrSelection == -1:

View File

@@ -359,9 +359,7 @@ class MainFrame(wx.Frame):
dlg.Show()
def showTargetResistsEditor(self, event):
dlg=ResistsEditorDlg(self)
dlg.ShowModal()
dlg.Destroy()
ResistsEditorDlg(self)
def showDamagePatternEditor(self, event):
dlg=DmgPatternEditorDlg(self)
@@ -369,9 +367,7 @@ class MainFrame(wx.Frame):
dlg.Destroy()
def showImplantSetEditor(self, event):
dlg=ImplantSetEditorDlg(self)
dlg.ShowModal()
dlg.Destroy()
ImplantSetEditorDlg(self)
def showExportDialog(self, event):
""" Export active fit """

View File

@@ -23,11 +23,64 @@ import service
from wx.lib.intctrl import IntCtrl
from gui.utils.clipboard import toClipboard, fromClipboard
from service.damagePattern import ImportError
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
###########################################################################
## Class DmgPatternEditorDlg
###########################################################################
class DmgPatternTextValidor(BaseValidator):
def __init__(self):
BaseValidator.__init__(self)
def Clone(self):
return DmgPatternTextValidor()
def Validate(self, win):
profileEditor = win.Parent
textCtrl = self.GetWindow()
text = textCtrl.GetValue().strip()
try:
if len(text) == 0:
raise ValueError("You must supply a name for your Damage Profile!")
elif text in [x.name for x in profileEditor.entityEditor.choices]:
raise ValueError("Damage Profile name already in use, please choose another.")
return True
except ValueError, e:
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
class DmgPatternEntityEditor(EntityEditor):
def __init__(self, parent):
EntityEditor.__init__(self, parent, "Damage Profile")
self.SetEditorValidator(DmgPatternTextValidor)
def getEntitiesFromContext(self):
sDP = service.DamagePattern.getInstance()
choices = sorted(sDP.getDamagePatternList(), key=lambda p: p.name)
return [c for c in choices if c.name != "Selected Ammo"]
def DoNew(self, name):
sDP = service.DamagePattern.getInstance()
return sDP.newPattern(name)
def DoRename(self, entity, name):
sDP = service.DamagePattern.getInstance()
sDP.renamePattern(entity, name)
def DoCopy(self, entity, name):
sDP = service.DamagePattern.getInstance()
copy = sDP.copyPattern(entity)
sDP.renamePattern(copy, name)
return copy
def DoDelete(self, entity):
sDP = service.DamagePattern.getInstance()
sDP.deletePattern(entity)
class DmgPatternEditorDlg(wx.Dialog):
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
@@ -39,52 +92,8 @@ class DmgPatternEditorDlg(wx.Dialog):
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)
sDP = service.DamagePattern.getInstance()
self.choices = sDP.getDamagePatternList()
# Remove "Selected Ammo" Damage Pattern
for dp in self.choices:
if dp.name == "Selected Ammo":
self.choices.remove(dp)
# Sort the remaining list and continue on
self.choices.sort(key=lambda p: p.name)
self.ccDmgPattern = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
self.ccDmgPattern.Bind(wx.EVT_CHOICE, self.patternChanged)
self.ccDmgPattern.SetSelection(0)
self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
self.namePicker.Hide()
size = None
headerSizer.Add(self.ccDmgPattern, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT|wx.LEFT, 3)
buttons = (("new", wx.ART_NEW),
("rename", BitmapLoader.getBitmap("rename", "gui")),
("copy", wx.ART_COPY),
("delete", wx.ART_DELETE))
for name, art in buttons:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s pattern" % name.capitalize())
headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
self.btnSave = wx.Button(self, wx.ID_SAVE)
self.btnSave.Hide()
self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
self.headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)
self.entityEditor = DmgPatternEntityEditor(self)
mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
@@ -108,7 +117,7 @@ class DmgPatternEditorDlg(wx.Dialog):
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big"%type, "gui"))
if i%2:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT
border = 10
border = 20
else:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT
border = 5
@@ -155,6 +164,7 @@ class DmgPatternEditorDlg(wx.Dialog):
importExport = (("Import", wx.ART_FILE_OPEN, "from"),
("Export", wx.ART_FILE_SAVE_AS, "to"))
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
@@ -170,14 +180,10 @@ class DmgPatternEditorDlg(wx.Dialog):
self.Layout()
bsize = self.GetBestSize()
self.SetSize((-1,bsize.height))
self.SetSize((-1, bsize.height))
self.CenterOnParent()
self.new.Bind(wx.EVT_BUTTON, self.newPattern)
self.rename.Bind(wx.EVT_BUTTON, self.renamePattern)
self.copy.Bind(wx.EVT_BUTTON, self.copyPattern)
self.delete.Bind(wx.EVT_BUTTON, self.deletePattern)
self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
self.Bind(wx.EVT_CHOICE, self.patternChanged)
self.patternChanged()
@@ -188,7 +194,7 @@ class DmgPatternEditorDlg(wx.Dialog):
if self.block:
return
p = self.getActivePattern()
p = self.entityEditor.getActiveEntity()
total = sum(map(lambda attr: getattr(self, "%sEdit"%attr).GetValue(), self.DAMAGE_TYPES))
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
@@ -207,24 +213,18 @@ class DmgPatternEditorDlg(wx.Dialog):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable(False)
self.rename.Enable(False)
self.delete.Enable(False)
self.entityEditor.btnRename.Enable(False)
self.entityEditor.btnDelete.Enable(False)
def unrestrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable()
self.rename.Enable()
self.delete.Enable()
def getActivePattern(self):
if len(self.choices) == 0:
return None
return self.choices[self.ccDmgPattern.GetSelection()]
self.entityEditor.btnRename.Enable()
self.entityEditor.btnDelete.Enable()
def patternChanged(self, event=None):
p = self.getActivePattern()
p = self.entityEditor.getActiveEntity()
if p is None:
return
@@ -244,126 +244,9 @@ class DmgPatternEditorDlg(wx.Dialog):
self.block = False
self.ValuesUpdated()
def newPattern(self, event):
self.restrict()
self.block = True
# reset values
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.SetValue(0)
self.block = False
self.btnSave.SetLabel("Create")
self.Refresh()
self.renamePattern()
def renamePattern(self, event=None):
if event is not None:
self.btnSave.SetLabel("Rename")
self.ccDmgPattern.Hide()
self.namePicker.Show()
self.headerSizer.Replace(self.ccDmgPattern, self.namePicker)
self.namePicker.SetFocus()
if event is not None: # Rename mode
self.btnSave.SetLabel("Rename")
self.namePicker.SetValue(self.getActivePattern().name)
else: # Create mode
self.namePicker.SetValue("")
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Hide()
self.btnSave.Show()
self.headerSizer.Layout()
if event is not None:
event.Skip()
def processRename(self, event):
newName = self.namePicker.GetLineText(0)
self.stNotice.SetLabel("")
if newName == "":
self.stNotice.SetLabel("Invalid name.")
return
sDP = service.DamagePattern.getInstance()
if self.btnSave.Label == "Create":
p = sDP.newPattern()
else:
# we are renaming, so get the current selection
p = self.getActivePattern()
for pattern in self.choices:
if pattern.name == newName and p != pattern:
self.stNotice.SetLabel("Name already used, please choose another")
return
sDP.renamePattern(p, newName)
self.updateChoices(newName)
self.headerSizer.Replace(self.namePicker, self.ccDmgPattern)
self.ccDmgPattern.Show()
self.namePicker.Hide()
self.btnSave.Hide()
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Show()
sel = self.ccDmgPattern.GetSelection()
self.ccDmgPattern.Delete(sel)
self.ccDmgPattern.Insert(newName, sel)
self.ccDmgPattern.SetSelection(sel)
self.ValuesUpdated()
self.unrestrict()
def copyPattern(self,event):
sDP = service.DamagePattern.getInstance()
p = sDP.copyPattern(self.getActivePattern())
self.choices.append(p)
id = self.ccDmgPattern.Append(p.name)
self.ccDmgPattern.SetSelection(id)
self.btnSave.SetLabel("Copy")
self.renamePattern()
self.patternChanged()
def deletePattern(self,event):
sDP = service.DamagePattern.getInstance()
sel = self.ccDmgPattern.GetSelection()
sDP.deletePattern(self.getActivePattern())
self.ccDmgPattern.Delete(sel)
self.ccDmgPattern.SetSelection(max(0, sel - 1))
del self.choices[sel]
self.patternChanged()
def __del__( self ):
def __del__(self):
pass
def updateChoices(self, select=None):
"Gathers list of patterns and updates choice selections"
sDP = service.DamagePattern.getInstance()
self.choices = sDP.getDamagePatternList()
for dp in self.choices:
if dp.name == "Selected Ammo": # don't include this special butterfly
self.choices.remove(dp)
# Sort the remaining list and continue on
self.choices.sort(key=lambda p: p.name)
self.ccDmgPattern.Clear()
for i, choice in enumerate(map(lambda p: p.name, self.choices)):
self.ccDmgPattern.Append(choice)
if select is not None and choice == select:
self.ccDmgPattern.SetSelection(i)
if select is None:
self.ccDmgPattern.SetSelection(0)
self.patternChanged()
def importPatterns(self, event):
text = fromClipboard()
if text:
@@ -384,3 +267,6 @@ class DmgPatternEditorDlg(wx.Dialog):
sDP = service.DamagePattern.getInstance()
toClipboard( sDP.exportPatterns() )
self.stNotice.SetLabel("Patterns exported to clipboard")
def contextChanged(self, event):
print "lol"

View File

@@ -22,6 +22,61 @@ from gui.bitmapLoader import BitmapLoader
import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.targetResists import ImportError
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
class TargetResistsTextValidor(BaseValidator):
def __init__(self):
BaseValidator.__init__(self)
def Clone(self):
return TargetResistsTextValidor()
def Validate(self, win):
profileEditor = win.parent.Parent
textCtrl = self.GetWindow()
text = textCtrl.GetValue().strip()
try:
if len(text) == 0:
raise ValueError("You must supply a name for your Target Resist Profile!")
elif text in [x.name for x in profileEditor.entityEditor.choices]:
raise ValueError("Target Resist Profile name already in use, please choose another.")
return True
except ValueError, e:
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
class TargetResistsEntityEditor(EntityEditor):
def __init__(self, parent):
EntityEditor.__init__(self, parent, "Target Resist Profile")
self.SetEditorValidator(TargetResistsTextValidor)
def getEntitiesFromContext(self):
sTR = service.TargetResists.getInstance()
choices = sorted(sTR.getTargetResistsList(), key=lambda p: p.name)
return choices
def DoNew(self, name):
sTR = service.TargetResists.getInstance()
return sTR.newPattern(name)
def DoRename(self, entity, name):
sTR = service.TargetResists.getInstance()
sTR.renamePattern(entity, name)
def DoCopy(self, entity, name):
sTR = service.TargetResists.getInstance()
copy = sTR.copyPattern(entity)
sTR.renamePattern(copy, name)
return copy
def DoDelete(self, entity):
sTR = service.TargetResists.getInstance()
sTR.deletePattern(entity)
class ResistsEditorDlg(wx.Dialog):
@@ -35,51 +90,8 @@ class ResistsEditorDlg(wx.Dialog):
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)
sTR = service.TargetResists.getInstance()
self.choices = sTR.getTargetResistsList()
# Sort the remaining list and continue on
self.choices.sort(key=lambda p: p.name)
self.ccResists = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
self.ccResists.Bind(wx.EVT_CHOICE, self.patternChanged)
self.ccResists.SetSelection(0)
self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
self.namePicker.Hide()
size = None
headerSizer.Add(self.ccResists, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
buttons = (("new", wx.ART_NEW),
("rename", BitmapLoader.getBitmap("rename", "gui")),
("copy", wx.ART_COPY),
("delete", wx.ART_DELETE))
for name, art in buttons:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s resist profile" % name.capitalize())
headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
self.btnSave = wx.Button(self, wx.ID_SAVE)
self.btnSave.Hide()
self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)
self.entityEditor = TargetResistsEntityEditor(self)
mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
@@ -157,19 +169,21 @@ class ResistsEditorDlg(wx.Dialog):
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) )
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
if not self.entityEditor.checkEntitiesExist():
self.Destroy()
return
self.Layout()
bsize = self.GetBestSize()
self.SetSize((-1,bsize.height))
self.SetSize((-1, bsize.height))
self.CenterOnParent()
self.new.Bind(wx.EVT_BUTTON, self.newPattern)
self.rename.Bind(wx.EVT_BUTTON, self.renamePattern)
self.copy.Bind(wx.EVT_BUTTON, self.copyPattern)
self.delete.Bind(wx.EVT_BUTTON, self.deletePattern)
self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
self.Bind(wx.EVT_CHOICE, self.patternChanged)
self.patternChanged()
self.ShowModal()
def closeEvent(self, event):
self.Destroy()
@@ -184,7 +198,7 @@ class ResistsEditorDlg(wx.Dialog):
return
try:
p = self.getActivePattern()
p = self.entityEditor.getActiveEntity()
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
@@ -220,33 +234,15 @@ class ResistsEditorDlg(wx.Dialog):
finally: # Refresh for color changes to take effect immediately
self.Refresh()
def restrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable(False)
self.rename.Enable(False)
self.delete.Enable(False)
def unrestrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable()
self.rename.Enable()
self.delete.Enable()
def getActivePattern(self):
if len(self.choices) == 0:
return None
return self.choices[self.ccResists.GetSelection()]
def patternChanged(self, event=None):
"Event fired when user selects pattern. Can also be called from script"
p = self.getActivePattern()
if not self.entityEditor.checkEntitiesExist():
self.Destroy()
return
p = self.entityEditor.getActiveEntity()
if p is None:
# This happens when there are no patterns in the DB. As such, force
# user to create one first or exit dlg.
self.newPattern(None)
return
self.block = True
@@ -259,142 +255,9 @@ class ResistsEditorDlg(wx.Dialog):
self.block = False
self.ValuesUpdated()
def newPattern(self, event):
'''
Simply does new-pattern specifics: replaces label on button, restricts,
and resets values to default. Hands off to the rename function for
further handling.
'''
self.btnSave.SetLabel("Create")
self.restrict()
# reset values
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.ChangeValue("0.0")
editObj.SetForegroundColour(self.colorReset)
self.Refresh()
self.renamePattern()
def renamePattern(self, event=None):
"Changes layout to facilitate naming a pattern"
self.showInput(True)
if event is not None: # Rename mode
self.btnSave.SetLabel("Rename")
self.namePicker.SetValue(self.getActivePattern().name)
else: # Create mode
self.namePicker.SetValue("")
if event is not None:
event.Skip()
def processRename(self, event):
'''
Processes rename event (which can be new or old patterns). If new
pattern, creates it; if old, selects it. if checks are valid, rename
saves pattern to DB.
Also resets to default layout and unrestricts.
'''
newName = self.namePicker.GetLineText(0)
self.stNotice.SetLabel("")
if newName == "":
self.stNotice.SetLabel("Invalid name")
return
sTR = service.TargetResists.getInstance()
if self.btnSave.Label == "Create":
p = sTR.newPattern()
else:
# we are renaming, so get the current selection
p = self.getActivePattern()
# test for patterns of the same name
for pattern in self.choices:
if pattern.name == newName and p != pattern:
self.stNotice.SetLabel("Name already used, please choose another")
return
# rename regardless of new or rename
sTR.renamePattern(p, newName)
self.updateChoices(newName)
self.showInput(False)
sel = self.ccResists.GetSelection()
self.ValuesUpdated()
self.unrestrict()
def copyPattern(self,event):
sTR = service.TargetResists.getInstance()
p = sTR.copyPattern(self.getActivePattern())
self.choices.append(p)
id = self.ccResists.Append(p.name)
self.ccResists.SetSelection(id)
self.btnSave.SetLabel("Copy")
self.renamePattern()
self.patternChanged()
def deletePattern(self,event):
sTR = service.TargetResists.getInstance()
sel = self.ccResists.GetSelection()
sTR.deletePattern(self.getActivePattern())
self.ccResists.Delete(sel)
self.ccResists.SetSelection(max(0, sel - 1))
del self.choices[sel]
self.patternChanged()
def showInput(self, bool):
if bool and not self.namePicker.IsShown():
self.ccResists.Hide()
self.namePicker.Show()
self.headerSizer.Replace(self.ccResists, self.namePicker)
self.namePicker.SetFocus()
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Hide()
self.btnSave.Show()
self.restrict()
self.headerSizer.Layout()
elif not bool and self.namePicker.IsShown():
self.headerSizer.Replace(self.namePicker, self.ccResists)
self.ccResists.Show()
self.namePicker.Hide()
self.btnSave.Hide()
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Show()
self.unrestrict()
self.headerSizer.Layout()
def __del__( self ):
pass
def updateChoices(self, select=None):
"Gathers list of patterns and updates choice selections"
sTR = service.TargetResists.getInstance()
self.choices = sTR.getTargetResistsList()
if len(self.choices) == 0:
#self.newPattern(None)
return
# Sort the remaining list and continue on
self.choices.sort(key=lambda p: p.name)
self.ccResists.Clear()
for i, choice in enumerate(map(lambda p: p.name, self.choices)):
self.ccResists.Append(choice)
if select is not None and choice == select:
self.ccResists.SetSelection(i)
if select is None:
self.ccResists.SetSelection(0)
self.patternChanged()
def importPatterns(self, event):
"Event fired when import from clipboard button is clicked"

View File

@@ -24,9 +24,63 @@ import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.implantSet import ImportError
import logging
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
logger = logging.getLogger(__name__)
class ImplantTextValidor(BaseValidator):
def __init__(self):
BaseValidator.__init__(self)
def Clone(self):
return ImplantTextValidor()
def Validate(self, win):
profileEditor = win.parent.Parent
textCtrl = self.GetWindow()
text = textCtrl.GetValue().strip()
try:
if len(text) == 0:
raise ValueError("You must supply a name for the Implant Set!")
elif text in [x.name for x in profileEditor.entityEditor.choices]:
raise ValueError("Imlplant Set name already in use, please choose another.")
return True
except ValueError, e:
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
class ImplantSetEntityEditor(EntityEditor):
def __init__(self, parent):
EntityEditor.__init__(self, parent, "Implant Set")
self.SetEditorValidator(ImplantTextValidor)
def getEntitiesFromContext(self):
sIS = service.ImplantSets.getInstance()
return sorted(sIS.getImplantSetList(), key=lambda c: c.name)
def DoNew(self, name):
sIS = service.ImplantSets.getInstance()
return sIS.newSet(name)
def DoRename(self, entity, name):
sIS = service.ImplantSets.getInstance()
sIS.renameSet(entity, name)
def DoCopy(self, entity, name):
sIS = service.ImplantSets.getInstance()
copy = sIS.copySet(entity)
sIS.renameSet(copy, name)
return copy
def DoDelete(self, entity):
sIS = service.ImplantSets.getInstance()
sIS.deleteSet(entity)
class ImplantSetEditor(BaseImplantEditorView):
def __init__(self, parent):
BaseImplantEditorView.__init__(self, parent)
@@ -34,27 +88,26 @@ class ImplantSetEditor(BaseImplantEditorView):
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
def bindContext(self):
self.Parent.ccSets.Bind(wx.EVT_CHOICE, self.contextChanged)
self.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged)
def getImplantsFromContext(self):
sIS = service.ImplantSets.getInstance()
set = self.Parent.getActiveSet()
set = self.Parent.entityEditor.getActiveEntity()
if set:
return sIS.getImplants(set.ID)
return []
def addImplantToContext(self, item):
sIS = service.ImplantSets.getInstance()
set = self.Parent.getActiveSet()
set = self.Parent.entityEditor.getActiveEntity()
sIS.addImplant(set.ID, item.ID)
def removeImplantFromContext(self, pos):
def removeImplantFromContext(self, implant):
sIS = service.ImplantSets.getInstance()
set = self.Parent.getActiveSet()
sIS.removeImplant(set.ID, self.implants[pos])
set = self.Parent.entityEditor.getActiveEntity()
sIS.removeImplant(set.ID, implant)
class ImplantSetEditorDlg(wx.Dialog):
@@ -66,55 +119,8 @@ class ImplantSetEditorDlg(wx.Dialog):
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)
sIS = service.ImplantSets.getInstance()
self.choices = sIS.getImplantSetList()
# Sort the remaining list and continue on
self.choices.sort(key=lambda s: s.name)
self.ccSets = wx.Choice(self, wx.ID_ANY, style=0)
for set in self.choices:
i = self.ccSets.Append(set.name, set.ID)
self.ccSets.Bind(wx.EVT_CHOICE, self.setChanged)
self.ccSets.SetSelection(0)
self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
self.namePicker.Hide()
size = None
headerSizer.Add(self.ccSets, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
buttons = (("new", wx.ART_NEW),
("rename", BitmapLoader.getBitmap("rename", "gui")),
("copy", wx.ART_COPY),
("delete", wx.ART_DELETE))
for name, art in buttons:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s implant set" % name.capitalize())
headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
self.btnSave = wx.Button(self, wx.ID_SAVE)
self.btnSave.Hide()
self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)
self.entityEditor = ImplantSetEntityEditor(self)
mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
@@ -157,174 +163,29 @@ class ImplantSetEditorDlg(wx.Dialog):
self.SetSizer(mainSizer)
self.Layout()
self.new.Bind(wx.EVT_BUTTON, self.newSet)
self.rename.Bind(wx.EVT_BUTTON, self.renameSet)
self.copy.Bind(wx.EVT_BUTTON, self.copySet)
self.delete.Bind(wx.EVT_BUTTON, self.deleteSet)
if not self.entityEditor.checkEntitiesExist():
self.Destroy()
return
self.Bind(wx.EVT_CHOICE, self.entityChanged)
self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
self.CenterOnParent()
self.ShowModal()
def entityChanged(self, event):
if not self.entityEditor.checkEntitiesExist():
self.Destroy()
return
def closeEvent(self, event):
self.Destroy()
def getActiveSet(self):
selection = self.ccSets.GetCurrentSelection()
return self.ccSets.GetClientData(selection) if selection is not None else None
def restrict(self):
self.rename.Enable(False)
self.delete.Enable(False)
def unrestrict(self):
self.rename.Enable()
self.delete.Enable()
def getActiveSet(self):
if len(self.choices) == 0:
return None
return self.choices[self.ccSets.GetSelection()]
def setChanged(self, event=None):
"Event fired when user selects pattern. Can also be called from script"
p = self.getActiveSet()
self.iview.update()
if p is None:
# This happens when there are no patterns in the DB. As such, force
# user to create one first or exit dlg.
self.newSet(None)
return
def newSet(self, event):
'''
Simply does new-set specifics: replaces label on button, restricts,
and resets values to default. Hands off to the rename function for
further handling.
'''
self.btnSave.SetLabel("Create")
self.restrict()
self.Refresh()
self.renameSet()
def renameSet(self, event=None):
"Changes layout to facilitate naming a pattern"
self.showInput(True)
if event is not None: # Rename mode
self.btnSave.SetLabel("Rename")
self.namePicker.SetValue(self.getActiveSet().name)
else: # Create mode
self.namePicker.SetValue("")
if event is not None:
event.Skip()
def processRename(self, event):
'''
Processes rename event (which can be new or old patterns). If new
pattern, creates it; if old, selects it. if checks are valid, rename
saves pattern to DB.
Also resets to default layout and unrestricts.
'''
newName = self.namePicker.GetLineText(0)
self.stNotice.SetLabel("")
if newName == "":
self.stNotice.SetLabel("Invalid name")
return
sIS = service.ImplantSets.getInstance()
if self.btnSave.Label == "Create":
s = sIS.newSet()
else:
# we are renaming, so get the current selection
s = self.getActiveSet()
# test for patterns of the same name
for set in self.choices:
if set.name == newName and s != set:
self.stNotice.SetLabel("Name already used, please choose another")
return
# rename regardless of new or rename
sIS.renameSet(s, newName)
self.updateChoices(newName)
self.showInput(False)
sel = self.ccSets.GetSelection()
self.unrestrict()
def copySet(self,event):
sIS = service.ImplantSets.getInstance()
p = sIS.copySet(self.getActiveSet())
self.choices.append(p)
id = self.ccSets.Append(p.name)
self.ccSets.SetSelection(id)
self.btnSave.SetLabel("Copy")
self.renameSet()
self.setChanged()
def deleteSet(self,event):
sIS = service.ImplantSets.getInstance()
sel = self.ccSets.GetSelection()
sIS.deleteSet(self.getActiveSet())
self.ccSets.Delete(sel)
self.ccSets.SetSelection(max(0, sel - 1))
del self.choices[sel]
self.setChanged()
def showInput(self, bool):
if bool and not self.namePicker.IsShown():
self.ccSets.Hide()
self.namePicker.Show()
self.headerSizer.Replace(self.ccSets, self.namePicker)
self.namePicker.SetFocus()
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Hide()
self.btnSave.Show()
self.restrict()
self.headerSizer.Layout()
elif not bool and self.namePicker.IsShown():
self.headerSizer.Replace(self.namePicker, self.ccSets)
self.ccSets.Show()
self.namePicker.Hide()
self.btnSave.Hide()
for btn in (self.new, self.rename, self.delete, self.copy):
btn.Show()
self.unrestrict()
self.headerSizer.Layout()
def __del__( self ):
pass
def updateChoices(self, select=None):
"Gathers list of patterns and updates choice selections"
sIS = service.ImplantSets.getInstance()
self.choices = sIS.getImplantSetList()
if len(self.choices) == 0:
#self.newPattern(None)
return
# Sort the remaining list and continue on
self.choices.sort(key=lambda p: p.name)
self.ccSets.Clear()
for i, choice in enumerate(map(lambda p: p.name, self.choices)):
self.ccSets.Append(choice)
if select is not None and choice == select:
self.ccSets.SetSelection(i)
if select is None:
self.ccSets.SetSelection(0)
self.setChanged()
def importPatterns(self, event):
"Event fired when import from clipboard button is clicked"

View File

@@ -50,9 +50,8 @@ class CharacterImportThread(threading.Thread):
# we try to parse api XML data first
with open(path, mode='r') as charFile:
sheet = service.ParseXML(charFile)
charID = sCharacter.new()
sCharacter.rename(charID, sheet.name+" (imported)")
sCharacter.apiUpdateCharSheet(charID, sheet.skills)
char = sCharacter.new(sheet.name+" (imported)")
sCharacter.apiUpdateCharSheet(char.ID, sheet.skills)
except:
# if it's not api XML data, try this
# this is a horrible logic flow, but whatever
@@ -69,9 +68,8 @@ class CharacterImportThread(threading.Thread):
"typeID": int(skill.getAttribute("typeID")),
"level": int(skill.getAttribute("level")),
})
charID = sCharacter.new()
sCharacter.rename(charID, name+" (EVEMon)")
sCharacter.apiUpdateCharSheet(charID, skills)
char = sCharacter.new(name+" (EVEMon)")
sCharacter.apiUpdateCharSheet(char.ID, skills)
except:
continue
@@ -116,6 +114,11 @@ class Character(object):
return cls.instance
def __init__(self):
# Simply initializes default characters in case they aren't in the database yet
self.all0()
self.all5()
def exportText(self):
data = "Pyfa exported plan for \""+self.skillReqsDict['charname']+"\"\n"
data += "=" * 79 + "\n"
@@ -185,10 +188,7 @@ class Character(object):
return self.all5().ID
def getCharacterList(self):
baseChars = [eos.types.Character.getAll0(), eos.types.Character.getAll5()]
sFit = service.Fit.getInstance()
return map(lambda c: (c.ID, c.name if not c.isDirty else "{} *".format(c.name), c == sFit.character), eos.db.getCharacterList())
return eos.db.getCharacterList()
def getCharacter(self, charID):
char = eos.db.getCharacter(charID)
@@ -248,25 +248,21 @@ class Character(object):
def getCharName(self, charID):
return eos.db.getCharacter(charID).name
def new(self):
char = eos.types.Character("New Character")
def new(self, name="New Character"):
char = eos.types.Character(name)
eos.db.save(char)
return char.ID
return char
def rename(self, charID, newName):
char = eos.db.getCharacter(charID)
def rename(self, char, newName):
char.name = newName
eos.db.commit()
def copy(self, charID):
char = eos.db.getCharacter(charID)
def copy(self, char):
newChar = copy.deepcopy(char)
eos.db.save(newChar)
return newChar.ID
return newChar
def delete(self, charID):
char = eos.db.getCharacter(charID)
eos.db.commit()
def delete(self, char):
eos.db.remove(char)
def getApiDetails(self, charID):

View File

@@ -46,9 +46,10 @@ class DamagePattern():
def getDamagePattern(self, name):
return eos.db.getDamagePattern(name)
def newPattern(self):
def newPattern(self, name):
p = eos.types.DamagePattern(0, 0, 0, 0)
p.name = ""
p.name = name
eos.db.save(p)
return p
def renamePattern(self, p, newName):

View File

@@ -55,10 +55,11 @@ class ImplantSets():
set.implants.remove(implant)
eos.db.commit()
def newSet(self):
p = eos.types.ImplantSet()
p.name = ""
return p
def newSet(self, name):
s = eos.types.ImplantSet()
s.name = name
eos.db.save(s)
return s
def renameSet(self, s, newName):
s.name = newName

View File

@@ -39,9 +39,10 @@ class TargetResists():
def getTargetResists(self, name):
return eos.db.getTargetResists(name)
def newPattern(self):
def newPattern(self, name):
p = eos.types.TargetResists(0.0, 0.0, 0.0, 0.0)
p.name = ""
p.name = name
eos.db.save(p)
return p
def renamePattern(self, p, newName):