Merge branch 'master' into cargo
Conflicts: eos/saveddata/fit.py
@@ -66,7 +66,7 @@ from eos.db.saveddata.queries import getUser, getCharacter, getFit, getFitsWithS
|
||||
getCharacterList, getPrice, getDamagePatternList, getDamagePattern, \
|
||||
getFitList, getFleetList, getFleet, save, remove, commit, add, \
|
||||
getCharactersForUser, getMiscData, getSquadsIDsWithFitID, getWing, \
|
||||
getSquad, getBoosterFits
|
||||
getSquad, getBoosterFits, getProjectedFits
|
||||
|
||||
#If using in memory saveddata, you'll want to reflect it so the data structure is good.
|
||||
if config.saveddata_connectionstring == "sqlite:///:memory:":
|
||||
|
||||
@@ -21,6 +21,7 @@ from eos.db.util import processEager, processWhere
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.types import User, Character, Fit, Price, DamagePattern, Fleet, MiscData, Wing, Squad
|
||||
from eos.db.saveddata.fleet import squadmembers_table
|
||||
from eos.db.saveddata.fit import projectedFits_table
|
||||
from sqlalchemy.sql import and_
|
||||
import eos.config
|
||||
|
||||
@@ -360,7 +361,15 @@ def getSquadsIDsWithFitID(fitID):
|
||||
return squads
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
|
||||
def getProjectedFits(fitID):
|
||||
if isinstance(fitID, int):
|
||||
with sd_lock:
|
||||
filter = and_(projectedFits_table.c.sourceID == fitID, Fit.ID == projectedFits_table.c.victimID)
|
||||
fits = saveddata_session.query(Fit).filter(filter).all()
|
||||
return fits
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
def add(stuff):
|
||||
with sd_lock:
|
||||
|
||||
@@ -196,10 +196,12 @@ class Fit(object):
|
||||
def importEft(cls, eftString):
|
||||
from eos import db
|
||||
offineSuffix = " /OFFLINE"
|
||||
|
||||
fit = cls()
|
||||
eftString = eftString.strip()
|
||||
lines = re.split('[\n\r]+', eftString)
|
||||
info = lines[0][1:-1].split(",", 1)
|
||||
|
||||
if len(info) == 2:
|
||||
shipType = info[0].strip()
|
||||
fitName = info[1].strip()
|
||||
@@ -212,28 +214,46 @@ class Fit(object):
|
||||
fit.name = fitName
|
||||
except:
|
||||
return
|
||||
|
||||
# maintain map of drones and their quantities
|
||||
droneMap = {}
|
||||
for i in range(1, len(lines)):
|
||||
ammoName = None
|
||||
droneAmount = None
|
||||
|
||||
line = lines[i].strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
setOffline = line.endswith(offineSuffix)
|
||||
if setOffline == True:
|
||||
# remove offline suffix from line
|
||||
line = line[:len(line) - len(offineSuffix)]
|
||||
|
||||
modAmmo = line.split(",")
|
||||
modDrone = modAmmo[0].split(" x")
|
||||
if len(modAmmo) == 2: ammoName = modAmmo[1].strip()
|
||||
else: ammoName = None
|
||||
modName = modDrone[0].strip()
|
||||
if len(modDrone) == 2: droneAmount = modDrone[1].strip()
|
||||
else: droneAmount = None
|
||||
# matches drone and cargo with x{qty}
|
||||
modExtra = modAmmo[0].split(" x")
|
||||
|
||||
if len(modAmmo) == 2:
|
||||
# line with a module and ammo
|
||||
ammoName = modAmmo[1].strip()
|
||||
modName = modAmmo[0].strip()
|
||||
elif len(modExtra) == 2:
|
||||
# line with drone/cargo and qty
|
||||
droneAmount = modExtra[1].strip()
|
||||
modName = modExtra[0].strip()
|
||||
else:
|
||||
# line with just module
|
||||
modName = modExtra[0].strip()
|
||||
|
||||
try:
|
||||
# get item information. If we are on a Drone/Cargo line, throw out cargo
|
||||
item = db.getItem(modName, eager="group.category")
|
||||
except:
|
||||
try:
|
||||
item = db.getItem(modAmmo[0], eager="group.category")
|
||||
except:
|
||||
if len(modExtra) == 2 and item.category.name != "Drone":
|
||||
continue
|
||||
except:
|
||||
# if no data can be found (old names)
|
||||
continue
|
||||
|
||||
if item.category.name == "Drone":
|
||||
droneAmount = int(droneAmount) if droneAmount is not None else 1
|
||||
@@ -249,7 +269,9 @@ class Fit(object):
|
||||
continue
|
||||
if ammoName:
|
||||
try:
|
||||
m.charge = db.getItem(ammoName)
|
||||
ammo = db.getItem(ammoName)
|
||||
if m.isValidCharge(ammo) and m.charge is None:
|
||||
m.charge = ammo
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -442,9 +464,7 @@ class Fit(object):
|
||||
f.modules.append(m)
|
||||
except KeyboardInterrupt:
|
||||
continue
|
||||
|
||||
fits.append(f)
|
||||
|
||||
fits.append(f)
|
||||
|
||||
return fits
|
||||
|
||||
@@ -496,18 +516,28 @@ class Fit(object):
|
||||
def exportDna(self):
|
||||
dna = str(self.shipID)
|
||||
mods = OrderedDict()
|
||||
charges = OrderedDict()
|
||||
for mod in self.modules:
|
||||
if not mod.isEmpty:
|
||||
if not mod.itemID in mods:
|
||||
mods[mod.itemID] = 0
|
||||
mods[mod.itemID] += 1
|
||||
|
||||
if mod.charge:
|
||||
if not mod.chargeID in charges:
|
||||
charges[mod.chargeID] = 0
|
||||
# `or 1` because some charges (ie scripts) are without qty
|
||||
charges[mod.chargeID] += mod.numShots or 1
|
||||
|
||||
for mod in mods:
|
||||
dna += ":{0};{1}".format(mod, mods[mod])
|
||||
|
||||
for drone in self.drones:
|
||||
dna += ":{0};{1}".format(drone.itemID, drone.amount)
|
||||
|
||||
for charge in charges:
|
||||
dna += ":{0};{1}".format(charge, charges[charge])
|
||||
|
||||
return dna + "::"
|
||||
|
||||
@classmethod
|
||||
@@ -515,7 +545,6 @@ class Fit(object):
|
||||
doc = xml.dom.minidom.Document()
|
||||
fittings = doc.createElement("fittings")
|
||||
doc.appendChild(fittings)
|
||||
|
||||
for fit in fits:
|
||||
fitting = doc.createElement("fitting")
|
||||
fitting.setAttribute("name", fit.name)
|
||||
@@ -527,6 +556,7 @@ class Fit(object):
|
||||
shipType.setAttribute("value", fit.ship.item.name)
|
||||
fitting.appendChild(shipType)
|
||||
|
||||
charges = {}
|
||||
slotNum = {}
|
||||
for module in fit.modules:
|
||||
if module.isEmpty:
|
||||
@@ -543,6 +573,12 @@ class Fit(object):
|
||||
hardware.setAttribute("slot", "%s slot %d" % (slotName, slotId))
|
||||
fitting.appendChild(hardware)
|
||||
|
||||
if module.charge:
|
||||
if not module.charge.name in charges:
|
||||
charges[module.charge.name] = 0
|
||||
# `or 1` because some charges (ie scripts) are without qty
|
||||
charges[module.charge.name] += module.numShots or 1
|
||||
|
||||
for drone in fit.drones:
|
||||
hardware = doc.createElement("hardware")
|
||||
hardware.setAttribute("qty", "%d" % drone.amount)
|
||||
@@ -550,13 +586,19 @@ class Fit(object):
|
||||
hardware.setAttribute("type", drone.item.name)
|
||||
fitting.appendChild(hardware)
|
||||
|
||||
for name, qty in charges.items():
|
||||
hardware = doc.createElement("hardware")
|
||||
hardware.setAttribute("qty", "%d" % qty)
|
||||
hardware.setAttribute("slot", "cargo")
|
||||
hardware.setAttribute("type", name)
|
||||
fitting.appendChild(hardware)
|
||||
|
||||
for cargo in fit.cargo:
|
||||
hardware = doc.createElement("hardware")
|
||||
hardware.setAttribute("qty", "%d" % cargo.amount)
|
||||
hardware.setAttribute("slot", "cargo")
|
||||
hardware.setAttribute("type", cargo.item.name)
|
||||
fitting.appendChild(hardware)
|
||||
|
||||
return doc.toprettyxml()
|
||||
|
||||
@reconstructor
|
||||
|
||||
@@ -569,7 +569,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
context = ("module",)
|
||||
projected = False
|
||||
|
||||
if self.charge is not None and not projected:
|
||||
if self.charge is not None:
|
||||
for effect in self.charge.effects.itervalues():
|
||||
if effect.runTime == runTime:
|
||||
effect.handler(fit, self, ("moduleCharge",))
|
||||
|
||||
@@ -22,6 +22,10 @@ from eos.effectHandlerHelpers import HandledItem
|
||||
|
||||
class Ship(ItemAttrShortcut, HandledItem):
|
||||
def __init__(self, item):
|
||||
|
||||
if item.category.name != "Ship":
|
||||
raise ValueError('Passed item "%s" (category: (%s)) is not under Ship category'%(item.name, item.category.name))
|
||||
|
||||
self.__item = item
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
if not isinstance(item, int):
|
||||
|
||||
@@ -99,6 +99,9 @@ if __name__ == "__main__":
|
||||
# We don't care about some kind of rows, filter it out if so
|
||||
if not isIgnored(jsonName, row):
|
||||
instance = tables[jsonName]()
|
||||
# fix for issue 80
|
||||
if jsonName is "icons" and "res:/UI/Texture/Icons/" in str(row['iconFile']):
|
||||
row['iconFile'] = row['iconFile'].replace('res:/UI/Texture/Icons/','').replace('.png','')
|
||||
for k, v in row.iteritems():
|
||||
setattr(instance, fieldMap.get(k, k), v)
|
||||
|
||||
|
||||
@@ -19,8 +19,16 @@
|
||||
import config
|
||||
|
||||
versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion)
|
||||
license = "pyfa is released under GNU GPLv3"
|
||||
licenseLocation = "gpl.txt"
|
||||
developers = ("\n cncfanatics \t(Sakari Orisi)\n" , " DarkPhoenix \t(Kadesh Priestess)\n", " Darriele \t(Darriele)")
|
||||
credits = (("Entity (Entity) \t\tCapacitor calculations / EVEAPI python lib / Reverence"), ("Aurora \t\tMaths"), ("Corollax (Aamrr) \tVarious EOS/pyfa improvements"))
|
||||
description = "Pyfa (the Python Fitting Assistant) is a standalone application able to create and simulate fittings for EVE-Online SciFi MMORPG with a very high degree of accuracy.\nPyfa can be virtually ran on all platforms where python and wxwidgets are supported.\n\n\nAll EVE-Online related materials are property of CCP hf.\n\nSilk Icons Set by famfamfam.com released under Creative Commons Attribution 2.5 License\n\nFat Cow Icons by fatcow.com released under Creative Commons Attribution 3.0 License"
|
||||
licenses = (
|
||||
"pyfa is released under GNU GPLv3 - see included gpl.txt",
|
||||
"All EVE-Online related materials are property of CCP hf.",
|
||||
"Silk Icons Set by famfamfam.com - Creative Commons Attribution 2.5 License",
|
||||
"Fat Cow Icons by fatcow.com - Creative Commons Attribution 3.0 License"
|
||||
)
|
||||
developers = ("blitzmann \t(Sable Blitzmann)", "cncfanatics \t(Sakari Orisi)" , "DarkPhoenix \t(Kadesh Priestess) (Project Lead)", "Darriele \t(Darriele)")
|
||||
credits = ("Entity (Entity) \t\tCapacitor calculations / EVEAPI python lib / Reverence", "Aurora \t\t\tMaths", "Corollax (Aamrr) \tVarious EOS / pyfa improvements")
|
||||
description = (
|
||||
"Pyfa (the Python Fitting Assistant) is an open-source standalone application able to "
|
||||
"create and simulate fittings for EVE-Online SciFi MMORPG with a very high degree of "
|
||||
"accuracy. Pyfa can run on all platforms where Python and wxWidgets are supported."
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gui.contextMenu import ContextMenu
|
||||
import gui.mainFrame
|
||||
import service
|
||||
@@ -112,7 +113,7 @@ class ModuleAmmoPicker(ContextMenu):
|
||||
|
||||
def addSeperator(self, m, text):
|
||||
id = wx.NewId()
|
||||
m.Append(id, "--- %s ---" % text)
|
||||
m.Append(id, u'─ %s ─' % text)
|
||||
m.Enable(id, False)
|
||||
|
||||
def getSubMenu(self, context, selection, menu, i):
|
||||
@@ -132,6 +133,11 @@ class ModuleAmmoPicker(ContextMenu):
|
||||
sub = None
|
||||
self.charges.sort(key=self.turretSorter)
|
||||
for charge in self.charges:
|
||||
# fix issue 71 - will probably have to change if CCP adds more Orbital ammo
|
||||
if "Orbital" in charge.name:
|
||||
item = self.addCharge(m, charge)
|
||||
items.append(item)
|
||||
continue
|
||||
currBase = charge.name.rsplit()[-2:]
|
||||
currRange = charge.getAttribute("weaponRangeMultiplier")
|
||||
if nameBase is None or range != currRange or nameBase != currBase:
|
||||
@@ -156,6 +162,7 @@ class ModuleAmmoPicker(ContextMenu):
|
||||
|
||||
if sub is not None:
|
||||
self.addSeperator(sub, "More Damage")
|
||||
|
||||
for item in items:
|
||||
m.AppendItem(item)
|
||||
|
||||
|
||||
@@ -233,10 +233,23 @@ class FittingView(d.Display):
|
||||
event.Skip()
|
||||
|
||||
def fitRemoved(self, event):
|
||||
'''If fit is removed and active, the page is deleted.
|
||||
We also refresh the fit of the new current page in case
|
||||
delete fit caused change in stats (projected)
|
||||
'''
|
||||
fitID = event.fitID
|
||||
|
||||
if fitID == self.getActiveFit():
|
||||
self.parent.DeletePage(self.parent.GetPageIndex(self))
|
||||
|
||||
|
||||
try:
|
||||
# Sometimes there is no active page after deletion, hence the try block
|
||||
cFit = service.Fit.getInstance()
|
||||
cFit.refreshFit(self.getActiveFit())
|
||||
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID))
|
||||
except wx._core.PyDeadObjectError:
|
||||
pass
|
||||
|
||||
event.Skip()
|
||||
|
||||
def fitRenamed(self, event):
|
||||
|
||||
@@ -26,9 +26,13 @@ import wx.lib.mixins.listctrl as listmix
|
||||
import wx.html
|
||||
from eos.types import Ship, Module, Skill, Booster, Implant, Drone
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
from collections import OrderedDict
|
||||
import service
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from gui.utils.compat import OrderedDict
|
||||
|
||||
class ItemStatsDialog(wx.Dialog):
|
||||
counter = 0
|
||||
def __init__(self, victim, fullContext=None, pos = wx.DefaultPosition, size = wx.DefaultSize, maximized = False):
|
||||
|
||||
@@ -243,14 +243,12 @@ class MainFrame(wx.Frame):
|
||||
info = wx.AboutDialogInfo()
|
||||
info.Name = "pyfa"
|
||||
info.Version = gui.aboutData.versionString
|
||||
info.Description = wordwrap(gui.aboutData.description + "\n\n\nDevelopers: " +
|
||||
"".join(gui.aboutData.developers) +
|
||||
"\n\nAdditional credits:\n " +
|
||||
"\n ".join(gui.aboutData.credits)
|
||||
+ "\n\nLicense: " +
|
||||
gui.aboutData.license +
|
||||
" - see included " +
|
||||
gui.aboutData.licenseLocation +
|
||||
info.Description = wordwrap(gui.aboutData.description + "\n\nDevelopers:\n\t" +
|
||||
"\n\t".join(gui.aboutData.developers) +
|
||||
"\n\nAdditional credits:\n\t" +
|
||||
"\n\t".join(gui.aboutData.credits) +
|
||||
"\n\nLicenses:\n\t" +
|
||||
"\n\t".join(gui.aboutData.licenses) +
|
||||
"\n\nPython: \t" + sys.version +
|
||||
"\nwxPython: \t" + wx.__version__ +
|
||||
"\nSQLAlchemy: \t" + sqlalchemy.__version__,
|
||||
@@ -364,7 +362,7 @@ class MainFrame(wx.Frame):
|
||||
# Export HTML
|
||||
self.Bind(wx.EVT_MENU, self.exportHtml, id=menuBar.exportHtmlId)
|
||||
# Preference dialog
|
||||
self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id = menuBar.preferencesId)
|
||||
self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id=wx.ID_PREFERENCES)
|
||||
# User guide
|
||||
self.Bind(wx.EVT_MENU, self.goWiki, id = menuBar.wikiId)
|
||||
# EVE Forums
|
||||
@@ -384,6 +382,7 @@ class MainFrame(wx.Frame):
|
||||
self.additionstab2 = wx.NewId()
|
||||
self.additionstab3 = wx.NewId()
|
||||
self.additionstab4 = wx.NewId()
|
||||
self.additionstab5 = wx.NewId()
|
||||
|
||||
# Close Page
|
||||
self.Bind(wx.EVT_MENU, self.CloseCurrentPage, id=self.closePageId)
|
||||
@@ -396,6 +395,7 @@ class MainFrame(wx.Frame):
|
||||
self.Bind(wx.EVT_MENU, self.AdditionsTabSelect, id = self.additionstab2)
|
||||
self.Bind(wx.EVT_MENU, self.AdditionsTabSelect, id = self.additionstab3)
|
||||
self.Bind(wx.EVT_MENU, self.AdditionsTabSelect, id = self.additionstab4)
|
||||
self.Bind(wx.EVT_MENU, self.AdditionsTabSelect, id = self.additionstab5)
|
||||
|
||||
actb = [(wx.ACCEL_CTRL, ord('T'), self.addPageId),
|
||||
(wx.ACCEL_CMD, ord('T'), self.addPageId),
|
||||
@@ -416,10 +416,12 @@ class MainFrame(wx.Frame):
|
||||
(wx.ACCEL_CTRL, ord('2'), self.additionstab2),
|
||||
(wx.ACCEL_CTRL, ord('3'), self.additionstab3),
|
||||
(wx.ACCEL_CTRL, ord('4'), self.additionstab4),
|
||||
(wx.ACCEL_CTRL, ord('5'), self.additionstab5),
|
||||
(wx.ACCEL_CMD, ord('1'), self.additionstab1),
|
||||
(wx.ACCEL_CMD, ord('2'), self.additionstab2),
|
||||
(wx.ACCEL_CMD, ord('3'), self.additionstab3),
|
||||
(wx.ACCEL_CMD, ord('4'), self.additionstab4)
|
||||
(wx.ACCEL_CMD, ord('4'), self.additionstab4),
|
||||
(wx.ACCEL_CMD, ord('5'), self.additionstab5)
|
||||
]
|
||||
atable = wx.AcceleratorTable(actb)
|
||||
self.SetAcceleratorTable(atable)
|
||||
@@ -434,7 +436,8 @@ class MainFrame(wx.Frame):
|
||||
selTab = 2
|
||||
if event.GetId() == self.additionstab4:
|
||||
selTab = 3
|
||||
|
||||
if event.GetId() == self.additionstab5:
|
||||
selTab = 4
|
||||
if selTab is not None:
|
||||
self.additionsPane.notebook.SetSelection(selTab)
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ class MainMenuBar(wx.MenuBar):
|
||||
self.exportSkillsNeededId = wx.NewId()
|
||||
self.importCharacterId = wx.NewId()
|
||||
self.exportHtmlId = wx.NewId()
|
||||
self.preferencesId = wx.NewId()
|
||||
self.wikiId = wx.NewId()
|
||||
self.forumId = wx.NewId()
|
||||
|
||||
@@ -59,7 +58,6 @@ class MainMenuBar(wx.MenuBar):
|
||||
fileMenu.AppendSeparator()
|
||||
fileMenu.Append(wx.ID_EXIT)
|
||||
|
||||
|
||||
# Edit menu
|
||||
editMenu = wx.Menu()
|
||||
self.Append(editMenu, "&Edit")
|
||||
@@ -67,7 +65,6 @@ class MainMenuBar(wx.MenuBar):
|
||||
#editMenu.Append(wx.ID_UNDO)
|
||||
#editMenu.Append(wx.ID_REDO)
|
||||
|
||||
|
||||
copyText = "&To Clipboard" + ("\tCTRL+C" if 'wxMSW' in wx.PlatformInfo else "")
|
||||
pasteText = "&From Clipboard" + ("\tCTRL+V" if 'wxMSW' in wx.PlatformInfo else "")
|
||||
editMenu.Append(wx.ID_COPY, copyText, "Export a fit to the clipboard")
|
||||
@@ -89,13 +86,9 @@ class MainMenuBar(wx.MenuBar):
|
||||
graphFrameItem.SetBitmap(bitmapLoader.getBitmap("graphs_small", "icons"))
|
||||
windowMenu.AppendItem(graphFrameItem)
|
||||
|
||||
#=======================================================================
|
||||
# DISABLED FOR RC2 Release
|
||||
#
|
||||
preferencesItem = wx.MenuItem(windowMenu, self.preferencesId, "Preferences\tCTRL+P")
|
||||
preferencesItem = wx.MenuItem(windowMenu, wx.ID_PREFERENCES, "Preferences\tCTRL+P")
|
||||
preferencesItem.SetBitmap(bitmapLoader.getBitmap("preferences_small", "icons"))
|
||||
windowMenu.AppendItem(preferencesItem)
|
||||
#=======================================================================
|
||||
|
||||
# Help menu
|
||||
helpMenu = wx.Menu()
|
||||
@@ -108,8 +101,6 @@ class MainMenuBar(wx.MenuBar):
|
||||
if config.debug:
|
||||
helpMenu.Append( self.mainFrame.widgetInspectMenuID, "Open Widgets Inspect tool", "Open Widgets Inspect tool")
|
||||
|
||||
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
|
||||
def fitChanged(self, event):
|
||||
|
||||
@@ -132,20 +132,28 @@ class exportHtmlThread(threading.Thread):
|
||||
if len(fits) > 0:
|
||||
groupFits += len(fits)
|
||||
|
||||
# Ship group header
|
||||
HTMLship = (
|
||||
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" data-corners="false">\n'
|
||||
' <h2>' + ship.name + ' <span class="ui-li-count">'+str(len(fits))+'</span></h2>\n'
|
||||
' <ul data-role="listview" data-shadow="false" data-inset="true" data-corners="false">\n')
|
||||
|
||||
for fit in fits:
|
||||
if len(fits) == 1:
|
||||
if self.stopRunning:
|
||||
return;
|
||||
return
|
||||
fit = fits[0]
|
||||
dnaFit = sFit.exportDna(fit[0])
|
||||
HTMLship += ' <li><a data-dna="' + dnaFit + '" target="_blank">' + fit[1] + '</a></li>\n'
|
||||
HTMLgroup += (
|
||||
' <li><a data-dna="' + dnaFit + '" target="_blank">' + ship.name + ": " + fit[1] + '</a></li>\n')
|
||||
else:
|
||||
# Ship group header
|
||||
HTMLship = (
|
||||
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" data-corners="false">\n'
|
||||
' <h2>' + ship.name + ' <span class="ui-li-count">'+str(len(fits))+'</span></h2>\n'
|
||||
' <ul data-role="listview" data-shadow="false" data-inset="true" data-corners="false">\n')
|
||||
|
||||
HTMLgroup += HTMLship + (' </ul>\n'
|
||||
' </li>\n')
|
||||
for fit in fits:
|
||||
if self.stopRunning:
|
||||
return
|
||||
dnaFit = sFit.exportDna(fit[0])
|
||||
HTMLship += ' <li><a data-dna="' + dnaFit + '" target="_blank">' + fit[1] + '</a></li>\n'
|
||||
|
||||
HTMLgroup += HTMLship + (' </ul>\n'
|
||||
' </li>\n')
|
||||
if groupFits > 0:
|
||||
# Market group header
|
||||
HTML += (
|
||||
|
||||
@@ -162,6 +162,8 @@ class Fit(object):
|
||||
fit = eos.db.getFit(fitID)
|
||||
sFlt = Fleet.getInstance()
|
||||
sFlt.removeAssociatedFleetData(fit)
|
||||
self.removeProjectedData(fitID)
|
||||
|
||||
eos.db.remove(fit)
|
||||
|
||||
def copyFit(self, fitID):
|
||||
@@ -177,7 +179,15 @@ class Fit(object):
|
||||
fit = eos.db.getFit(fitID)
|
||||
fit.clear()
|
||||
return fit
|
||||
|
||||
|
||||
def removeProjectedData(self, fitID):
|
||||
'''Removes projection relation from ships that have fitID as projection. See GitHub issue #90'''
|
||||
fit = eos.db.getFit(fitID)
|
||||
fits = eos.db.getProjectedFits(fitID)
|
||||
|
||||
for projectee in fits:
|
||||
projectee.projectedFits.remove(fit)
|
||||
|
||||
def toggleFactorReload(self, fitID):
|
||||
if fitID is None:
|
||||
return None
|
||||
|
||||
BIN
staticdata/icons/icon108_5.png
Normal file
|
After Width: | Height: | Size: 756 B |
BIN
staticdata/icons/icon113_64_1.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
staticdata/icons/icon113_64_2.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
staticdata/icons/icon113_64_3.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
staticdata/icons/icon53_64_16.png
Normal file
|
After Width: | Height: | Size: 914 B |
BIN
staticdata/icons/icon94_64_9.png
Normal file
|
After Width: | Height: | Size: 698 B |
BIN
staticdata/icons/iconMarketIcon_16px_Amarr.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
staticdata/icons/iconMarketIcon_16px_Caldari.png
Normal file
|
After Width: | Height: | Size: 852 B |
BIN
staticdata/icons/iconMarketIcon_16px_Gallente.png
Normal file
|
After Width: | Height: | Size: 794 B |
BIN
staticdata/icons/iconMarketIcon_16px_Minmatar.png
Normal file
|
After Width: | Height: | Size: 776 B |