NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

ledgerPanel.py (20239B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\ledger\ledgerPanel.py
      2 import evetypes
      3 import telemetry
      4 import threadutils
      5 import uthread
      6 from caching.memoize import Memoize
      7 from carbonui.button.const import HEIGHT_NORMAL
      8 from carbonui.control.combo import Combo
      9 from carbonui.control.dragResizeCont import DragResizeCont
     10 from carbonui.primitives.container import Container
     11 import carbonui.const as uiconst
     12 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     13 from carbonui.primitives.fill import Fill
     14 from carbonui.primitives.line import Line
     15 from carbonui.util.sortUtil import SortListOfTuples
     16 from carbonui.button.group import ButtonGroup
     17 from eve.client.script.ui.control.dateSinglelineEdit import DateRangePicker
     18 from eve.client.script.ui.control.eveLabel import EveLabelMedium, EveLabelLarge
     19 from eve.client.script.ui.control.eveScroll import Scroll
     20 import eve.client.script.ui.shared.ledger.ledgerUtil as ledgerUtil
     21 from eve.client.script.ui.control.filter import OptionObject, FilterController, Filter
     22 from eve.client.script.ui.control.infoIcon import MoreInfoIcon
     23 from eve.client.script.ui.quickFilter import QuickFilterEdit
     24 from eve.client.script.ui.shared.fitting.fittingUtil import EatSignalChangingErrors
     25 from eve.client.script.ui.shared.ledger.ledgerEntry import GetLedgerEntriesPersonal, GetLedgerEntriesCorp
     26 from eve.client.script.ui.shared.ledger.ledgerGraph import LedgerGraphCont
     27 from eve.client.script.ui.shared.ledger.ledgerMinimap import LedgerMinimap, MiniMapSliderController
     28 from eveservices.ledger import GetLedgerService
     29 from localization import GetByLabel
     30 from signals.signalUtil import ChangeSignalConnect
     31 import blue
     32 from utillib import KeyVal
     33 OPTION_TYPEID = 1
     34 OPTION_ITEMID = 2
     35 OPTION_TYPE_GROUPINGID = 3
     36 
     37 class LedgerPanelPersonal(Container):
     38     __notifyevents__ = ['OnMiningLedgerGraphSettingChanged']
     39     default_align = uiconst.TOALL
     40 
     41     def ApplyAttributes(self, attributes):
     42         self.filterController = None
     43         self.currentNormalOreGroupIDs = set()
     44         self.currentMoonTypeIDsByGroupID = set()
     45         self.currentPersonalDataVersion = -1
     46         Container.ApplyAttributes(self, attributes)
     47         addInfoIcon = attributes.addInfoIcon
     48         if addInfoIcon:
     49             self.AddMoreInfoIcon()
     50         self.graphParent = DragResizeCont(name='scrollCont', parent=self, align=uiconst.TOTOP_PROP, minSize=200, maxSize=0.6, defaultSize=250, settingsID='ledgerPanel_left')
     51         Line(parent=self.graphParent.dragArea, align=uiconst.TOBOTTOM, opacity=0.08)
     52         Line(parent=self.graphParent.dragArea, align=uiconst.TOTOP, opacity=0.08)
     53         self.bottomCont = Container(name='bottomCont', parent=self, align=uiconst.TOALL, clipChildren=True, padTop=16)
     54         self.filterCont = ContainerAutoSize(name='filterCont', parent=self.bottomCont, align=uiconst.TOTOP)
     55         self.ConstructFilterCont()
     56         self.scrollCont = Container(name='scrollCont', parent=self.bottomCont, align=uiconst.TOALL)
     57         EveLabelLarge(parent=self.scrollCont, text=GetByLabel('UI/Ledger/LogsHeader'), align=uiconst.TOTOP, padTop=8)
     58         self.ChangeSignalConnection()
     59         self.AddGraphs()
     60         self.AddCopyBtns()
     61         self.scroll = Scroll(parent=self.scrollCont, padding=(0, 4, 0, 0), id='ledgerPanelPersonal')
     62         self.scroll.ApplyTabstopsToNode = self.ScrollApplyTabstopsToNode
     63         uthread.new(self.LoadContent)
     64         sm.RegisterNotify(self)
     65 
     66     def OnTabSelect(self):
     67         self.LoadContent()
     68 
     69     def LoadContent(self):
     70         self.LoadOreFilter()
     71         self.ReloadContent()
     72 
     73     def ScrollApplyTabstopsToNode(self, node, fromWhere = ''):
     74         Scroll.ApplyTabstopsToNode(self.scroll, node, fromWhere)
     75         if node.panel and node.tabs:
     76             node.panel.UpdateLegendFillPos(node.tabs[0])
     77 
     78     def ConstructFilterCont(self):
     79         EveLabelLarge(parent=self.filterCont, text=GetByLabel('UI/Ledger/FiltersHeader'), align=uiconst.TOTOP)
     80         self.innerFilterCont = Container(name='innerFilterCont', parent=self.filterCont, align=uiconst.TOTOP, height=HEIGHT_NORMAL, padTop=4)
     81         startTime, endTime = ledgerUtil.GetMiniMapRange()
     82         self.sliderController = MiniMapSliderController(startTime, endTime)
     83         fromTime, toTime = self.sliderController.GetVisibleRange()
     84         labelPaths = ['UI/Ledger/DateRange', 'UI/Ledger/DateRangeTo']
     85         DateRangePicker(name='DateRangePicker', parent=self.innerFilterCont, pos=(150, 4, 50, 0), fromTime=fromTime, toTime=toTime, sliderController=self.sliderController, labelPaths=labelPaths)
     86         self.filterController = FilterController('ledgerWnd_personal_oreType', [], doSortChildren=False)
     87         Filter(name='oreFilter', parent=self.innerFilterCont, filterText=GetByLabel('UI/Ledger/OreTypeFilter'), filterController=self.filterController, columns=1, align=uiconst.CENTERLEFT, maxSize=300)
     88         EveLabelMedium(parent=self.filterCont, align=uiconst.TOTOP, text=GetByLabel('UI/Ledger/DateSelectionText'), padTop=8)
     89         minimapCont = Container(name='miniMapCont', parent=self.filterCont, align=uiconst.TOTOP, height=60, top=0, padTop=4)
     90         minimapCont.isTabStop = True
     91         ledgerMinimap = LedgerMinimap(parent=minimapCont, sliderController=self.sliderController)
     92         ledgerMinimap.LoadMiniMap(ledgerUtil.GetDataForPersonaMinimap())
     93         Fill(bgParent=minimapCont, color=(1, 1, 1, 0.05))
     94 
     95     def LoadOreFilter(self):
     96         data, self.currentPersonalDataVersion = GetLedgerService().GetPersonalData()
     97         self._LoadOreFilterData(data)
     98 
     99     def _LoadOreFilterData(self, data):
    100         options = GetOreOptionsFromData(data)
    101         self.filterController.SetOptions(options)
    102 
    103     def LoadOreFilterIfNeeded(self, data):
    104         normalOreGroupIDs, moonTypeIDsByGroupID = ledgerUtil.GetGroupingsForOreFromData(data)
    105         if self.currentNormalOreGroupIDs == normalOreGroupIDs and self.currentMoonTypeIDsByGroupID == set(moonTypeIDsByGroupID.keys()):
    106             return
    107         self.currentNormalOreGroupIDs = normalOreGroupIDs
    108         self.currentMoonTypeIDsByGroupID = set(moonTypeIDsByGroupID.keys())
    109         self._LoadOreFilterData(data)
    110 
    111     def AddCopyBtns(self):
    112         self.btnGroup = ButtonGroup(parent=self.scrollCont, idx=0)
    113         text = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboard')
    114         self.btnGroup.AddButton(text, self.CopyToClipboard, ())
    115 
    116     def OnFiltersChanged(self, controller):
    117         self.ReloadContent()
    118 
    119     def AddGraphs(self):
    120         EveLabelLarge(parent=self.graphParent, text=GetByLabel('UI/Ledger/GraphsHeader'), align=uiconst.TOTOP)
    121         self.graphCont = LedgerGraphCont(parent=self.graphParent, padBottom=8)
    122 
    123     def OnMiningLedgerGraphSettingChanged(self):
    124         self.ReloadContent()
    125 
    126     @threadutils.throttled(0.5)
    127     def ReloadContent(self):
    128         visibleRange = self.sliderController.GetVisibleRange()
    129         data, personalDataVersion = GetLedgerService().GetPersonalData()
    130         if self.currentPersonalDataVersion != personalDataVersion:
    131             self.LoadOreFilterIfNeeded(data)
    132             self.currentPersonalDataVersion = personalDataVersion
    133         data = self.FilterOutData(data)
    134         self.LoadScroll(data, visibleRange)
    135         self.graphCont.UpdateGraphFromRawData(data, *visibleRange)
    136 
    137     def LoadScroll(self, data, visibleRange):
    138         contentList = GetLedgerEntriesPersonal(data, *visibleRange)
    139         self.scroll.Load(contentList=contentList, headers=ledgerUtil.SCROLL_HEADERS_PERSONAL, noContentHint=GetByLabel('UI/Ledger/NoLogsToShow'))
    140 
    141     def OnOreFilterChanged(self, *args):
    142         self.ReloadContent()
    143 
    144     def FilterOutData(self, dataList):
    145         newDataList = []
    146         for each in dataList:
    147             if self.IsFilteredOut(each):
    148                 continue
    149             newDataList.append(each)
    150 
    151         return newDataList
    152 
    153     def IsFilteredOut(self, info):
    154         isFilterActive = self.filterController.IsActive()
    155         if not isFilterActive:
    156             return False
    157         selectedOptions = self.filterController.GetSelectedOptions()
    158         groupsSelected = {x[1] for x in selectedOptions if x[0] == OPTION_TYPE_GROUPINGID}
    159         typesSelected = filter(None, {x[1] for x in selectedOptions if x[0] == OPTION_TYPEID})
    160         if evetypes.GetGroupID(info.typeID) in groupsSelected or ledgerUtil.GetBasicOreForTypeID(info.typeID) in typesSelected:
    161             return False
    162         return True
    163 
    164     def ChangeSignalConnection(self, connect = True):
    165         signalAndCallback = [(self.sliderController.on_change, self.ReloadContent), (self.filterController.on_filter_changed, self.OnFiltersChanged)]
    166         ChangeSignalConnect(signalAndCallback, connect)
    167 
    168     def CopyToClipboard(self, *args):
    169         extraColumns = [GetByLabel('UI/Ledger/OreTypeID'), GetByLabel('UI/Ledger/SolarSystemID')]
    170         allLines = ['\t'.join(ledgerUtil.SCROLL_HEADERS_PERSONAL + extraColumns)]
    171         for eachData in self.scroll.GetNodes():
    172             text = '\t'.join([eachData.formattedText['date'],
    173              eachData.formattedText['typeName'],
    174              unicode(eachData.formattedText['qty']),
    175              unicode(eachData.formattedText['qtyWasted']),
    176              unicode(eachData.formattedText['volume']),
    177              unicode(eachData.formattedText['volumeWasted']),
    178              unicode(eachData.formattedText['estPrice']),
    179              unicode(eachData.formattedText['estPriceWasted']),
    180              unicode(eachData.formattedText['locationName']),
    181              unicode(eachData.ledgerData.typeID),
    182              unicode(eachData.ledgerData.solarsystemID)])
    183             allLines.append(text)
    184 
    185         allText = '\r\n'.join(allLines)
    186         if allText:
    187             blue.pyos.SetClipboardData(allText)
    188 
    189     def AddMoreInfoIcon(self):
    190         moreinfoicon = MoreInfoIcon(left=2, top=-1, parent=self, idx=0, align=uiconst.TOPRIGHT)
    191         moreinfoicon.hint = GetByLabel('UI/Ledger/PersonalLedgerCacheHint')
    192 
    193     def Close(self):
    194         with EatSignalChangingErrors(errorMsg='LedgerPanelPersonal'):
    195             self.ChangeSignalConnection(connect=False)
    196         Container.Close(self)
    197 
    198 
    199 class LedgerPanelCorp(Container):
    200     default_align = uiconst.TOALL
    201 
    202     def ApplyAttributes(self, attributes):
    203         Container.ApplyAttributes(self, attributes)
    204         self.oreTypeFilterController = FilterController('ledgerWnd_corp_oreType', ())
    205         self.corpFilterController = FilterController('ledgerWnd_corp_corp', ())
    206         self.filterCont = Container(parent=self, align=uiconst.TOTOP, height=30, padLeft=4, padRight=4)
    207         self.rangeCont = Container(parent=self, align=uiconst.TOTOP, height=70, padLeft=4, padRight=4)
    208         self.AddComboFilters()
    209         self.AddRangeSlider()
    210         self.AddCopyBtns()
    211         self.scroll = Scroll(parent=self, padding=4, id='ledgerPanelCorp')
    212         self.scroll.LoadContent(noContentHint=GetByLabel('UI/ScienceAndIndustry/ScienceAndIndustryWindow/FetchingData'))
    213         uthread.new(self.PopulateStructureCombo)
    214         self.ChangeSignalConnection()
    215 
    216     def AddComboFilters(self):
    217         structureOptions = []
    218         self.structureCombo = Combo(parent=self.filterCont, name='ledger_corp_oreFilter', options=structureOptions, prefskey='ledger_corp_oreFilter', callback=self.OnStructureChanged, align=uiconst.CENTERLEFT, width=280)
    219         left = self.structureCombo.left + self.structureCombo.width + 16
    220         self.oreFilter = Filter(name='oreFilter', parent=self.filterCont, filterText=GetByLabel('UI/Ledger/OreTypeFilter'), filterController=self.oreTypeFilterController, columns=1, align=uiconst.CENTERLEFT, left=left, maxSize=300)
    221         left = self.oreFilter.left + self.oreFilter.width + 16
    222         self.corpFilter = Filter(name='corpFilter', parent=self.filterCont, filterText=GetByLabel('UI/Ledger/CorpFilter'), filterController=self.corpFilterController, columns=1, align=uiconst.CENTERLEFT, left=left, maxSize=300)
    223         self.filterInput = QuickFilterEdit(name='filterInput', parent=self.filterCont, setvalue='', hintText=GetByLabel('UI/Inventory/Filter'), maxLength=64, pos=(6, 0, 100, 0), align=uiconst.CENTERRIGHT, OnClearFilter=self.LoadScroll, isCharacterField=True)
    224         self.filterInput.OnReturn = self.LoadScroll
    225         self.filterInput.ReloadFunction = self.LoadScroll
    226 
    227     def AddRangeSlider(self):
    228         startTime, endTime = ledgerUtil.GetMiniMapRange()
    229         self.sliderController = MiniMapSliderController(startTime, endTime)
    230         fromTime, toTime = self.sliderController.GetVisibleRange()
    231         labelPaths = ['UI/Ledger/DateRange', 'UI/Ledger/DateRangeTo']
    232         DateRangePicker(name='DateRangePicker', parent=self.rangeCont, fromTime=fromTime, toTime=toTime, sliderController=self.sliderController, labelPaths=labelPaths)
    233         minimapCont = Container(name='minimapCont', parent=self.rangeCont, align=uiconst.TOTOP, height=40, top=24)
    234         minimapCont.isTabStop = True
    235         self.ledgerMinimap = LedgerMinimap(parent=minimapCont, sliderController=self.sliderController)
    236         Fill(bgParent=minimapCont, color=(1, 1, 1, 0.05))
    237 
    238     def PopulateStructureCombo(self):
    239         select = settings.user.ui.Get(self.structureCombo.prefskey, None)
    240         structureOptions = self.GetStructureComboOptions()
    241         self.structureCombo.LoadOptions(structureOptions, select)
    242         structureIdSelected = self.structureCombo.GetValue()
    243         if structureIdSelected:
    244             self.LoadFiltersAndScroll(structureIdSelected)
    245 
    246     def LoadFiltersAndScroll(self, structureIdSelected):
    247         data = self.GetCorpData(structureIdSelected)
    248         self.LoadExtraFilters(data)
    249         self.LoadScroll()
    250 
    251     def AddCopyBtns(self):
    252         self.btnGroup = ButtonGroup(parent=self, idx=0)
    253         text = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboard')
    254         self.btnGroup.AddButton(text, self.CopyToClipboard, ())
    255 
    256     def GetStructureComboOptions(self):
    257         allStructuresByID, allSolarSystemIDs = GetLedgerService().GetStructuresForCorpData()
    258         options = []
    259         for eachItemID, eachItemInfo in allStructuresByID.iteritems():
    260             name = eachItemInfo.itemName
    261             options.append((name.lower(), (name, eachItemID)))
    262 
    263         options = SortListOfTuples(options)
    264         return options
    265 
    266     def LoadExtraFilters(self, data):
    267         allCorps, allCharIDs = ledgerUtil.GetGroupsForData(data)
    268         toPrime = allCorps.union(allCharIDs.union(allCorps))
    269         cfg.eveowners.Prime(toPrime)
    270         corpOptions = [ (cfg.eveowners.Get(x).name, x) for x in allCorps ]
    271         corpOptions.sort(key=lambda x: x[0])
    272         oreFilterOptions = GetOreOptionsFromData(data)
    273         self.oreTypeFilterController.SetOptions(oreFilterOptions)
    274         corpFilterOptions = [ OptionObject(cfg.eveowners.Get(corpID).name, corpID, OPTION_ITEMID) for corpID in allCorps ]
    275         self.corpFilterController.SetOptions(corpFilterOptions)
    276 
    277     def GetCorpData(self, structureID):
    278         data = GetLedgerService().GetCorpData(structureID)
    279         return data
    280 
    281     def LoadScroll(self):
    282         structureID = self.structureCombo.GetValue()
    283         self.ledgerMinimap.LoadMiniMap(ledgerUtil.GetDataForCorpMinimap(structureID))
    284         data = self.GetCorpData(structureID)
    285         data = self.FilterOutData(data)
    286         filterText = self.filterInput.GetValue()
    287         contentList = GetLedgerEntriesCorp(data, filterText.lower())
    288         self.scroll.Load(contentList=contentList, headers=ledgerUtil.SCROLL_HEADERS_CORP, noContentHint=GetByLabel('UI/ScienceAndIndustry/ScienceAndIndustryWindow/FiltersReturnedNoResults'))
    289         self.scroll.HideLoading()
    290 
    291     def OnSliderChanged(self):
    292         self.scroll.ShowLoading()
    293         uthread.new(self.ReloadContent)
    294 
    295     @threadutils.throttled(1.0)
    296     def ReloadContent(self):
    297         self.LoadScroll()
    298 
    299     def OnStructureChanged(self, combo, key, structureID):
    300         settings.user.ui.Set(combo.prefskey, structureID)
    301         self.LoadFiltersAndScroll(structureID)
    302 
    303     def OnMainFilterChanged(self, *args):
    304         self.LoadScroll()
    305 
    306     @telemetry.ZONE_METHOD
    307     def FilterOutData(self, dataList):
    308         fromTime, toTime = self.sliderController.GetVisibleRange()
    309         selectedOreOptions = self.oreTypeFilterController.GetSelectedOptions()
    310         oreTypeIDs = [ x[1] for x in selectedOreOptions if x[0] == OPTION_TYPEID ]
    311         oreGroupIDs = {x[1] for x in selectedOreOptions if x[0] == OPTION_TYPE_GROUPINGID}
    312         filterInfo = KeyVal(oreTypeIDs=oreTypeIDs, oreGroupIDs=oreGroupIDs, corpIDs=[ x[1] for x in self.corpFilterController.GetSelectedOptions() ], oreActive=self.oreTypeFilterController.IsActive(), corpActive=self.corpFilterController.IsActive(), fromTime=fromTime, toTime=toTime)
    313         newDataList = []
    314         for each in dataList:
    315             if self.IsFilteredOut(each, filterInfo):
    316                 continue
    317             newDataList.append(each)
    318 
    319         return newDataList
    320 
    321     @telemetry.ZONE_METHOD
    322     def IsFilteredOut(self, info, filterInfo):
    323         if not ledgerUtil.IsInRange(info.eventDate, filterInfo.fromTime, filterInfo.toTime):
    324             return True
    325         if not filterInfo.oreActive and not filterInfo.corpActive:
    326             return False
    327         if filterInfo.corpActive and info.corporationID not in filterInfo.corpIDs:
    328             return True
    329         if filterInfo.oreActive and self._IsOreTypeFilteredOut(info.typeID, filterInfo):
    330             return True
    331         return False
    332 
    333     def _IsOreTypeFilteredOut(self, typeID, filterInfo):
    334         if typeID in filterInfo.oreTypeIDs:
    335             return False
    336         if _GetGroupID(typeID) in filterInfo.oreGroupIDs:
    337             return False
    338         if _GetBasicOreForTypeID(typeID) in filterInfo.oreTypeIDs:
    339             return False
    340         return True
    341 
    342     def OnTabSelect(self):
    343         self.PopulateStructureCombo()
    344         self.LoadScroll()
    345 
    346     def ChangeSignalConnection(self, connect = True):
    347         signalAndCallback = [(self.oreTypeFilterController.on_filter_changed, self.OnMainFilterChanged), (self.corpFilterController.on_filter_changed, self.OnMainFilterChanged), (self.sliderController.on_change, self.OnSliderChanged)]
    348         ChangeSignalConnect(signalAndCallback, connect)
    349 
    350     def CopyToClipboard(self, *args):
    351         extraColumns = [GetByLabel('UI/Ledger/OreTypeID'), GetByLabel('UI/Ledger/SolarSystemID')]
    352         allLines = ['\t'.join(ledgerUtil.SCROLL_HEADERS_CORP + extraColumns)]
    353         for eachData in self.scroll.GetNodes():
    354             text = '\t'.join([eachData.formattedText['date'],
    355              eachData.formattedText['corpName'],
    356              eachData.formattedText['charName'],
    357              eachData.formattedText['typeName'],
    358              unicode(eachData.formattedText['qty']),
    359              unicode(eachData.formattedText['volume']),
    360              unicode(eachData.formattedText['estPrice']),
    361              unicode(eachData.ledgerData.typeID),
    362              unicode(eachData.ledgerData.solarsystemID)])
    363             allLines.append(text)
    364 
    365         allText = '\r\n'.join(allLines)
    366         if allText:
    367             blue.pyos.SetClipboardData(allText)
    368 
    369     def Close(self):
    370         with EatSignalChangingErrors(errorMsg='LedgerPanelCorp'):
    371             self.ChangeSignalConnection(connect=False)
    372         Container.Close(self)
    373 
    374 
    375 def GetOreOptionsFromData(data):
    376     normalOreGroupIDs, moonTypeIDsByGroupID = ledgerUtil.GetGroupingsForOreFromData(data)
    377     moonOptions = []
    378     for moonGroupID, typeIDs in moonTypeIDsByGroupID.iteritems():
    379         basicTypeIDs = {ledgerUtil.GetBasicOreForTypeID(x) for x in typeIDs}
    380         subOptions = [ OptionObject(evetypes.GetName(x), x, OPTION_TYPEID) for x in basicTypeIDs ]
    381         moonOptions.append(OptionObject(evetypes.GetGroupNameByGroup(moonGroupID), moonGroupID, OPTION_TYPE_GROUPINGID, subOptions))
    382 
    383     moonOptions.sort(key=lambda x: x.value)
    384     normalOptions = [ OptionObject(evetypes.GetGroupNameByGroup(x), x, OPTION_TYPE_GROUPINGID) for x in normalOreGroupIDs ]
    385     normalOptions.sort(key=lambda x: x.name)
    386     options = moonOptions + normalOptions
    387     return options
    388 
    389 
    390 @Memoize(1)
    391 def _GetGroupID(typeID):
    392     return evetypes.GetGroupID(typeID)
    393 
    394 
    395 @Memoize(1)
    396 def _GetBasicOreForTypeID(typeID):
    397     return ledgerUtil.GetBasicOreForTypeID(typeID)