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

journal.py (51722B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\journal.py
      2 from operator import attrgetter
      3 import blue
      4 import carbonui.const as uiconst
      5 import evetypes
      6 import geo2
      7 import localization
      8 import log
      9 import telemetry
     10 import uthread
     11 import utillib
     12 from carbon.common.script.sys.service import Service
     13 from carbon.common.script.util.format import FmtDate, FmtSimpleDateUTC, FmtTimeInterval, ParseDate, ParseSmallDate
     14 from carbonui.control.button import Button
     15 from carbonui.control.checkbox import Checkbox
     16 from carbonui.control.combo import Combo
     17 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     18 from carbonui.control.window import Window
     19 from carbonui.primitives.container import Container
     20 from carbonui.window.header.tab_navigation import TabNavigationWindowHeader
     21 from eve.client.script.ui.control import eveEdit, eveScroll
     22 from eve.client.script.ui.control.divider import Divider
     23 from eve.client.script.ui.control.entries.generic import Generic
     24 from eve.client.script.ui.control.entries.util import GetFromClass
     25 from eve.client.script.ui.control.listgroup import ListGroup
     26 from eve.client.script.ui.shared.incursionJournal import GlobalIncursionReportEntry, IncursionTab
     27 from eve.client.script.ui.shared.neocom.activeMissionController import ActiveMissionController
     28 from eve.client.script.ui.station.agents import agentUtil
     29 from eve.client.script.ui.station.agents.agentConst import MISSIONSTATELABELS
     30 from eve.client.script.ui.station.agents.agentDialogueUtil import GetAgentNameAndLevel
     31 from eve.client.script.ui.station.missions.missionentry import VirtualAgentMissionEntry
     32 from eve.common.lib import appConst
     33 from eve.common.lib import appConst as const
     34 from eve.common.lib.appConst import factionDrifters
     35 from eve.common.script.mgt import appLogConst
     36 from eve.common.script.mgt import appLogConst as logConst
     37 from eve.common.script.sys.rowset import IndexRowset
     38 from evePathfinder.core import IsUnreachableJumpCount
     39 from eveservices.menu import GetMenuService
     40 from grouprewards import REWARD_TYPE_ISK
     41 from grouprewards import REWARD_TYPE_LP
     42 from grouprewards.data import get_max_reward_value_by_reward_type
     43 from inventorycommon.const import ownerAmarrNavy
     44 from localization import GetByLabel
     45 from menu import MenuLabel, MenuList
     46 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     47 MAX_COL_LENGTH = 60
     48 
     49 class ReportSortBy():
     50     Constellation, LP, Jumps, Influence, StagingSolarSystem, Security = range(6)
     51 
     52 
     53 REPORT_SORT_PARAMETERS = (('constellationName', False),
     54  ('loyaltyPoints', True),
     55  ('jumps', False),
     56  ('influence', True),
     57  ('stagingSolarSystemName', False),
     58  ('security', True))
     59 REWARD_SCOUT = 8
     60 REWARD_VANGUARD = 1
     61 REWARD_ASSAULT = 2
     62 REWARD_HQ = 3
     63 REWARD_BOSS = 10
     64 REWARD_THRONE_WORLDS_LIGHT = 15
     65 REWARD_THRONE_WORLDS_MEDIUM = 16
     66 REWARD_THRONE_WORLDS_HEAVY = 17
     67 INCURSION_DUNGEONS = {'scout': (utillib.KeyVal(severity='scout', index=1, rewardID=REWARD_SCOUT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/One', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/OneText'),
     68            utillib.KeyVal(severity='scout', index=2, rewardID=REWARD_SCOUT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/Two', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/TwoText'),
     69            utillib.KeyVal(severity='scout', index=3, rewardID=REWARD_SCOUT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/Three', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/ThreeText'),
     70            utillib.KeyVal(severity='scout', index=4, rewardID=REWARD_SCOUT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/Four', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Scout/FourText')),
     71  'vanguard': (utillib.KeyVal(severity='vanguard', index=1, rewardID=REWARD_VANGUARD, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/One', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/OneText'), utillib.KeyVal(severity='vanguard', index=2, rewardID=REWARD_VANGUARD, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/Two', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/TwoText'), utillib.KeyVal(severity='vanguard', index=3, rewardID=REWARD_VANGUARD, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/Three', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Vanguard/ThreeText')),
     72  'assault': (utillib.KeyVal(severity='assault', index=1, rewardID=REWARD_ASSAULT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/One', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/OneText'), utillib.KeyVal(severity='assault', index=2, rewardID=REWARD_ASSAULT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/Two', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/TwoText'), utillib.KeyVal(severity='assault', index=3, rewardID=REWARD_ASSAULT, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/Three', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/Assault/ThreeText')),
     73  'hq': (utillib.KeyVal(severity='hq', index=1, rewardID=REWARD_HQ, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/One', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/OneText'),
     74         utillib.KeyVal(severity='hq', index=2, rewardID=REWARD_HQ, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/Two', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/TwoText'),
     75         utillib.KeyVal(severity='hq', index=3, rewardID=REWARD_HQ, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/Three', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/ThreeText'),
     76         utillib.KeyVal(severity='hq', index=4, rewardID=REWARD_BOSS, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/Four', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/FourText'),
     77         utillib.KeyVal(severity='hq', index=5, rewardID=REWARD_BOSS, name='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/Five', text='UI/Incursion/Distributions/SanshaIncursion/Encounters/HQ/FiveText')),
     78  'amarr': (utillib.KeyVal(severity='defensiveOutpost', index=1, rewardID=REWARD_THRONE_WORLDS_LIGHT, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrDefensiveOutpost', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrDefensiveOutpostText'), utillib.KeyVal(severity='encampment', index=2, rewardID=REWARD_THRONE_WORLDS_MEDIUM, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrEncampment', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrEncampmentText'), utillib.KeyVal(severity='battalion', index=3, rewardID=REWARD_THRONE_WORLDS_HEAVY, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrBattalion', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Amarr/AmarrBattalionText')),
     79  'drifters': (utillib.KeyVal(severity='moderateInflux', index=1, rewardID=REWARD_THRONE_WORLDS_LIGHT, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/ModerateDrifterInflux', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/ModerateDrifterInfluxText'), utillib.KeyVal(severity='severeInflux', index=2, rewardID=REWARD_THRONE_WORLDS_MEDIUM, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/SevereDrifterInflux', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/SevereDrifterInfluxText'), utillib.KeyVal(severity='criticalInflux', index=3, rewardID=REWARD_THRONE_WORLDS_HEAVY, name='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/CriticalDrifterInflux', text='UI/Incursion/Distributions/DefenseOfTheThroneWorlds/Encounters/Drifters/CriticalDrifterInfluxText'))}
     80 ENGLISH_MISSIONS_SETTING = 'AgentMissionsInEnglish'
     81 
     82 def _GetIncursionJournalEntry(label, **kwargs):
     83     label_path = '/'.join(['UI/Incursion/Journal', label])
     84     return GetByLabel(label_path, **kwargs)
     85 
     86 
     87 def _GetInvasionJournalEntry(label, **kwargs):
     88     label_path = '/'.join(['UI/Invasion/Journal', label])
     89     return GetByLabel(label_path, **kwargs)
     90 
     91 
     92 def FormatJournalEntry(label, rewardID, **kwargs):
     93     if rewardID == appConst.rewardInvasions:
     94         return _GetInvasionJournalEntry(label, **kwargs)
     95     return _GetIncursionJournalEntry(label, **kwargs)
     96 
     97 
     98 class LPTypeFilter():
     99     LPLost = -1
    100     LPPayedOut = -2
    101 
    102 
    103 class JournalSvc(Service):
    104     __exportedcalls__ = {'Refresh': [],
    105      'GetMyAgentJournalDetails': []}
    106     __update_on_reload__ = 0
    107     __guid__ = 'svc.journal'
    108     __notifyevents__ = ['ProcessSessionChange',
    109      'OnAgentMissionChange',
    110      'OnEscalatingPathMessage',
    111      'OnEscalatingPathChange',
    112      'OnFleetEscalatingPathMessage',
    113      'ProcessUIRefresh',
    114      'OnSessionReset']
    115     __servicename__ = 'journal'
    116     __displayname__ = 'Journal Client Service'
    117     __dependencies__ = ['window', 'settings']
    118 
    119     def Run(self, memStream = None):
    120         log.LogInfo('Starting Journal')
    121         self.Reset()
    122         self.outdatedAgentJournals = []
    123         self.pathPlexPositionByInstanceID = {}
    124 
    125     def Stop(self, memStream = None):
    126         wnd = self.GetWnd()
    127         if wnd is not None and not wnd.destroyed:
    128             wnd.Close()
    129 
    130     def OnSessionReset(self):
    131         self.Reset()
    132         self.outdatedAgentJournals = []
    133         self.pathPlexPositionByInstanceID = {}
    134 
    135     def ProcessSessionChange(self, isremote, session, change):
    136         if session.charid is None:
    137             self.Stop()
    138             self.Reset()
    139         if 'locationid' in change:
    140             self.pathPlexPositionByInstanceID = {}
    141 
    142     def ProcessUIRefresh(self):
    143         self.Reset()
    144 
    145     @telemetry.ZONE_METHOD
    146     def OnAgentMissionChange(self, missionState, agentID):
    147         if agentID is None:
    148             self.agentjournal = None
    149         elif agentID not in self.outdatedAgentJournals:
    150             self.outdatedAgentJournals.append(agentID)
    151         sm.GetService('addressbook').RefreshWindow()
    152         wnd = self.GetWnd()
    153         if (not wnd or wnd.destroyed) and missionState not in (appConst.agentMissionDeclined,
    154          appConst.agentMissionCompleted,
    155          appConst.agentMissionQuit,
    156          appConst.agentMissionOfferDeclined,
    157          appConst.agentMissionDungeonMoved):
    158             hint = GetByLabel('UI/Neocom/Blink/AgentMissionStatusChanged', agentID=agentID)
    159             sm.GetService('neocom').Blink(JournalWindow.default_windowID, hint)
    160         sm.ScatterEvent('OnAgentMissionChanged', missionState, agentID)
    161 
    162     def OnEscalatingPathMessage(self, instanceID):
    163         exp1 = self.GetEscalations()
    164         exp2 = IndexRowset(exp1.header, exp1.lines, 'instanceID')
    165         if instanceID not in exp2:
    166             exp1 = self.GetEscalations(1)
    167             exp2 = IndexRowset(exp1.header, exp1.lines, 'instanceID')
    168         if instanceID in exp2:
    169             data = utillib.KeyVal()
    170             data.rec = exp2[instanceID]
    171             self.PopupDungeonDescription(data)
    172         else:
    173             log.LogInfo("Someone tried loading a message that isn't there")
    174 
    175     def OnEscalatingPathChange(self, *args):
    176         self.GetEscalations(1)
    177 
    178     def OnFleetEscalatingPathMessage(self, charID, journalEntryTemplateID):
    179         if charID != session.charid:
    180             if cfg.eveowners.GetIfExists(charID) is not None:
    181                 dungeonName = GetByLabel('UI/Journal/JournalWindow/Dungeons/DungeonName', character=charID)
    182             else:
    183                 dungeonName = GetByLabel('UI/Journal/JournalWindow/Dungeons/DungeonNameUnknown')
    184             journalEntry = localization.GetByMessageID(journalEntryTemplateID)
    185             data = utillib.KeyVal()
    186             data.instanceID = 0
    187             data.dungeonName = dungeonName
    188             data.pathEntry = GetByLabel('UI/Journal/JournalWindow/Dungeons/UpdatedJournalEntry', character=charID, journalEntry=journalEntry)
    189             data.fakerec = True
    190             data.rec = data
    191             self.PopupDungeonDescription(data)
    192 
    193     def Reset(self):
    194         self.agentjournal = None
    195         self.semaphore = uthread.Semaphore()
    196         self.notext = None
    197         self.escalationRowset = None
    198         self._activeMissions = []
    199 
    200     def Refresh(self):
    201         wnd = self.GetWnd()
    202         if wnd is not None and not wnd.destroyed:
    203             wnd.sr.maintabs.ReloadVisible()
    204 
    205     def GetWnd(self, new = 0, skipAutoSelect = False):
    206         if new:
    207             wnd = JournalWindow.Open(skipAutoSelect=skipAutoSelect)
    208         else:
    209             wnd = JournalWindow.GetIfOpen()
    210         return wnd
    211 
    212     def ShowIncursionTab(self, flag = None, constellationID = None, taleID = None, open = False):
    213         wnd = self.GetWnd(new=open, skipAutoSelect=True)
    214         if wnd is not None and not wnd.destroyed:
    215             blue.pyos.synchro.Yield()
    216             wnd.ShowIncursionTab(flag, constellationID, taleID)
    217 
    218     def GetEscalations(self, force = 0):
    219         if self.escalationRowset is None or force:
    220             self.escalationRowset = sm.RemoteSvc('dungeonExplorationMgr').GetMyEscalatingPathDetails()
    221             sm.ScatterEvent('OnEscalationsDataUpdated')
    222         return self.escalationRowset
    223 
    224     def PopupDungeonDescription(self, node):
    225         if node.get('fakerec', None):
    226             did = node.instanceID
    227             dname = node.dungeonName
    228             djentry = node.pathEntry
    229         else:
    230             if node.rec:
    231                 dungeonDstData = node.rec.destDungeon
    232                 dungeonSrcData = node.rec.srcDungeon
    233                 dungeonInstanceID = node.rec.dungeon.instanceID
    234                 journalEntryTemplateID = node.rec.journalEntryTemplateID
    235             else:
    236                 dungeonDstData = node.destDungeon
    237                 dungeonSrcData = node.srcDungeon
    238                 dungeonInstanceID = node.dungeon.instanceID
    239                 journalEntryTemplateID = node.journalEntryTemplateID
    240             did = dungeonInstanceID
    241             if dungeonDstData is not None:
    242                 dname = localization.GetByMessageID(dungeonDstData.dungeonNameID)
    243             elif dungeonSrcData is not None:
    244                 dname = localization.GetByMessageID(dungeonSrcData.dungeonNameID)
    245             else:
    246                 log.LogError('No dungeon data to get dungeon name from. id:', did)
    247                 return
    248             djentry = localization.GetByMessageID(journalEntryTemplateID)
    249         data = utillib.KeyVal()
    250         data.rec = node
    251         data.header = dname
    252         data.icon = '40_14'
    253         data.text = djentry
    254         data.caption = GetByLabel('UI/Common/Expeditions')
    255         data.hasDungeonWarp = True
    256         data.instanceID = did
    257         wnd = sm.GetService('transmission').OnIncomingTransmission(data)
    258 
    259     def GetMyAgentJournalDetails(self):
    260         self._CheckUpdateMissionData()
    261         return self.agentjournal
    262 
    263     def _CheckUpdateMissionData(self):
    264         s = getattr(self, 'semaphore', None)
    265         if s is not None:
    266             s.acquire()
    267         try:
    268             if self.agentjournal is None:
    269                 self._UpdateMissionDataFull()
    270                 self._UpdateActiveMissions()
    271             elif self.outdatedAgentJournals:
    272                 self._UpdateMissionDataPartial()
    273                 self._UpdateActiveMissions()
    274         finally:
    275             if s is not None:
    276                 s.release()
    277 
    278     def _UpdateMissionDataFull(self):
    279         self.agentjournal = sm.RemoteSvc('agentMgr').GetMyJournalDetails()
    280         for mission in self.agentjournal[0]:
    281             for b in mission[6]:
    282                 if getattr(b, 'originalHint', None) is None:
    283                     b.originalHint = b.hint
    284                 b.hint = GetByLabel(b.originalHint, location=b.locationID, index=b.locationNumber + 1)
    285 
    286     def _UpdateMissionDataPartial(self):
    287         parallelCalls = []
    288         tmp = self.outdatedAgentJournals
    289         for agentID in self.outdatedAgentJournals:
    290             parallelCalls.append((sm.GetService('agents').GetAgentMoniker(agentID).GetMyJournalDetails, ()))
    291 
    292         self.outdatedAgentJournals = []
    293         parallelResults = uthread.parallel(parallelCalls)
    294         self.i = parallelResults
    295         if self.agentjournal is None:
    296             self.agentjournal = sm.RemoteSvc('agentMgr').GetMyJournalDetails()
    297         else:
    298             for agentID in tmp:
    299                 for mission in self.agentjournal[0]:
    300                     if mission[4] == agentID:
    301                         self.agentjournal[0].remove(mission)
    302                         break
    303 
    304             for i in range(len(parallelResults)):
    305                 for mission in parallelResults[i][0]:
    306                     for b in mission[6]:
    307                         if getattr(b, 'originalHint', None) is None:
    308                             b.originalHint = b.hint
    309                         b.hint = GetByLabel(b.originalHint, location=b.locationID, index=b.locationNumber + 1)
    310 
    311                 agentID = tmp[i]
    312                 for n in range(2):
    313                     self.agentjournal[n].extend(parallelResults[i][n])
    314 
    315     def _UpdateActiveMissions(self):
    316         self._activeMissions = []
    317         for missionData in self.agentjournal[:1][0]:
    318             self._activeMissions.append(ActiveMissionController(*missionData))
    319 
    320     def GetActiveMissions(self):
    321         self._CheckUpdateMissionData()
    322         return self._activeMissions
    323 
    324     def GetActiveMissionForAgent(self, agentID):
    325         for mission in self.GetActiveMissions():
    326             if mission.agentID == agentID:
    327                 return mission
    328 
    329     def GetActiveStorylineMissions(self):
    330         return [ mission for mission in self.GetActiveMissions() if mission.isImportantMission ]
    331 
    332     def GetAgentMissions(self):
    333         return self.GetMyAgentJournalDetails()[:1][0]
    334 
    335     def IsMissionActiveWithAgent(self, agentID):
    336         for _, _, _, _, _agentID, _, _, _, _, _ in self.GetAgentMissions():
    337             if _agentID == agentID:
    338                 return True
    339 
    340         return False
    341 
    342     def GetMyAgentJournalBookmarks(self):
    343         ret = []
    344         missions = self.GetMyAgentJournalDetails()[0]
    345         if len(missions):
    346             i = 0
    347             for i in range(len(missions)):
    348                 missionState, importantMission, missionType, missionName, agentID, expirationTime, bookmarks, remoteOfferable, remoteCompletable, contentID = missions[i]
    349                 ret.append((missionName, bookmarks, agentID))
    350 
    351         return ret
    352 
    353     def CheckUndock(self, stationID):
    354         missions = self.GetMyAgentJournalDetails()[0]
    355         if len(missions):
    356             for i in range(len(missions)):
    357                 missionState, importantMission, missionType, missionNameID, agentID, expirationTime, bookmarks, remoteOfferable, remoteCompletable, contentID = missions[i]
    358                 if missionState == const.agentMissionStateAccepted:
    359                     for b in bookmarks:
    360                         if b.itemID == stationID and b.locationType == 'objective.source':
    361                             if not sm.GetService('agents').CheckCourierCargo(agentID, b.itemID, contentID):
    362                                 missionName = sm.GetService('agents').ProcessMessage((missionNameID, contentID), agentID)
    363                                 return prompt_player_fsd_dialog('CourierUndockMissingCargo', {'missionName': missionName}, uiconst.YESNO) == uiconst.ID_YES
    364 
    365         return True
    366 
    367 
    368 class PlanetaryInteractionLaunchEntry(Generic):
    369     __guid__ = 'listentry.PlanetaryInteractionLaunchEntry'
    370     OnSelectCallback = None
    371 
    372     def Load(self, node):
    373         Generic.Load(self, node)
    374         self.sr.node = node
    375         self.sr.label.text = node.label
    376         self.OnSelectCallback = node.Get('callback', None)
    377         if node.Get('selected', 0):
    378             self.Select()
    379         else:
    380             self.Deselect()
    381         self.state = uiconst.UI_NORMAL
    382         self.sr.label.Update()
    383 
    384     def GetMenu(self):
    385         node = self.sr.node
    386         m = MenuList()
    387         if not node.expired:
    388             if node.rec.solarSystemID is not None:
    389                 m += GetMenuService().CelestialMenu(node.rec.solarSystemID).filter('UI/Inflight/BookmarkLocation')
    390                 m.append(None)
    391             if node.rec.solarSystemID == session.solarsystemid:
    392                 mickey = sm.StartService('michelle')
    393                 me = mickey.GetBall(session.shipid)
    394                 dist = geo2.Vec3DistanceD((node.rec.x, node.rec.y, node.rec.z), (me.x, me.y, me.z))
    395                 if dist < const.minWarpDistance:
    396                     m.append((MenuLabel('UI/Inflight/ApproachLocation'), self.Approach, list((node.rec.itemID, node))))
    397                 else:
    398                     m.append((MenuLabel('UI/Inflight/WarpToBookmark'), self.WarpToLaunchPickup, (node.rec.launchID, node)))
    399         else:
    400             m.append(None)
    401             m.append((MenuLabel('UI/Commands/Remove'), self.DeleteLaunchEntry, (node.rec.launchID, node)))
    402         return m
    403 
    404     def Approach(self, launchID, node):
    405         bp = sm.StartService('michelle').GetRemotePark()
    406         if bp is not None:
    407             bp.CmdFollowBall(launchID, 50)
    408 
    409     def WarpToLaunchPickup(self, launchID, node, *args):
    410         sm.GetService('michelle').CmdWarpToStuff('launch', launchID)
    411 
    412     def DeleteLaunchEntry(self, launchID, *args):
    413         rm = []
    414         for entry in self.sr.node.scroll.GetNodes():
    415             if entry.id == launchID:
    416                 rm.append(entry)
    417 
    418         if rm:
    419             self.sr.node.scroll.RemoveEntries(rm)
    420         uthread.new(sm.RemoteSvc('planetMgr').DeleteLaunch, launchID)
    421         uthread.new(sm.GetService('planetUI').GetLaunches, force=1)
    422 
    423 
    424 class JournalWindow(Window):
    425     __guid__ = 'form.Journal'
    426     __notifyevents__ = ['ProcessSessionChange', 'OnAgentMissionChange']
    427     default_width = 525
    428     default_height = 300
    429     default_minSize = (465, 300)
    430     default_windowID = 'journal'
    431     default_captionLabelPath = 'UI/Journal/JournalWindow/Caption'
    432     default_descriptionLabelPath = 'Tooltips/Neocom/Journal_description'
    433     default_iconNum = 'res:/ui/Texture/WindowIcons/journal.png'
    434     default_scrollPanelPadding = 10
    435 
    436     def ApplyAttributes(self, attributes):
    437         Window.ApplyAttributes(self, attributes)
    438         self.entry = None
    439         self.showingIncursionTab = False
    440         self.incursionLPLogData = None
    441         skipAutoSelect = attributes.Get('skipAutoSelect', False)
    442         self.SetScope(uiconst.SCOPE_INGAME)
    443         self.clientPathfinderService = sm.GetService('clientPathfinderService')
    444         width = settings.char.ui.Get('journalIncursionEncounterScrollWidth', 100)
    445         self.sr.incursionEncounterScroll = eveScroll.Scroll(parent=self.sr.main, name='encounterScroll', align=uiconst.TOLEFT, width=width, state=uiconst.UI_HIDDEN)
    446         self.LoadIncursionDistributions()
    447         divider = Divider(name='incursionEncountersDivider', align=uiconst.TOLEFT, width=const.defaultPadding, parent=self.sr.main, state=uiconst.UI_HIDDEN)
    448         dividerMin = 100
    449         dividerMax = self.sr.incursionEncounterScroll.GetMaxTextWidth(200) + self.default_scrollPanelPadding
    450         divider.Startup(self.sr.incursionEncounterScroll, 'width', 'x', dividerMin, dividerMax)
    451         divider.OnSizeChanged = self.OnIncursionEncounterResize
    452         self.sr.incursionEncounterDivider = divider
    453         self.incursionReportFilter = Container(name='incursionGlobalReportFilter', parent=self.sr.main, align=uiconst.TOTOP, height=Button.default_height, state=uiconst.UI_HIDDEN)
    454         options = ((GetByLabel('UI/Common/Constellation'), ReportSortBy.Constellation),
    455          (GetByLabel('UI/Incursion/Journal/StagingSystem'), ReportSortBy.StagingSolarSystem),
    456          (GetByLabel('UI/Common/Jumps'), ReportSortBy.Jumps),
    457          (GetByLabel('UI/Common/Security'), ReportSortBy.Security),
    458          (GetByLabel('UI/LPStore/LP'), ReportSortBy.LP),
    459          (GetByLabel('UI/Incursion/Common/HUDInfluenceTitle'), ReportSortBy.Influence))
    460         self.incursionReportSortCombo = Combo(label=GetByLabel('UI/Common/SortBy'), parent=self.incursionReportFilter, options=options, name='reportSortByCombo', callback=self.OnReportSortByComboChange, align=uiconst.TOLEFT, width=200, select=settings.char.ui.Get('journalIncursionReportSort', ReportSortBy.Constellation), padLeft=4)
    461         Button(parent=self.incursionReportFilter, align=uiconst.TOPRIGHT, texturePath='res:/UI/Texture/Icons/105_32_22.png', iconSize=24, hint=GetByLabel('UI/Incursion/Journal/RefreshGlobalReport'), func=lambda : self.ShowIncursionTab(IncursionTab.GlobalReport), args=())
    462         self.incursionLPLogFilters = Container(name='incursionLPLogFilters', parent=self.sr.main, height=Button.default_height, align=uiconst.TOTOP, state=uiconst.UI_HIDDEN, padTop=16)
    463         self.incursionLPLoadbutton = Button(parent=self.incursionLPLogFilters, label=GetByLabel('UI/Generic/Load'), align=uiconst.BOTTOMRIGHT, func=self.LoadIncursionLPLog)
    464         now = FmtDate(blue.os.GetWallclockTime(), 'sn')
    465         self.incursionLPDate = SingleLineEditText(name='incursionFromdate', parent=self.incursionLPLogFilters, setvalue=now, align=uiconst.TOLEFT, maxLength=16, label=GetByLabel('UI/Common/Date'), padding=(4, 0, 0, 0), width=110)
    466         options = [(GetByLabel('UI/Incursion/Journal/AllIncursionsFilter'), None)]
    467         self.incursionLPTaleIDFilter = Combo(label=GetByLabel('UI/Incursion/Journal/Incursion'), parent=self.incursionLPLogFilters, options=options, name='incursionTaleIDFilter', width=110, align=uiconst.TOLEFT, padding=(4, 0, 0, 0))
    468         options = [(GetByLabel('UI/Incursion/Journal/AllTypesFilter'), None)]
    469         self.incursionLPTaleIDFilter = Combo(label=GetByLabel('UI/Incursion/Journal/Types'), parent=self.incursionLPLogFilters, options=options, name='incursionTypeFilter', width=110, align=uiconst.TOLEFT, padding=(4, 0, 0, 0))
    470         self.sr.incursionEncounterEdit = eveEdit.Edit(parent=self.sr.main, name='incursionEncounterEdit', state=uiconst.UI_HIDDEN, readonly=True, align=uiconst.TOALL)
    471         self.sr.main = self.GetChild('main')
    472         self.sr.agentEnglishMissionsCnt = Container(name='agentEnglishMissionCnt', parent=self.sr.main, padding=(const.defaultPadding,) * 4, height=20, align=uiconst.TOBOTTOM, state=uiconst.UI_HIDDEN)
    473         self.sr.agentEnglishMissions = Checkbox(parent=self.sr.agentEnglishMissionsCnt, name='agentMissionEnglish', text=GetByLabel('UI/Journal/JournalWindow/Agents/ShowEnglishMissionNames'), checked=settings.user.localization.Get(ENGLISH_MISSIONS_SETTING, False), callback=self.OnAgentEnglishCheckBoxChange)
    474         self.sr.scroll = eveScroll.Scroll(parent=self.sr.main)
    475         self.sr.scroll.multiSelect = 0
    476         self.ConstructTabGroup(skipAutoSelect)
    477         sm.RegisterNotify(self)
    478 
    479     def Prepare_Header_(self):
    480         self.header = TabNavigationWindowHeader()
    481 
    482     def ConstructTabGroup(self, skipAutoSelect):
    483         self.tabGroup = self.header.tab_group
    484         self.tabGroup.AddTab(GetByLabel('UI/PeopleAndPlaces/AgentMissions'), self.sr.scroll, self, ('agent_missions', 0), hint=GetByLabel('UI/Journal/JournalWindow/Agents/MissionsHint'))
    485         if not skipAutoSelect:
    486             self.tabGroup.AutoSelect()
    487 
    488     def MouseDown(self, *args):
    489         sm.GetService('neocom').BlinkOff(self.default_windowID)
    490 
    491     def LoadIncursionDistributions(self):
    492         self._ConstructIncursionDistributionData()
    493         scrolllist = []
    494         for distributionId, distributionData in self.incursionDistributions.iteritems():
    495             scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.LoadIncursionEncounters,
    496              'label': distributionData['distributionName'],
    497              'sublevel': 0,
    498              'selected': False,
    499              'id': ('distribution', distributionId),
    500              'showlen': False,
    501              'state': 'locked',
    502              'BlockOpenWindow': True,
    503              'showicon': 'hide'}))
    504 
    505         scrolllist.sort(key=lambda encounter: encounter['label'])
    506         self.sr.incursionEncounterScroll.LoadContent(contentList=scrolllist)
    507 
    508     def LoadIncursionEncounters(self, distributionNodeData, *args):
    509         scrolllist = []
    510         distributionId = distributionNodeData['id'][1]
    511         infestationTypes = self.incursionDistributions[distributionId]['infestationTypes']
    512         for encounterId, encounterLabel in infestationTypes.iteritems():
    513             scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetIncursionDungeons,
    514              'label': encounterLabel,
    515              'encounterId': encounterId,
    516              'sublevel': 1,
    517              'selected': False,
    518              'id': ('encounter', encounterId),
    519              'showlen': False,
    520              'state': 'locked',
    521              'BlockOpenWindow': True,
    522              'showicon': 'hide'}))
    523 
    524         scrolllist.sort(key=lambda encounter: encounter['label'])
    525         return scrolllist
    526 
    527     def GetIncursionDungeons(self, encounterDataNode, *args):
    528         scrolllist = []
    529         incursionSvc = sm.GetService('incursion')
    530         for dungeon in INCURSION_DUNGEONS[encounterDataNode['encounterId']]:
    531             scrolllist.append(GetFromClass(Generic, {'label': localization.GetImportantByLabel(dungeon.name),
    532              'OnClick': self.ShowEncounter,
    533              'dungeon': dungeon,
    534              'sublevel': 2,
    535              'id': ('dungeon', localization.GetImportantByLabel(dungeon.name)),
    536              'lpAmount': get_max_reward_value_by_reward_type(dungeon.rewardID, REWARD_TYPE_LP),
    537              'iskAmount': get_max_reward_value_by_reward_type(dungeon.rewardID, REWARD_TYPE_ISK)}))
    538 
    539         return scrolllist
    540 
    541     def _ConstructIncursionDistributionData(self):
    542         self.incursionDistributions = {'sansha': {'distributionName': localization.GetImportantByLabel('UI/TaleDistributions/SanshaIncursion'),
    543                     'infestationTypes': {'scout': localization.GetImportantByLabel('UI/Incursion/Common/Scout'),
    544                                          'vanguard': localization.GetImportantByLabel('UI/Incursion/Common/Vanguard'),
    545                                          'assault': localization.GetImportantByLabel('UI/Incursion/Common/Assault'),
    546                                          'hq': localization.GetImportantByLabel('UI/Incursion/Common/HQ')}},
    547          'drifters': {'distributionName': GetByLabel('UI/TaleDistributions/DefenseOfTheThroneWorldsIncursion'),
    548                       'infestationTypes': {'amarr': localization.GetByMessageID(cfg.eveowners.Get(ownerAmarrNavy).ownerNameID),
    549                                            'drifters': localization.GetByMessageID(cfg.eveowners.Get(factionDrifters).ownerNameID)}}}
    550 
    551     def ShowEncounter(self, node):
    552         data = node.sr.node
    553         imgLink = '<img size=250 style=margin-left:8;margin-top:8 src=reward:{rewardID} align=right>'
    554         html = GetByLabel(data.dungeon.text)
    555         self.sr.incursionEncounterEdit.SetText(html)
    556 
    557     def OnIncursionEncounterResize(self):
    558         settings.char.ui.Set('journalIncursionEncounterScrollWidth', self.sr.incursionEncounterScroll.width)
    559 
    560     def OnReportSortByComboChange(self, combo, key, value):
    561         self.SortIncursionGlobalReport(value)
    562 
    563     def Load(self, args):
    564         key, flag = args
    565         self.sr.scroll.ShowHint(None)
    566         self.incursionReportFilter.Hide()
    567         self.sr.incursionEncounterScroll.Hide()
    568         self.sr.incursionEncounterEdit.Hide()
    569         self.sr.scroll.Hide()
    570         self.incursionLPLogFilters.Hide()
    571         self.sr.agentEnglishMissionsCnt.Hide()
    572         if key == 'agents':
    573             self.sr.scroll.Show()
    574         elif key[:6] == 'agent_':
    575             self.sr.scroll.Show()
    576             self.ShowAgentTab(flag)
    577         elif key.startswith('incursions'):
    578             self.ShowIncursionTab(IncursionTab.LPLog)
    579 
    580     def OnAgentEnglishCheckBoxChange(self, checkbox):
    581         if checkbox.checked:
    582             settings.user.localization.Set(ENGLISH_MISSIONS_SETTING, True)
    583         else:
    584             settings.user.localization.Delete(ENGLISH_MISSIONS_SETTING)
    585         if getattr(self.sr, 'maintabs', None):
    586             self.tabGroup.ReloadVisible()
    587 
    588     def ShowAgentTab(self, statusflag = -1):
    589         self._SelectTab(self.tabGroup.sr.Get(GetByLabel('UI/Journal/JournalWindow/AgentsTab') + '_tab'))
    590         self.ShowLoad()
    591         showEnglishTitles = localization.util.GetLanguageID() != localization.const.LOCALE_SHORT_ENGLISH and settings.user.localization.Get(ENGLISH_MISSIONS_SETTING, False)
    592         if statusflag == 0:
    593             missions = sm.GetService('journal').GetMyAgentJournalDetails()[0]
    594             scrolllist = []
    595             if len(missions):
    596                 missionIconData = []
    597                 maxOptionalIcons = 0
    598                 for i in xrange(len(missions)):
    599                     missionIconData.append(self.GetMissionIconDataForAgentTab(missions[i]))
    600                     maxOptionalIcons = max(maxOptionalIcons, len(missionIconData[i]))
    601 
    602                 for i in xrange(len(missions)):
    603                     missionState, importantMission, missionTypeLabel, missionNameID, agentID, expirationTime, bookmarks, remoteOfferable, remoteCompletable, contentID = missions[i]
    604                     missionType = GetByLabel(missionTypeLabel)
    605                     if isinstance(missionNameID, (int, long)):
    606                         missionName = localization.GetByMessageID(missionNameID)
    607                         if showEnglishTitles:
    608                             enMissionName = localization.GetByMessageID(missionNameID, languageID=localization.const.LOCALE_SHORT_ENGLISH)
    609                     else:
    610                         enMissionName = missionName = missionNameID
    611                     sm.GetService('agents').PrimeMessageArguments(agentID, contentID)
    612                     blankIconID = 'ui_38_16_39'
    613                     for j in xrange(maxOptionalIcons - len(missionIconData[i])):
    614                         missionIconData[i].insert(0, (blankIconID, ''))
    615 
    616                     missionLogInfo = '%s mission %d (%s) %s' % (MISSIONSTATELABELS[missionState],
    617                      i,
    618                      missionName,
    619                      'expires in ' + FmtTimeInterval(expirationTime - blue.os.GetWallclockTime()) if expirationTime else 'does not expire')
    620                     log.LogInfo('Journal::ShowAgentTab:', missionLogInfo)
    621                     if importantMission:
    622                         missionType = '<color=0xFFFFFF00>' + GetByLabel('UI/Journal/JournalWindow/Agents/ImportantMission', missionType=missionType) + '<color=0xffffffff>'
    623                     stateText, expirationText = agentUtil.GetMissionExpirationAndStateText(missionState, expirationTime)
    624                     level = sm.GetService('agents').GetAgentByID(agentID).level
    625                     agentName = GetAgentNameAndLevel(agentID, level)
    626                     if showEnglishTitles:
    627                         text = '<t>'.join([stateText,
    628                          agentName,
    629                          missionName,
    630                          enMissionName,
    631                          missionType,
    632                          expirationText])
    633                     else:
    634                         text = '<t>'.join([stateText,
    635                          agentName,
    636                          missionName,
    637                          missionType,
    638                          expirationText])
    639                     scrolllist.append(GetFromClass(VirtualAgentMissionEntry, {'missionState': missionState,
    640                      'agentID': agentID,
    641                      'label': text,
    642                      'missionIconData': missionIconData[i]}))
    643 
    644             if showEnglishTitles:
    645                 headers = [GetByLabel('UI/Journal/JournalWindow/Agents/HeaderStatus'),
    646                  GetByLabel('UI/Agents/Agent'),
    647                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderMission'),
    648                  GetByLabel('UI/Journal/JournalWindow/Agents/EnglishName'),
    649                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderType'),
    650                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderExpiration')]
    651             else:
    652                 headers = [GetByLabel('UI/Journal/JournalWindow/Agents/HeaderStatus'),
    653                  GetByLabel('UI/Agents/Agent'),
    654                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderMission'),
    655                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderType'),
    656                  GetByLabel('UI/Journal/JournalWindow/Agents/HeaderExpiration')]
    657             self.sr.scroll.sr.id = 'agentjournalscroll%s' % statusflag
    658             self.sr.scroll.Load(contentList=scrolllist, headers=headers, noContentHint=GetByLabel('UI/Journal/JournalWindow/Agents/NoMissionsOfferedOrAccepted'))
    659             if localization.util.GetLanguageID() != localization.const.LOCALE_SHORT_ENGLISH:
    660                 self.sr.agentEnglishMissionsCnt.Show()
    661         self.HideLoad()
    662 
    663     def _SelectTab(self, tab):
    664         if tab is None:
    665             return
    666         if not tab.IsSelected():
    667             tab.Select(True)
    668 
    669     def GetMissionIconDataForAgentTab(self, missionJournalDetails):
    670         missionState, importantMission, missionType, missionName, agentID, expirationTime, bookmarks, remoteOfferable, remoteCompletable, contentID = missionJournalDetails
    671         missionIconData = []
    672         chatBubbleIconID = 'ui_38_16_38'
    673         remoteMissionHints = []
    674         if remoteOfferable:
    675             remoteMissionHints.append(GetByLabel('UI/Agents/Dialogue/StandardMission/AcceptRemotelyHint'))
    676         if remoteCompletable:
    677             remoteMissionHints.append(GetByLabel('UI/Agents/Dialogue/StandardMission/CompleteRemotelyHint'))
    678         if remoteOfferable or remoteCompletable:
    679             remoteMissionHintText = '<br>'.join(remoteMissionHints)
    680             missionIconData.append((chatBubbleIconID, remoteMissionHintText))
    681         return missionIconData
    682 
    683     def GetJumpCount(self, toID):
    684         jumps = self.clientPathfinderService.GetAutopilotJumpCount(session.solarsystemid2, toID)
    685         if IsUnreachableJumpCount(jumps):
    686             return None
    687         return jumps
    688 
    689     def ShowIncursionTab(self, flag = None, constellationID = None, taleID = None):
    690         if self.showingIncursionTab:
    691             return
    692         self.showingIncursionTab = True
    693         if flag is None:
    694             flag = settings.char.ui.Get('journalIncursionTab', IncursionTab.GlobalReport)
    695         settings.char.ui.Set('journalIncursionTab', flag)
    696         self._SelectTab(self.tabGroup.sr.Get(GetByLabel('UI/Journal/JournalWindow/IncursionsTab') + '_tab'))
    697         if flag == IncursionTab.GlobalReport:
    698             self.sr.scroll.Show()
    699             self.incursionReportFilter.state = uiconst.UI_PICKCHILDREN
    700             starmap = sm.GetService('starmap')
    701             map = starmap.map
    702             report = sm.RemoteSvc('map').GetIncursionGlobalReport()
    703             rewardGroupIDs = [ r.rewardGroupID for r in report ]
    704             delayedRewards = sm.GetService('incursion').GetDelayedRewardsByGroupIDs(rewardGroupIDs)
    705             scrolllist = []
    706             factionsToPrime = set()
    707             for data in report:
    708                 data.jumps = self.GetJumpCount(data.stagingSolarSystemID)
    709                 data.influenceData = utillib.KeyVal(influence=data.influence, lastUpdated=data.lastUpdated, graceTime=data.graceTime, decayRate=data.decayRate)
    710                 ssitem = map.GetItem(data.stagingSolarSystemID)
    711                 data.stagingSolarSystemName = ssitem.itemName
    712                 data.security = map.GetSecurityStatus(data.stagingSolarSystemID)
    713                 data.constellationID = ssitem.locationID
    714                 data.constellationName = map.GetItem(ssitem.locationID).itemName
    715                 data.factionID = ssitem.factionID or starmap.GetAllianceSolarSystems().get(data.stagingSolarSystemID, None)
    716                 factionsToPrime.add(data.factionID)
    717                 rewards = delayedRewards.get(data.rewardGroupID, None)
    718                 data.loyaltyPoints = rewards[0].rewardQuantity if rewards else 0
    719                 scrolllist.append(GetFromClass(GlobalIncursionReportEntry, data))
    720 
    721             cfg.eveowners.Prime(list(factionsToPrime))
    722             self.sr.scroll.LoadContent(contentList=scrolllist, scrollTo=0.0)
    723             self.SortIncursionGlobalReport()
    724         elif flag == IncursionTab.LPLog:
    725             self.incursionLPLogFilters.Show()
    726             self.sr.scroll.Show()
    727             if taleID is not None and constellationID is not None:
    728                 self.LoadIncursionLPLog(self.sr.scroll, taleID, constellationID)
    729             elif self.incursionLPLogData is None:
    730                 self.sr.scroll.Clear()
    731                 self.sr.scroll.ShowHint(GetByLabel('UI/Incursion/Journal/LoadData'))
    732             else:
    733                 self.UpdateIncursionLPLog(self.incursionLPLogData)
    734         elif flag == IncursionTab.Encounters:
    735             self.sr.incursionEncounterEdit.Show()
    736             self.sr.incursionEncounterScroll.Show()
    737             self.sr.incursionEncounterDivider.Show()
    738         self.showingIncursionTab = False
    739 
    740     def SortIncursionGlobalReport(self, sortBy = None):
    741         if sortBy is None:
    742             sortBy = settings.char.ui.Get('journalIncursionReportSort', ReportSortBy.Constellation)
    743         else:
    744             settings.char.ui.Set('journalIncursionReportSort', sortBy)
    745         attrName, reverse = REPORT_SORT_PARAMETERS[sortBy]
    746         scroll = self.sr.scroll
    747         scroll.sr.nodes = sorted(scroll.sr.nodes, key=attrgetter(attrName), reverse=reverse)
    748         scroll.UpdatePositionThreaded(fromWhere='SortIncursionGlobalReport')
    749 
    750     def LoadIncursionLPLog(self, scroll, taleID = None, constellationID = None):
    751         rewardMgr = session.ConnectToRemoteService('rewardMgr')
    752         self.incursionLPLogData = rewardMgr.GetRewardLPLogs()
    753         self.UpdateIncursionLPLog(self.incursionLPLogData, taleID, constellationID)
    754 
    755     def UpdateIncursionLPLog(self, data, selectedTaleID = None, selectedConstellationID = None):
    756         mapsvc = sm.GetService('map')
    757         taleIDFilter = self.incursionLPTaleIDFilter.selectedValue
    758         solarsystemTypeFilter = self.incursionLPTaleIDFilter.selectedValue
    759         try:
    760             fromDate = ParseSmallDate(self.incursionLPDate.GetValue())
    761         except (Exception, TypeError):
    762             dateString = localization.formatters.FormatDateTime(blue.os.GetWallclockTime(), dateFormat='short', timeFormat='none')
    763             fromDate = ParseDate(dateString)
    764             self.incursionLPDate.SetValue(dateString)
    765 
    766         fromDate += const.DAY
    767         dungeonTypes = set()
    768         taleIDs = {}
    769         filteredData = []
    770         for d in data:
    771             dungeonTypes.add(d.rewardMessageKey)
    772             constellationID = mapsvc.GetParent(d.solarSystemID)
    773             if constellationID is not None:
    774                 constellation = mapsvc.GetItem(constellationID)
    775                 if constellation is not None:
    776                     taleIDs[d.taleID] = constellation.itemName
    777             if selectedTaleID is not None:
    778                 if selectedTaleID != d.taleID:
    779                     continue
    780             if taleIDFilter is not None and selectedTaleID is None:
    781                 if taleIDFilter != d.taleID:
    782                     continue
    783             if solarsystemTypeFilter is not None:
    784                 shouldAdd = False
    785                 if solarsystemTypeFilter == LPTypeFilter.LPPayedOut:
    786                     if d.eventTypeID == logConst.eventRewardLPPoolPayedOut:
    787                         shouldAdd = True
    788                 elif solarsystemTypeFilter == LPTypeFilter.LPLost:
    789                     if d.eventTypeID == logConst.eventRewardLPPoolLost:
    790                         shouldAdd = True
    791                 elif solarsystemTypeFilter == d.rewardMessageKey:
    792                     shouldAdd = True
    793                 if not shouldAdd:
    794                     continue
    795             if fromDate < d.date:
    796                 continue
    797             filteredData.append(d)
    798 
    799         if selectedTaleID is not None:
    800             if selectedTaleID not in taleIDs:
    801                 constellation = mapsvc.GetItem(selectedConstellationID)
    802                 if constellation is not None:
    803                     taleIDs[selectedTaleID] = constellation.itemName
    804         scrolllist = []
    805         for d in filteredData:
    806             solarSystemType = ''
    807             if d.eventTypeID == logConst.eventRewardLPPoolPayedOut:
    808                 solarSystemType = FormatJournalEntry('CompletedAndPaidOut', d.rewardID)
    809             elif d.eventTypeID == logConst.eventRewardLPPoolLost:
    810                 solarSystemType = FormatJournalEntry('CompletedAndNotPaidOut', d.rewardID)
    811             elif d.rewardMessageKey is not None and isinstance(d.rewardMessageKey, int):
    812                 solarSystemType = localization.GetByMessageID(d.rewardMessageKey)
    813             elif d.rewardMessageKey is not None and d.rewardMessageKey != '':
    814                 solarSystemType = GetByLabel(d.rewardMessageKey)
    815             if d.lpAmountAddedToPool is None:
    816                 d.lpAmountAddedToPool = 0
    817             if d.lpAmountAddedToPool == 0:
    818                 LPAmountAddedToPool = '<color=0xFFFFFFFF>' + localization.formatters.FormatNumeric(0) + '</color>'
    819             else:
    820                 LPAmountAddedToPool = '<color=0xFFFFFF00>' + localization.formatters.FormatNumeric(d.lpAmountAddedToPool) + '</color>'
    821             if d.lpAmountPayedOut is None:
    822                 d.lpAmountPayedOut = 0
    823             if d.lpAmountPayedOut == 0:
    824                 LPAmountPayedOut = '<color=0xFFFFFFFF>' + localization.formatters.FormatNumeric(0) + '</color>'
    825             elif d.eventTypeID == logConst.eventRewardLPPoolLost:
    826                 LPAmountPayedOut = '<color=0xFFFF0000>' + localization.formatters.FormatNumeric(0) + '</color>'
    827             else:
    828                 LPAmountPayedOut = '<color=0xFF00FF00>' + localization.formatters.FormatNumeric(d.lpAmountPayedOut) + '</color>'
    829             if d.numberOfPlayers is None:
    830                 d.numberOfPlayers = 0
    831             description = ''
    832             if d.eventTypeID == logConst.eventRewardDisqualified:
    833                 if d.disqualifierType == const.rewardIneligibleReasonTrialAccount:
    834                     description = FormatJournalEntry('DisqualifiedTrialAccount', d.rewardID)
    835                 elif d.disqualifierType == const.rewardIneligibleReasonInvalidGroup:
    836                     groupName = evetypes.GetGroupNameByGroup(d.disqualifierData)
    837                     description = FormatJournalEntry('DisqualifiedInvalidShipGroup2', d.rewardID, groupName=groupName)
    838                 elif d.disqualifierType == const.rewardIneligibleReasonShipCloaked:
    839                     description = FormatJournalEntry('DisqualifiedCloaked', d.rewardID)
    840                 elif d.disqualifierType == const.rewardIneligibleReasonNotInFleet:
    841                     description = FormatJournalEntry('DisqualifiedNoFleet', d.rewardID)
    842                 elif d.disqualifierType == const.rewardIneligibleReasonNotBestFleet:
    843                     description = FormatJournalEntry('DisqualifiedNotBestFleet', d.rewardID)
    844                 elif d.disqualifierType == const.rewardIneligibleReasonNotTop5:
    845                     description = FormatJournalEntry('DisqualifiedNotInTopFive', d.rewardID)
    846                 elif d.disqualifierType == const.rewardIneligibleReasonNotTopN:
    847                     maxWinners = d.disqualifierData
    848                     description = FormatJournalEntry('DisqualifiedNotInTopN', d.rewardID, n=maxWinners)
    849                 elif d.disqualifierType == const.rewardIneligibleReasonNotRightAmountOfPlayers:
    850                     description = FormatJournalEntry('DisqualifiedNotEnoughParticipants', d.rewardID)
    851                 elif d.disqualifierType == const.rewardIneligibleReasonTaleAlreadyEnded:
    852                     description = FormatJournalEntry('DisqualifiedExpired', d.rewardID)
    853                 elif d.disqualifierType == const.rewardIneligibleReasonLowContribution:
    854                     description = FormatJournalEntry('DisqualifiedLowContribution', d.rewardID)
    855             elif d.eventTypeID == logConst.eventRewardLPStoredInPool:
    856                 description = FormatJournalEntry('LoyaltyPointPilotRewardCount', d.rewardID, rewardedPlayers=d.numberOfPlayers)
    857             elif d.eventTypeID == logConst.eventRewardLPPoolPayedOut:
    858                 description = FormatJournalEntry('LoyaltyPointPoolPaidOut', d.rewardID)
    859             elif d.eventTypeID == logConst.eventRewardLPPoolLost:
    860                 description = FormatJournalEntry('LoyaltyPointPoolLost', d.rewardID)
    861             elif d.eventTypeID == appLogConst.eventRewardLPPaidDirectly:
    862                 description = FormatJournalEntry('LPPaidDirectly', d.rewardID, rewardedPlayers=d.numberOfPlayers)
    863             hint = description
    864             texts = [FmtSimpleDateUTC(d.date),
    865              solarSystemType,
    866              d.dungeonName,
    867              LPAmountAddedToPool,
    868              LPAmountPayedOut,
    869              description]
    870             scrolllist.append(GetFromClass(Generic, {'label': '<t>'.join(texts),
    871              'sort_' + GetByLabel('UI/Incursion/Journal/StoredLP'): d.lpAmountAddedToPool,
    872              'sort_' + GetByLabel('UI/Incursion/Journal/PaidLP'): d.lpAmountPayedOut,
    873              'hint': hint}))
    874 
    875         headers = [GetByLabel('UI/Common/Date'),
    876          GetByLabel('UI/Incursion/Journal/Type'),
    877          GetByLabel('UI/Incursion/Journal/EncounterName'),
    878          GetByLabel('UI/Incursion/Journal/StoredLP'),
    879          GetByLabel('UI/Incursion/Journal/PaidLP'),
    880          GetByLabel('UI/Incursion/Journal/Description')]
    881         options = [(GetByLabel('UI/Incursion/Journal/AllIncursionsFilter'), None)]
    882         for taleID, constellationName in taleIDs.iteritems():
    883             options.append((constellationName, taleID))
    884 
    885         self.incursionLPTaleIDFilter.LoadOptions(options)
    886         if selectedTaleID is None:
    887             self.incursionLPTaleIDFilter.SelectItemByValue(taleIDFilter)
    888         else:
    889             self.incursionLPTaleIDFilter.SelectItemByValue(selectedTaleID)
    890         options = [(GetByLabel('UI/Incursion/Journal/AllTypesFilter'), None), (GetByLabel('UI/Incursion/Journal/CompletedAndNotPaidOut'), LPTypeFilter.LPLost), (GetByLabel('UI/Incursion/Journal/CompletedAndPaidOut'), LPTypeFilter.LPPayedOut)]
    891         for dungeonType in dungeonTypes:
    892             if dungeonType is not None and dungeonType != '':
    893                 if isinstance(dungeonType, int):
    894                     options.append((localization.GetByMessageID(dungeonType), dungeonType))
    895                 else:
    896                     options.append((GetByLabel(dungeonType), dungeonType))
    897 
    898         self.incursionLPTaleIDFilter.LoadOptions(options)
    899         self.incursionLPTaleIDFilter.SelectItemByValue(solarsystemTypeFilter)
    900         if scrolllist:
    901             sortBy = self.sr.scroll.GetSortBy()
    902             sortDirection = self.sr.scroll.GetSortDirection()
    903             self.sr.scroll.LoadContent(contentList=scrolllist, reversesort=1, headers=headers, scrollTo=0.0)
    904             if sortBy is None:
    905                 self.sr.scroll.Sort(by=GetByLabel('UI/Common/Date'), reversesort=1)
    906             else:
    907                 self.sr.scroll.Sort(by=sortBy, reversesort=sortDirection)
    908         else:
    909             self.sr.scroll.Clear()
    910             self.sr.scroll.ShowHint(GetByLabel('UI/Incursion/Journal/NoRecordFound'))
    911 
    912     def MouseExitHighlightOff(self, obj, *args):
    913         obj.SetRGB(1.0, 1.0, 1.0)
    914 
    915     def MouseEnterHighlightOn(self, obj, *args):
    916         obj.SetRGB(1.0, 1.0, 0.0)
    917 
    918     def OnComboChange(self, *args):
    919         pass
    920 
    921     def ProcessSessionChange(self, isremote, session, change):
    922         self.header.tab_group.ReloadVisible()
    923 
    924     def OnAgentMissionChange(self, what, agentID):
    925         self.header.tab_group.ReloadVisible()