Merge branch 'master' into singularity

Conflicts:
	eos/db/saveddata/fit.py
	gui/additionsPane.py
This commit is contained in:
blitzman
2016-11-20 20:52:23 -05:00
5 changed files with 177 additions and 152 deletions

View File

@@ -0,0 +1,14 @@
"""
Migration 16
- Alters fits table to introduce notes attribute
"""
import sqlalchemy
def upgrade(saveddata_engine):
# Update fits schema to include notes attribute
try:
saveddata_engine.execute("SELECT notes FROM fits LIMIT 1")
except sqlalchemy.exc.DatabaseError:
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN notes VARCHAR;")

View File

@@ -1,4 +1,4 @@
#===============================================================================
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
@@ -15,49 +15,46 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.sql import and_
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import *
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.sql import and_
from eos.db import saveddata_meta
from eos.db.saveddata.module import modules_table
from eos.db.saveddata.cargo import cargo_table
from eos.db.saveddata.drone import drones_table
from eos.db.saveddata.fighter import fighters_table
from eos.db.saveddata.cargo import cargo_table
from eos.db.saveddata.implant import fitImplants_table
from eos.types import Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, TargetResists, ImplantLocation
from eos.db.saveddata.module import modules_table
from eos.effectHandlerHelpers import *
from eos.types import Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, \
TargetResists, ImplantLocation
fits_table = Table("fits", saveddata_meta,
Column("ID", Integer, primary_key = True),
Column("ownerID", ForeignKey("users.ID"), nullable = True, index = True),
Column("shipID", Integer, nullable = False, index = True),
Column("name", String, nullable = False),
Column("timestamp", Integer, nullable = False),
Column("characterID", ForeignKey("characters.ID"), nullable = True),
Column("damagePatternID", ForeignKey("damagePatterns.ID"), nullable=True),
Column("booster", Boolean, nullable = False, index = True, default = 0),
Column("targetResistsID", ForeignKey("targetResists.ID"), nullable=True),
Column("modeID", Integer, nullable=True),
Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
)
Column("ID", Integer, primary_key=True),
Column("ownerID", ForeignKey("users.ID"), nullable=True, index=True),
Column("shipID", Integer, nullable=False, index=True),
Column("name", String, nullable=False),
Column("timestamp", Integer, nullable=False),
Column("characterID", ForeignKey("characters.ID"), nullable=True),
Column("damagePatternID", ForeignKey("damagePatterns.ID"), nullable=True),
Column("booster", Boolean, nullable=False, index=True, default=0),
Column("targetResistsID", ForeignKey("targetResists.ID"), nullable=True),
Column("modeID", Integer, nullable=True),
Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
Column("notes", String, nullable = True),
)
projectedFits_table = Table("projectedFits", saveddata_meta,
Column("sourceID", ForeignKey("fits.ID"), primary_key = True),
Column("victimID", ForeignKey("fits.ID"), primary_key = True),
Column("amount", Integer, nullable = False, default = 1),
Column("active", Boolean, nullable = False, default = 1),
)
Column("sourceID", ForeignKey("fits.ID"), primary_key=True),
Column("victimID", ForeignKey("fits.ID"), primary_key=True),
Column("amount", Integer, nullable=False, default=1),
Column("active", Boolean, nullable=False, default=1),
)
commandFits_table = Table("commandFits", saveddata_meta,
Column("boosterID", ForeignKey("fits.ID"), primary_key = True),
Column("boostedID", ForeignKey("fits.ID"), primary_key = True),
Column("active", Boolean, nullable = False, default = 1)
)
class ProjectedFit(object):
def __init__(self, sourceID, source_fit, amount=1, active=True):
@@ -89,25 +86,6 @@ class ProjectedFit(object):
self.sourceID, self.victimID, self.amount, self.active, hex(id(self))
)
class CommandFit(object):
def __init__(self, boosterID, booster_fit, active=True):
self.boosterID = boosterID
self.booster_fit = booster_fit
self.active = active
@reconstructor
def init(self):
if self.booster_fit.isInvalid:
# Very rare for this to happen, but be prepared for it
eos.db.saveddata_session.delete(self.booster_fit)
eos.db.saveddata_session.flush()
eos.db.saveddata_session.refresh(self.boosted_fit)
def __repr__(self):
return "CommandFit(boosterID={}, boostedID={}, active={}) at {}".format(
self.boosterID, self.boostedID, self.active, hex(id(self))
)
Fit._Fit__projectedFits = association_proxy(
"victimOf", # look at the victimOf association...
@@ -115,111 +93,91 @@ Fit._Fit__projectedFits = association_proxy(
creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit)
)
Fit._Fit__commandFits = association_proxy(
"boostedOf", # look at the boostedOf association...
"booster_fit", # .. and return the booster fit
creator=lambda boosterID, booster_fit: CommandFit(boosterID, booster_fit)
)
mapper(Fit, fits_table,
properties = {
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by=modules_table.c.position,
cascade='all, delete, delete-orphan'),
"_Fit__projectedModules": relation(
Module,
collection_class=HandledProjectedModList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
"owner": relation(
User,
backref="fits"),
"itemID": fits_table.c.shipID,
"shipID": fits_table.c.shipID,
"_Fit__boosters": relation(
Booster,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
single_parent=True),
"_Fit__drones": relation(
Drone,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
"_Fit__fighters": relation(
Fighter,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)),
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones": relation(
Drone,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
"_Fit__projectedFighters": relation(
Fighter,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)),
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='fit',
single_parent=True,
primaryjoin=fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin=fitImplants_table.c.implantID == Implant.ID,
secondary=fitImplants_table),
"_Fit__character": relation(
Character,
backref="fits"),
"_Fit__damagePattern": relation(DamagePattern),
"_Fit__targetResists": relation(TargetResists),
"projectedOnto": relationship(
ProjectedFit,
primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID,
backref='source_fit',
collection_class=attribute_mapped_collection('victimID'),
cascade='all, delete, delete-orphan'),
"victimOf": relationship(
ProjectedFit,
primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID,
backref='victim_fit',
collection_class=attribute_mapped_collection('sourceID'),
cascade='all, delete, delete-orphan'),
"boostedOnto": relationship(
CommandFit,
primaryjoin=commandFits_table.c.boosterID == fits_table.c.ID,
backref='booster_fit',
collection_class=attribute_mapped_collection('boostedID'),
cascade='all, delete, delete-orphan'),
"boostedOf": relationship(
CommandFit,
primaryjoin=fits_table.c.ID == commandFits_table.c.boostedID,
backref='boosted_fit',
collection_class=attribute_mapped_collection('boosterID'),
cascade='all, delete, delete-orphan'),
properties={
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by=modules_table.c.position,
cascade='all, delete, delete-orphan'),
"_Fit__projectedModules": relation(
Module,
collection_class=HandledProjectedModList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
"owner": relation(
User,
backref="fits"),
"itemID": fits_table.c.shipID,
"shipID": fits_table.c.shipID,
"_Fit__boosters": relation(
Booster,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
single_parent=True),
"_Fit__drones": relation(
Drone,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
"_Fit__fighters": relation(
Fighter,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)),
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones": relation(
Drone,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
"_Fit__projectedFighters": relation(
Fighter,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)),
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='fit',
single_parent=True,
primaryjoin=fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin=fitImplants_table.c.implantID == Implant.ID,
secondary=fitImplants_table),
"_Fit__character": relation(
Character,
backref="fits"),
"_Fit__damagePattern": relation(DamagePattern),
"_Fit__targetResists": relation(TargetResists),
"projectedOnto": relationship(
ProjectedFit,
primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID,
backref='source_fit',
collection_class=attribute_mapped_collection('victimID'),
cascade='all, delete, delete-orphan'),
"victimOf": relationship(
ProjectedFit,
primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID,
backref='victim_fit',
collection_class=attribute_mapped_collection('sourceID'),
cascade='all, delete, delete-orphan'),
}
)
)
mapper(ProjectedFit, projectedFits_table,
properties = {
"_ProjectedFit__amount": projectedFits_table.c.amount,
properties={
"_ProjectedFit__amount": projectedFits_table.c.amount,
}
)
mapper(CommandFit, commandFits_table)
)

View File

@@ -1137,6 +1137,7 @@ class Fit(object):
copy.name = "%s copy" % self.name
copy.damagePattern = self.damagePattern
copy.targetResists = self.targetResists
copy.notes = self.notes
toCopy = (
"modules",

View File

@@ -25,7 +25,9 @@ from gui.fighterView import FighterView
from gui.cargoView import CargoView
from gui.implantView import ImplantView
from gui.projectedView import ProjectedView
from gui.commandView import CommandView
from gui.notesView import NotesView
from gui.pyfatogglepanel import TogglePanel
from gui.gangView import GangView
from gui.bitmapLoader import BitmapLoader
@@ -58,6 +60,7 @@ class AdditionsPane(TogglePanel):
projectedImg = BitmapLoader.getImage("projected_small", "gui")
gangImg = BitmapLoader.getImage("fleet_fc_small", "gui")
cargoImg = BitmapLoader.getImage("cargo_small", "gui")
notesImg = BitmapLoader.getImage("skill_small", "gui")
self.drone = DroneView(self.notebook)
self.notebook.AddPage(self.drone, "Drones", tabImage = droneImg, showClose = False)
@@ -80,9 +83,13 @@ class AdditionsPane(TogglePanel):
self.gangPage = CommandView(self.notebook)
self.notebook.AddPage(self.gangPage, "Command", tabImage = gangImg, showClose = False)
self.notes = NotesView(self.notebook)
self.notebook.AddPage(self.notes, "Notes", tabImage = notesImg, showClose = False)
self.notebook.SetSelection(0)
PANES = ["Drones", "Fighters", "Cargo", "Implants", "Boosters", "Projected", "Command"]
PANES = ["Drones", "Fighters", "Cargo", "Implants", "Boosters", "Projected", "Command", "Notes"]
def select(self, name):
self.notebook.SetSelection(self.PANES.index(name))

45
gui/notesView.py Normal file
View File

@@ -0,0 +1,45 @@
import wx
import service
import gui.globalEvents as GE
import gui.mainFrame
class NotesView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.lastFitId = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.editNotes = wx.TextCtrl(self, style=wx.TE_MULTILINE)
mainSizer.Add(self.editNotes, 1, wx.EXPAND)
self.SetSizer(mainSizer)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.Bind(wx.EVT_TEXT, self.onText)
self.saveTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.delayedSave, self.saveTimer)
def fitChanged(self, event):
sFit = service.Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
if event.fitID is None and self.lastFitId is not None:
self.lastFitId = None
event.Skip()
return
elif event.fitID != self.lastFitId:
self.lastFitId = event.fitID
self.editNotes.SetValue(fit.notes or "")
def onText(self, event):
# delay the save so we're not writing to sqlite on every keystroke
self.saveTimer.Stop() # cancel the existing timer
self.saveTimer.Start(1000, True)
def delayedSave(self, event):
sFit = service.Fit.getInstance()
fit = sFit.getFit(self.lastFitId)
newNotes = self.editNotes.GetValue()
fit.notes = newNotes
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fit.ID))