From ef36dc5ba3f4c3fb4fc29608962902dbfc107fe5 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 2 Nov 2015 18:42:01 -0500 Subject: [PATCH] Import/export/clear overrides, add missing files due to bad gitignore entry --- eos/db/saveddata/override.py | 31 ++++++++++ eos/db/saveddata/queries.py | 6 ++ eos/saveddata/override.py | 59 ++++++++++++++++++ gui/propertyEditor.py | 117 +++++++++++++++++++++++++++++++---- 4 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 eos/db/saveddata/override.py create mode 100644 eos/saveddata/override.py diff --git a/eos/db/saveddata/override.py b/eos/db/saveddata/override.py new file mode 100644 index 000000000..2d5d74a47 --- /dev/null +++ b/eos/db/saveddata/override.py @@ -0,0 +1,31 @@ +#=============================================================================== +# Copyright (C) 2010 Diego Duclos +# +# This file is part of eos. +# +# eos is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# eos 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with eos. If not, see . +#=============================================================================== + +from sqlalchemy import Table, Column, Integer, Float +from sqlalchemy.orm import mapper + +from eos.db import saveddata_meta +from eos.types import Override + +overrides_table = Table("overrides", saveddata_meta, + Column("itemID", Integer, primary_key=True, index = True), + Column("attrID", Integer, primary_key=True, index = True), + Column("value", Float, nullable = False)) + +mapper(Override, overrides_table) diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py index 7b2853b6f..172093191 100644 --- a/eos/db/saveddata/queries.py +++ b/eos/db/saveddata/queries.py @@ -422,6 +422,12 @@ def getOverrides(itemID, eager=None): else: raise TypeError("Need integer as argument") +def clearOverrides(): + with sd_lock: + deleted_rows = saveddata_session.query(Override).delete() + commit() + return deleted_rows + def getAllOverrides(eager=None): return saveddata_session.query(Override).all() diff --git a/eos/saveddata/override.py b/eos/saveddata/override.py new file mode 100644 index 000000000..b33875e89 --- /dev/null +++ b/eos/saveddata/override.py @@ -0,0 +1,59 @@ +#=============================================================================== +# Copyright (C) 2015 Ryan Holmes +# +# This file is part of eos. +# +# eos is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# eos 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with eos. If not, see . +#=============================================================================== + +from eos.eqBase import EqBase +from sqlalchemy.orm import validates, reconstructor +import eos.db +import logging + +logger = logging.getLogger(__name__) + +class Override(EqBase): + + def __init__(self, item, attr, value): + self.itemID = item.ID + self.__item = item + self.attrID = attr.ID + self.__attr = attr + self.value = value + + @reconstructor + def init(self): + self.__attr = None + self.__item = None + + if self.attrID: + self.__attr = eos.db.getAttributeInfo(self.attrID) + if self.__attr is None: + logger.error("Attribute (id: %d) does not exist", self.attrID) + return + + if self.itemID: + self.__item = eos.db.getItem(self.itemID) + if self.__item is None: + logger.error("Item (id: %d) does not exist", self.itemID) + return + + @property + def attr(self): + return self.__attr + + @property + def item(self): + return self.__item diff --git a/gui/propertyEditor.py b/gui/propertyEditor.py index 4172985ef..44c63307b 100644 --- a/gui/propertyEditor.py +++ b/gui/propertyEditor.py @@ -7,6 +7,8 @@ import gui.display as d import gui.globalEvents as GE from gui.bitmapLoader import BitmapLoader import service +import csv +import eos.db import logging @@ -22,26 +24,53 @@ class AttributeEditor( wx.Frame ): self.SetIcon(i) self.mainFrame = parent - self.panel = panel = wx.Panel(self, wx.ID_ANY) - topsizer = wx.BoxSizer(wx.HORIZONTAL) - leftsizer = wx.BoxSizer(wx.VERTICAL) + menubar = wx.MenuBar() + fileMenu = wx.Menu() + fileImport = fileMenu.Append(wx.ID_ANY, 'Import', 'Import overrides') + fileExport = fileMenu.Append(wx.ID_ANY, 'Export', 'Import overrides') + fileClear = fileMenu.Append(wx.ID_ANY, 'Clear All', 'Clear all overrides') + + menubar.Append(fileMenu, '&File') + self.SetMenuBar(menubar) + + self.Bind(wx.EVT_MENU, self.OnImport, fileImport) + self.Bind(wx.EVT_MENU, self.OnExport, fileExport) + self.Bind(wx.EVT_MENU, self.OnClear, fileClear) + + + i = wx.IconFromBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui")) + self.SetIcon(i) + + self.mainFrame = parent + self.panel = panel = wx.Panel(self, wx.ID_ANY) + + mainSizer = wx.BoxSizer(wx.HORIZONTAL) + + leftSizer = wx.BoxSizer(wx.VERTICAL) leftPanel = wx.Panel(panel, wx.ID_ANY, style=wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER) self.searchBox = SearchBox(leftPanel) self.itemView = ItemView(leftPanel) - leftsizer.Add(self.searchBox, 0, wx.EXPAND) - leftsizer.Add(self.itemView, 1, wx.EXPAND) + leftSizer.Add(self.searchBox, 0, wx.EXPAND) + leftSizer.Add(self.itemView, 1, wx.EXPAND) - leftPanel.SetSizer(leftsizer) - topsizer.Add(leftPanel, 1, wx.ALL | wx.EXPAND, 5) + leftPanel.SetSizer(leftSizer) + mainSizer.Add(leftPanel, 1, wx.ALL | wx.EXPAND, 5) + rightSizer = wx.BoxSizer(wx.VERTICAL) + self.btnRemoveOverrides = wx.Button( panel, wx.ID_ANY, u"Remove Overides for Item", wx.DefaultPosition, wx.DefaultSize, 0 ) self.pg = AttributeGrid(panel) - topsizer.Add(self.pg, 1, wx.ALL|wx.EXPAND, 5) + rightSizer.Add(self.pg, 1, wx.ALL|wx.EXPAND, 5) + rightSizer.Add(self.btnRemoveOverrides, 0, wx.ALL | wx.EXPAND, 5 ) + self.btnRemoveOverrides.Bind(wx.EVT_BUTTON, self.pg.removeOverrides) + self.btnRemoveOverrides.Enable(False) - panel.SetSizer(topsizer) - topsizer.SetSizeHints(panel) + mainSizer.Add(rightSizer, 1, wx.EXPAND) + + panel.SetSizer(mainSizer) + mainSizer.SetSizeHints(panel) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(panel, 1, wx.EXPAND) @@ -56,6 +85,48 @@ class AttributeEditor( wx.Frame ): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) self.Destroy() + def OnImport(self, event): + dlg = wx.FileDialog(self, "Import pyfa override file", + wildcard = "pyfa override file (*.csv)|*.csv", + style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if (dlg.ShowModal() == wx.ID_OK): + path = dlg.GetPath() + with open(path, 'rb') as csvfile: + spamreader = csv.reader(csvfile) + for row in spamreader: + itemID, attrID, value = row + item = eos.db.getItem(int(itemID)) + attr = eos.db.getAttributeInfo(int(attrID)) + item.setOverride(attr, float(value)) + self.itemView.updateItems(True) + + def OnExport(self, event): + sMkt = service.Market.getInstance() + items = sMkt.getItemsWithOverrides() + defaultFile = "pyfa_overrides.csv" + + dlg = wx.FileDialog(self, "Save Overrides As...", + wildcard = "pyfa overrides (*.csv)|*.csv", + style = wx.FD_SAVE, + defaultFile=defaultFile) + + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + with open(path, 'wb') as csvfile: + writer = csv.writer(csvfile) + for item in items: + for key, override in item.overrides.iteritems(): + writer.writerow([item.ID, override.attrID, override.value]) + + def OnClear(self, event): + dlg = wx.MessageDialog(self, + "Are you sure you want to delete all overrides?", + "Confirm Delete", wx.YES | wx.NO | wx.ICON_EXCLAMATION) + + if dlg.ShowModal() == wx.ID_YES: + eos.db.clearOverrides() + self.itemView.updateItems(True) + self.pg.Clear() # This is literally a stripped down version of the market. class ItemView(d.Display): @@ -86,9 +157,12 @@ class ItemView(d.Display): self.items = self.things self.update(self.items) - def updateItems(self): + def updateItems(self, updateDisplay=False): sMkt = service.Market.getInstance() self.things = sMkt.getItemsWithOverrides() + self.items = self.things + if updateDisplay: + self.update(self.things) def scheduleSearch(self, event=None): sMkt = service.Market.getInstance() @@ -118,6 +192,8 @@ class AttributeGrid(wxpg.PropertyGrid): self.itemView = parent.Parent.itemView + self.btn = parent.Parent.btnRemoveOverrides + self.Bind( wxpg.EVT_PG_CHANGED, self.OnPropGridChange ) self.Bind( wxpg.EVT_PG_SELECTED, self.OnPropGridSelect ) self.Bind( wxpg.EVT_PG_RIGHT_CLICK, self.OnPropGridRightClick ) @@ -127,6 +203,7 @@ class AttributeGrid(wxpg.PropertyGrid): def itemActivated(self, event): self.Clear() + self.btn.Enable(True) sel = event.EventObject.GetFirstSelected() self.item = item = self.itemView.items[sel] @@ -140,9 +217,25 @@ class AttributeGrid(wxpg.PropertyGrid): prop = wxpg.FloatProperty(key, value=default) prop.SetClientData(item.attributes[key]) # set this so that we may access it later - prop.SetHelpString("%s\n%s"%(item.attributes[key].displayName or key, "Default Value: %0.2f"%default)) + prop.SetHelpString("%s\n%s"%(item.attributes[key].displayName or key, "Default Value: %0.3f"%default)) self.Append(prop) + def removeOverrides(self, event): + if self.item is None: + return + + for _, x in self.item.overrides.items(): + self.item.deleteOverride(x.attr) + self.itemView.updateItems(True) + self.ClearModifiedStatus() + self.itemView.Select(self.itemView.GetFirstSelected(), on=False) + self.Clear() + + def Clear(self): + self.item = None + self.btn.Enable(False) + wxpg.PropertyGrid.Clear(self) + def OnPropGridChange(self, event): p = event.GetProperty() attr = p.GetClientData()