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

infosvc.py (188969B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\info\infosvc.py
      2 import sys
      3 import appConst
      4 import blue
      5 import carbonui.const as uiconst
      6 import copy
      7 import dogma.attributes.format as attributeFormat
      8 import dogma.attributes.groups as dogma_attr_groups
      9 import dogma.const as dogma_const
     10 import dogma.data as dogma_data
     11 import dynamicitemattributes
     12 import eveformat.client
     13 import evelink.client
     14 import evetypes
     15 import expertSystems.client
     16 import inventorycommon.typeHelpers
     17 import itertoolsext
     18 import localization
     19 import log
     20 import structures
     21 import telemetry
     22 import uthread
     23 import utillib
     24 from carbon.common.script.sys.service import Service
     25 from carbon.common.script.sys.serviceConst import ROLE_CONTENT, ROLE_GML, ROLE_WORLDMOD
     26 from carbon.common.script.util import timerstuff
     27 from carbon.common.script.util.commonutils import StripTags
     28 from carbon.common.script.util.format import FmtDate, FmtDist
     29 from carbon.common.script.util.linkUtil import GetShowInfoLink
     30 from carbonui.control.button import Button
     31 from carbonui.uicore import uicore
     32 from carbonui.util.color import Color
     33 from carbonui.util.various_unsorted import SortListOfTuples
     34 from characterdata.factions import get_faction_name, get_faction_races, get_station_count, get_station_system_count
     35 from characterdata.races import get_race_name
     36 from collections import defaultdict, OrderedDict
     37 from contrabandtypes.data import get_contraband_types_in_faction
     38 from corruptionsuppression.client.systemEffectsClient import CorruptionWarpSpeedIncreaserCheckerClient
     39 from corruptionsuppression.systemEffects import WARP_SPEED_INCREASE_STAGE_THRESHOLD
     40 from dbuff.client.uiFormatters import GetDbuffInfoEntriesForItem
     41 from dogma.attributes import uiAttributeGroups
     42 from dogma.attributes.format import FormatValue, FormatUnit
     43 from dogma.attributes.format import GetFormatAndValue, GetFormattedAttributeAndValue, GetAttribute
     44 from eve.client.script.ui.control.damageGaugeContainers import DamageEntry
     45 from eve.client.script.ui.control.entries.button import ButtonEntry
     46 from eve.client.script.ui.control.entries.certificate import CertEntry
     47 from eve.client.script.ui.control.entries.divider import DividerEntry
     48 from eve.client.script.ui.control.entries.generic import Generic
     49 from eve.client.script.ui.control.entries.header import Header, Subheader
     50 from eve.client.script.ui.control.entries.item import Item
     51 from eve.client.script.ui.control.entries.label_text import LabelMultilineTextTop, LabelTextSides, LabelTextSidesAttributes, LabelTextSidesMoreInfo, LabelTextTop
     52 from eve.client.script.ui.control.entries.space import Space
     53 from eve.client.script.ui.control.entries.status_bar import StatusBar
     54 from eve.client.script.ui.control.entries.text import Text
     55 from eve.client.script.ui.control.entries.universe import LabelLocationTextTop, SystemNameHeader, LocationGroup, LocationTextEntry
     56 from eve.client.script.ui.control.entries.util import GetFromClass
     57 from eve.client.script.ui.control.listgroup import ListGroup
     58 from player_messaging.client.ui_message import message_player, prompt_player_fsd_dialog
     59 from eve.client.script.ui.control.skillTreeEntry import SkillTreeEntry
     60 from eve.client.script.ui.inflight.itemTrader.itemTraderController import Recipe
     61 from eve.client.script.ui.inflight.itemTrader.offerBrowser import RecipeEntry
     62 from eve.client.script.ui.inflight.itemTrader.recipeUtil import GetSortedRecipeGroupsAndData
     63 from eve.client.script.ui.shared.agencyNew.contentGroups import contentGroupConst
     64 from eve.client.script.ui.shared.agencyNew.ui.agencyWnd import AgencyWndNew
     65 from eve.client.script.ui.shared.cloneGrade import ORIGIN_SHOWINFO
     66 from eve.client.script.ui.shared.dynamicItem.info import FormatAttributeBonusRange
     67 from eve.client.script.ui.shared.info.attribute import Attribute, CreateAttribute, MutatedAttribute, FloatCloseEnough
     68 from eve.client.script.ui.shared.info.infoConst import *
     69 from eve.client.script.ui.shared.info.infoUtil import GetAttributeTooltipTitleAndDescription
     70 from eve.client.script.ui.shared.info.infoWindow import InfoWindow, AttributeRowEntry
     71 from eve.client.script.ui.shared.info.infoContentBase import InfoWindowMonolith, InfoTypeEnum
     72 from eve.client.script.ui.shared.info.characterInfoWindow import CharacterInfoWindow
     73 from eve.client.script.ui.shared.info.corporationInfoWindow import CorporationInfoWindow
     74 from eve.client.script.ui.shared.info.shipInfoWindow import ShipInfoWindow
     75 from eve.client.script.ui.shared.mapView.mapViewPanel import MapViewPanel
     76 from eve.client.script.ui.shared.mapView.mapViewUtil import OpenMap
     77 from eve.client.script.ui.shared.mapView.settings import classic_map_enabled_setting
     78 from eve.client.script.ui.shared.maps import mapcommon
     79 from eve.client.script.ui.shared.medalribbonranks import MedalRibbonEntry, RankEntry
     80 from eve.client.script.ui.shared.neocom.Alliances.all_ui_home import PrimeTimeHourEntryHorizontal
     81 from eve.client.script.ui.shared.neocom.charsheet.charSheetUtil import GetMedalScrollEntries
     82 from eve.client.script.ui.shared.neocom.corporation.war.warEntry import WarEntry
     83 from eve.client.script.ui.shared.neocom.wallet.walletUtil import FmtWalletCurrency
     84 from eve.client.script.ui.shared.skins.uiutil import OPEN_SKINR_BUTTON_INFO_WINDOW_ANALYTIC_ID
     85 from eve.client.script.ui.shared.userentry import AgentEntry, User
     86 from eve.client.script.ui.station import stationServiceConst
     87 from eve.client.script.ui.station.stationServiceEntry import StationServiceEntry
     88 from eve.client.script.ui.structure.structureSettings.groupEntryCont import VALUE_TYPES
     89 from eve.client.script.ui.structure.structureSettings.uiSettingUtil import GetUnit
     90 from eve.client.script.ui.tooltips.tooltipsWrappers import TooltipHeaderDescriptionWrapper
     91 from eve.client.script.ui.util import uix
     92 from eve.common.lib import appConst as const
     93 from eve.common.script.net import eveMoniker
     94 from eve.common.script.sys import eveCfg, idCheckers
     95 from eve.common.script.util import industryCommon
     96 from eve.common.script.util.eveFormat import FmtISK, FmtPlanetAttributeKeyVal
     97 from eve.common.script.util.structuresCommon import IsStationServiceAvailable
     98 from evePathfinder.core import IsUnreachableJumpCount
     99 from eveexceptions import ExceptionEater, UserError
    100 from eveformat import volume_from_type
    101 from eveprefs import prefs
    102 from eveservices.menu import StartMenuService
    103 from eveservices.xmppchat import GetChatService
    104 from evestations.data import service_in_station_operation
    105 from evestations.standingsrestriction import get_station_standings_restriction_info_many
    106 from evetypes.skills import get_types_with_skill_type
    107 from eveuniverse.solar_systems import is_directional_scanner_suppressed
    108 from evewar.warPermitUtil import GetLabelPathForAllowWar
    109 from inventorycommon.util import GetTypeVolume, GetVolumeForPlasticItem
    110 from inventoryrestrictions import is_contractable, can_view_market_details
    111 from itemcompression.data import is_compressible_type, is_compressed_type
    112 from localization import GetByLabel
    113 from npcs.client.components.entity_bounty import get_entity_bounty
    114 from npcs.divisions import get_division_name
    115 from npcs.npccorporations import get_corporation_faction_id
    116 from npcs.npccorporations import get_corporation_ids_by_faction_id
    117 from npcs.npccorporations import get_npc_corporation
    118 from sovereignty.resource.shared.planetary_resources_cache import DataUnavailableError
    119 from sovereignty.upgrades.client.data_types import UpgradeStaticData
    120 from sovereignty.upgrades.client.errors import SovUpgradeDataUnavailableError
    121 from spacecomponents.client import factory
    122 from spacecomponents.client.display import IterAttributeCollectionInInfoOrder
    123 from spacecomponents.common.data import get_space_component_for_type, get_space_component_names_for_type
    124 from spacecomponents.common.helper import GetItemTraderComponent, HasMineableComponent
    125 from stackless_response_router.exceptions import TimeoutException
    126 from structures.services import GetServiceLabel, GetServiceIcon, META_SERVICES, STRUCTURES_WITHOUT_ONLINE_SERVICES, ONLINE_SERVICES
    127 from typematerials.data import is_reprocessable_type
    128 from utillib import KeyVal
    129 GENERIC_ATTRIBUTES_TO_AVOID = (const.attributeMass,)
    130 SUN_STATISTICS_ATTRIBUTES = ['spectralClass',
    131  'luminosity',
    132  'age',
    133  'radius',
    134  'temperature',
    135  'power']
    136 ASTEROID_BELT_STATISTICS_ATTRIBUTES = ['density',
    137  'massDust',
    138  'orbitPeriod',
    139  'orbitRadius',
    140  'eccentricity']
    141 FINISHED_WARS_FOLDER_THRESHOLD = 100
    142 MIN_IN_MS = 60000
    143 MOON_STATISTICS_ATTRIBUTES = ['density',
    144  'escapeVelocity',
    145  'massDust',
    146  'orbitPeriod',
    147  'orbitRadius',
    148  'pressure',
    149  'radius',
    150  'surfaceGravity',
    151  'temperature']
    152 PLANET_STATISTICS_ATTRIBUTES = ['density',
    153  'eccentricity',
    154  'escapeVelocity',
    155  'massDust',
    156  'orbitPeriod',
    157  'orbitRadius',
    158  'pressure',
    159  'radius',
    160  'surfaceGravity',
    161  'temperature']
    162 CELESTIAL_STATISTICS_ATTRIBUTES_BY_GROUPID = {const.groupPlanet: PLANET_STATISTICS_ATTRIBUTES,
    163  const.groupMoon: MOON_STATISTICS_ATTRIBUTES,
    164  const.groupAsteroidBelt: ASTEROID_BELT_STATISTICS_ATTRIBUTES}
    165 DAMAGE_ATTRIBUTES = [const.attributeEmDamage,
    166  const.attributeThermalDamage,
    167  const.attributeKineticDamage,
    168  const.attributeExplosiveDamage]
    169 
    170 class Info(Service):
    171     __exportedcalls__ = {'ShowInfo': [],
    172      'GetAttributeScrollListForType': [],
    173      'GetAttributeScrollListForItem': [],
    174      'GetSolarSystemReport': [],
    175      'GetKillsRecentKills': [],
    176      'GetKillsRecentLosses': [],
    177      'GetEmploymentHistorySubContent': [],
    178      'GetAllianceMembersSubContent': []}
    179     __guid__ = 'svc.info'
    180     __notifyevents__ = ('DoSessionChanging',
    181      'OnItemChange',
    182      'OnAllianceRelationshipChanged',
    183      'OnContactChange',
    184      'OnShowOwnerDetailsWindow')
    185     __servicename__ = 'info'
    186     __displayname__ = 'Information Service'
    187     __dependencies__ = ['dataconfig', 'map']
    188     __startupdependencies__ = ['settings', 'sovHubSvc']
    189 
    190     def Run(self, memStream = None):
    191         self.LogInfo('Starting InfoSvc')
    192         self.wnds = {}
    193         self.rwWindows = []
    194         self.lastActive = {}
    195         self._usedWithTypeIDs = None
    196         self._usedWithInitializing = False
    197         self.TryInitializeUsedWith()
    198         self.ClearWnds()
    199 
    200     def OnItemChange(self, item, change, location):
    201         if item.categoryID != const.categoryCharge and (item.locationID == session.shipid or const.ixLocationID in change and change[const.ixLocationID] == session.shipid):
    202             self.itemchangeTimer = timerstuff.AutoTimer(1000, self.DelayOnItemChange, item, change)
    203         itemGone = False
    204         if const.ixLocationID in change and idCheckers.IsJunkLocation(item.locationID):
    205             itemGone = True
    206         if const.ixQuantity in change and item.stacksize == 0:
    207             log.LogTraceback('infoSvc processing ixQuantity change')
    208             itemGone = True
    209         if const.ixStackSize in change and item.stacksize == 0:
    210             itemGone = True
    211         if itemGone:
    212             for each in self._GetOpenWindowsForType(item.typeID):
    213                 if each is None or each.destroyed:
    214                     self._UnregisterWindow(each)
    215                     continue
    216                 if each.itemID == item.itemID:
    217                     if isinstance(each, self._GetInfoWindowClass(item.typeID)):
    218                         each.ReconstructInfoWindow(each.typeID)
    219 
    220     def GetInfoWindowContentClass(self, type_id, item_id):
    221         if evetypes.GetCategoryID(type_id) == const.categoryShip:
    222             return ShipInfoWindow
    223         if idCheckers.IsCharacter(item_id):
    224             return CharacterInfoWindow
    225         if idCheckers.IsCorporation(item_id):
    226             return CorporationInfoWindow
    227         return InfoWindowMonolith
    228 
    229     def _GetInfoWindowClass(self, type_id):
    230         if evetypes.GetCategoryID(type_id) == const.categoryShip:
    231             return ShipInfoWindow
    232         return InfoWindow
    233 
    234     def GetEnumForInfoWindowType(self, window_type):
    235         if window_type == InfoWindowMonolith:
    236             return InfoTypeEnum.InfoWindowMonolith
    237         if window_type == ShipInfoWindow:
    238             return InfoTypeEnum.Ship
    239         if window_type == CharacterInfoWindow:
    240             return InfoTypeEnum.Character
    241         if window_type == CorporationInfoWindow:
    242             return InfoTypeEnum.Corporation
    243         raise Exception('GetEnumForInfoWindowType unhandled window_type "%s"' % window_type)
    244 
    245     def _GetOpenWindows(self, wndType):
    246         if wndType in self.wnds:
    247             return self.wnds[wndType]
    248         return []
    249 
    250     def _GetOpenWindowsForType(self, typeID):
    251         wndClass = self._GetInfoWindowClass(typeID)
    252         return self._GetOpenWindows(wndClass)
    253 
    254     def _RegisterWindow(self, wnd):
    255         wndType = wnd.__class__
    256         if wndType not in self.wnds:
    257             self.wnds[wndType] = []
    258         self.wnds[wndType].append(wnd)
    259 
    260     def _UnregisterWindow(self, wnd):
    261         wndType = type(wnd)
    262         if wndType in self.wnds:
    263             self.wnds[wndType].remove(wnd)
    264 
    265     def _GetLastActive(self, wndType):
    266         if wndType in self.lastActive:
    267             return self.lastActive[wndType]
    268 
    269     def _SetLastActive(self, wnd):
    270         wndType = wnd.__class__
    271         self.lastActive[wndType] = wnd
    272 
    273     def _ClearLastActive(self, wndType):
    274         if wndType in self.lastActive:
    275             self.lastActive.pop(wndType)
    276 
    277     def DelayOnItemChange(self, item, change):
    278         self.itemchangeTimer = None
    279         for each in self._GetOpenWindowsForType(item.typeID):
    280             if each is None or each.destroyed:
    281                 self._UnregisterWindow(each)
    282                 continue
    283             if each.itemID == session.shipid and not each.IsMinimized() and isinstance(each, self._GetInfoWindowClass(item.typeID)):
    284                 each.ReconstructInfoWindow(each.typeID, each.itemID, each.rec)
    285 
    286     def OnContactChange(self, contactIDs, contactType = None):
    287         for contactID in contactIDs:
    288             self.UpdateWnd(contactID)
    289 
    290     def OnAllianceRelationshipChanged(self, *args):
    291         for allianceid in (args[0], args[1]):
    292             self.UpdateWnd(allianceid)
    293 
    294     def GetStatusAttributeInfo(self):
    295         if not hasattr(self, 'statusAttributeInfo'):
    296             cargoCapacityColor = (0.0, 0.31, 0.4)
    297             shipBayLoadFunc = self.GetShipBayLoad
    298             self.statusAttributeInfo = {const.attributeCpuOutput: {'label': GetByLabel('UI/Common/Cpu'),
    299                                         'loadAttributeID': const.attributeCpuLoad,
    300                                         'color': (0.203125, 0.3828125, 0.37890625, 1.0)},
    301              const.attributePowerOutput: {'label': GetByLabel('UI/Common/Powergrid'),
    302                                           'loadAttributeID': const.attributePowerLoad,
    303                                           'color': (0.40625, 0.078125, 0.03125, 1.0)},
    304              const.attributeUpgradeCapacity: {'label': GetByLabel('UI/Common/Calibration'),
    305                                               'loadAttributeID': const.attributeUpgradeLoad},
    306              const.attributeMaxJumpClones: {'label': GetByLabel('UI/InfoWindow/JumpClonesStatusBar'),
    307                                             'loadAttributeFunc': self.GetCurrentShipCloneCount},
    308              const.attributeCapacity: {'loadAttributeFunc': shipBayLoadFunc,
    309                                        'color': cargoCapacityColor},
    310              const.attributeDroneCapacity: {'label': GetByLabel('UI/Common/DroneBay'),
    311                                             'loadAttributeFunc': shipBayLoadFunc,
    312                                             'color': cargoCapacityColor},
    313              const.attributeSpecialAmmoHoldCapacity: {'label': GetByLabel('UI/Ship/AmmoHold'),
    314                                                       'loadAttributeFunc': shipBayLoadFunc,
    315                                                       'color': cargoCapacityColor},
    316              const.attributeSpecialGasHoldCapacity: {'label': GetByLabel('UI/Ship/GasHold'),
    317                                                      'loadAttributeFunc': shipBayLoadFunc,
    318                                                      'color': cargoCapacityColor},
    319              const.attributeSpecialIndustrialShipHoldCapacity: {'label': GetByLabel('UI/Ship/IndustrialShipHold'),
    320                                                                 'loadAttributeFunc': shipBayLoadFunc,
    321                                                                 'color': cargoCapacityColor},
    322              const.attributeSpecialLargeShipHoldCapacity: {'label': GetByLabel('UI/Ship/LargeShipHold'),
    323                                                            'loadAttributeFunc': shipBayLoadFunc,
    324                                                            'color': cargoCapacityColor},
    325              const.attributeSpecialMediumShipHoldCapacity: {'label': GetByLabel('UI/Ship/MediumShipHold'),
    326                                                             'loadAttributeFunc': shipBayLoadFunc,
    327                                                             'color': cargoCapacityColor},
    328              const.attributeSpecialMineralHoldCapacity: {'label': GetByLabel('UI/Ship/MineralHold'),
    329                                                          'loadAttributeFunc': shipBayLoadFunc,
    330                                                          'color': cargoCapacityColor},
    331              const.attributeGeneralMiningHoldCapacity: {'label': GetByLabel('UI/Ship/GeneralMiningHold'),
    332                                                         'loadAttributeFunc': shipBayLoadFunc,
    333                                                         'color': cargoCapacityColor},
    334              const.attributeSpecialAsteroidHoldCapacity: {'label': GetByLabel('UI/Ship/AsteroidHold'),
    335                                                           'loadAttributeFunc': shipBayLoadFunc,
    336                                                           'color': cargoCapacityColor},
    337              const.attributeSpecialSalvageHoldCapacity: {'label': GetByLabel('UI/Ship/SalvageHold'),
    338                                                          'loadAttributeFunc': shipBayLoadFunc,
    339                                                          'color': cargoCapacityColor},
    340              const.attributeSpecialShipHoldCapacity: {'label': GetByLabel('UI/Ship/ShipHold'),
    341                                                       'loadAttributeFunc': shipBayLoadFunc,
    342                                                       'color': cargoCapacityColor},
    343              const.attributeSpecialSmallShipHoldCapacity: {'label': GetByLabel('UI/Ship/SmallShipHold'),
    344                                                            'loadAttributeFunc': shipBayLoadFunc,
    345                                                            'color': cargoCapacityColor},
    346              const.attributeSpecialCommandCenterHoldCapacity: {'label': GetByLabel('UI/Ship/CommandCenterHold'),
    347                                                                'loadAttributeFunc': shipBayLoadFunc,
    348                                                                'color': cargoCapacityColor},
    349              const.attributeSpecialPlanetaryCommoditiesHoldCapacity: {'label': GetByLabel('UI/Ship/PlanetaryCommoditiesHold'),
    350                                                                       'loadAttributeFunc': shipBayLoadFunc,
    351                                                                       'color': cargoCapacityColor},
    352              const.attributeFleetHangarCapacity: {'label': GetByLabel('UI/Ship/FleetHangar'),
    353                                                   'loadAttributeFunc': shipBayLoadFunc,
    354                                                   'color': cargoCapacityColor},
    355              const.attributeShipMaintenanceBayCapacity: {'label': GetByLabel('UI/Ship/ShipMaintenanceBay'),
    356                                                          'loadAttributeFunc': shipBayLoadFunc,
    357                                                          'color': cargoCapacityColor},
    358              const.attributeSpecialFuelBayCapacity: {'label': GetByLabel('UI/Ship/FuelBay'),
    359                                                      'loadAttributeFunc': shipBayLoadFunc,
    360                                                      'color': cargoCapacityColor},
    361              const.attributeSpecialSubsystemHoldCapacity: {'label': GetByLabel('UI/Ship/SubsystemBay'),
    362                                                            'loadAttributeFunc': shipBayLoadFunc,
    363                                                            'color': cargoCapacityColor},
    364              const.attributeSpecialCorpseHoldCapacity: {'label': GetByLabel('UI/Ship/CorpseBay'),
    365                                                         'loadAttributeFunc': shipBayLoadFunc,
    366                                                         'color': cargoCapacityColor},
    367              const.attributeFrigateEscapeBayCapacity: {'label': GetByLabel('UI/Ship/FrigateEscapeBay'),
    368                                                        'loadAttributeFunc': shipBayLoadFunc,
    369                                                        'color': cargoCapacityColor},
    370              const.attributeSpecialBoosterHoldCapacity: {'label': GetByLabel('UI/Ship/BoosterBay'),
    371                                                          'loadAttributeFunc': shipBayLoadFunc,
    372                                                          'color': cargoCapacityColor},
    373              const.attributeSpecialMobileDepotHoldCapacity: {'label': GetByLabel('UI/Ship/MobileDepotHold'),
    374                                                              'loadAttributeFunc': shipBayLoadFunc,
    375                                                              'color': cargoCapacityColor},
    376              const.attributeSpecialColonyResourcesHoldCapacity: {'label': GetByLabel('UI/Ship/InfrastructureHold'),
    377                                                                  'loadAttributeFunc': shipBayLoadFunc,
    378                                                                  'color': cargoCapacityColor},
    379              const.attributeSpecialExpeditionHoldCapacity: {'label': GetByLabel('UI/Ship/ExpeditionHold'),
    380                                                             'loadAttributeFunc': shipBayLoadFunc,
    381                                                             'color': cargoCapacityColor}}
    382         return self.statusAttributeInfo
    383 
    384     def Stop(self, memStream = None):
    385         self.ClearWnds()
    386         self.lastActive = {}
    387         self.wnds = {}
    388 
    389     def ClearWnds(self):
    390         self.wnds = {}
    391         if getattr(uicore, 'registry', None):
    392             for each in uicore.registry.GetWindows()[:]:
    393                 if each is not None and not each.destroyed and each.windowID and each.windowID in ('infowindow', 'shipInfoWindow'):
    394                     each.Close()
    395 
    396     def DoSessionChanging(self, isremote, session, change):
    397         if session.charid is None:
    398             self.ClearWnds()
    399         if 'charid' in change and change['charid'][1] is None:
    400             self.TryInitializeUsedWith()
    401 
    402     def GetSolarSystemReport(self, solarsystemID = None):
    403         solarsystemID = solarsystemID or session.solarsystemid or session.solarsystemid2
    404         if solarsystemID is None:
    405             return
    406         items = self.map.GetSolarsystemItems(solarsystemID)
    407         types = {}
    408         for celestial in items:
    409             types.setdefault(celestial.groupID, []).append(celestial)
    410 
    411         for groupID in types.iterkeys():
    412             if groupID == const.groupStation:
    413                 continue
    414 
    415     def ShowInfo(self, typeID, itemID = None, new = 0, rec = None, parentID = None, abstractinfo = None, selectTabType = None, addNewWindow = False, traversingHistory = False, params = None):
    416         if itemID == const.factionUnknown:
    417             prompt_player_fsd_dialog('KillerOfUnknownFaction')
    418             return
    419         modal = uicore.registry.GetModalWindow()
    420         createNew = new or not settings.user.ui.Get('useexistinginfownd', 1) or uicore.uilib.Key(uiconst.VK_SHIFT)
    421         self.CleanUpWindows()
    422         self.CleanUpRwWindows()
    423         useWnd = None
    424         wnds = self._GetOpenWindowsForType(typeID)
    425         if len(wnds) and not createNew:
    426             lastActive = self._GetLastActive(typeID)
    427             if lastActive is not None and lastActive in wnds:
    428                 if not lastActive.destroyed:
    429                     useWnd = lastActive
    430             wnd = wnds[-1]
    431             if not modal or modal and modal.parent == wnd.parent:
    432                 if not wnd.destroyed:
    433                     useWnd = wnd
    434         shouldReuseExistingWindow = useWnd and not modal
    435         if shouldReuseExistingWindow and not addNewWindow:
    436             info_type_class = self.GetInfoWindowContentClass(typeID, itemID)
    437             reuse_ship_window = type(useWnd) is info_type_class
    438             if reuse_ship_window:
    439                 param_match = params == useWnd.params
    440                 duplicate_info_window = typeID == useWnd.typeID and itemID == useWnd.itemID
    441             else:
    442                 param_match = params == useWnd.info_content.params
    443                 duplicate_info_window = typeID == useWnd.info_content.type_id and itemID == useWnd.info_content.item_id
    444             reconstruct_legacy = info_type_class == InfoWindowMonolith
    445             if not duplicate_info_window or not param_match or reconstruct_legacy:
    446                 branch_history = not traversingHistory and not duplicate_info_window
    447                 if not reuse_ship_window:
    448                     useWnd.change_info_content(info_type_class)
    449                     useWnd.ConstructLayout()
    450                 useWnd.ReconstructInfoWindow(typeID, itemID, rec=rec, parentID=parentID, abstractinfo=abstractinfo, selectTabType=selectTabType, branchHistory=branch_history, params=params)
    451                 useWnd.Maximize()
    452         else:
    453             useWnd = self.CreateInfoWindow(typeID, itemID, rec, parentID, modal, abstractinfo, selectTabType, params)
    454             self._RegisterWindow(useWnd)
    455         if modal and not modal.destroyed and modal.windowID != 'progresswindow':
    456             useWnd.ShowModal()
    457         return useWnd
    458 
    459     def CloseRwWindows(self):
    460         for each in self.rwWindows:
    461             if each and not each.destroyed:
    462                 each.Close()
    463 
    464         self.rwWindows = []
    465 
    466     def CleanUpWindows(self):
    467         for values in self.wnds.itervalues():
    468             for each in values:
    469                 if each is None or each.destroyed:
    470                     self._UnregisterWindow(each)
    471 
    472     def CleanUpRwWindows(self):
    473         for each in self.rwWindows:
    474             if each is None or each.destroyed:
    475                 self.rwWindows.remove(each)
    476 
    477     def CreateInfoWindow(self, typeID, itemID, rec, parentID, modal, abstractinfo, selectTabType, params = None):
    478         wndClass = self._GetInfoWindowClass(typeID)
    479         if wndClass is ShipInfoWindow:
    480             return wndClass.Open(windowInstanceID=blue.os.GetWallclockTime(), typeID=typeID, itemID=itemID, rec=rec, parentID=parentID, ignoreStack=modal, abstractinfo=abstractinfo, selectTabType=selectTabType, params=params)
    481         else:
    482             wndType = self.GetInfoWindowContentClass(typeID, itemID)
    483             return wndClass.Open(windowInstanceID=blue.os.GetWallclockTime(), typeID=typeID, itemID=itemID, rec=rec, parentID=parentID, ignoreStack=modal, abstractinfo=abstractinfo, selectTabType=selectTabType, params=params, info_type=wndType)
    484 
    485     def UpdateWnd(self, itemID, maximize = 0):
    486         for values in self.wnds.itervalues():
    487             for wnd in values:
    488                 if isinstance(wnd, InfoWindow):
    489                     if wnd.info_content.item_id == itemID or getattr(wnd.sr, 'corpID', None) == itemID or getattr(wnd.sr, 'allianceID', None) == itemID:
    490                         wnd.ReconstructInfoWindow(wnd.info_content.type_id, wnd.info_content.item_id)
    491                         if maximize:
    492                             wnd.Maximize()
    493                         break
    494 
    495     def UnregisterWindow(self, wnd, *args):
    496         self._UnregisterWindow(wnd)
    497         if self._GetLastActive(wnd.__class__) == wnd:
    498             self._ClearLastActive(wnd.__class__)
    499 
    500     def OnActivateWnd(self, wnd):
    501         self._SetLastActive(wnd)
    502 
    503     def GetRankEntry(self, rank, hilite = False):
    504         facwarcurrrank = getattr(rank, 'currentRank', 1)
    505         facwarfaction = getattr(rank, 'factionID', None)
    506         if rank and facwarfaction is not None:
    507             lbl, _ = sm.GetService('facwar').GetRankLabel(facwarfaction, facwarcurrrank)
    508             if hilite:
    509                 lbl = GetByLabel('UI/FactionWarfare/CurrentRank', currentRankName=lbl)
    510             return GetFromClass(RankEntry, {'label': get_faction_name(facwarfaction),
    511              'text': lbl,
    512              'rank': facwarcurrrank,
    513              'warFactionID': facwarfaction,
    514              'selected': False,
    515              'typeID': const.typeRank,
    516              'showinfo': 1,
    517              'line': 1})
    518 
    519     def GetMedalEntry(self, info, details, *args):
    520         d = details
    521         numAwarded = 0
    522         if type(info) == list:
    523             m = info[0]
    524             numAwarded = len(info)
    525         else:
    526             m = info
    527         sublevel = 1
    528         if args:
    529             sublevel = args[0]
    530         medalribbondata = uix.FormatMedalData(d)
    531         title = m.title
    532         if numAwarded > 0:
    533             title = GetByLabel('UI/InfoWindow/MedalAwardedNumTimes', medalName=title, numTimes=numAwarded)
    534         description = m.description
    535         medalTitleText = GetByLabel('UI/InfoWindow/MedalTitle')
    536         return GetFromClass(MedalRibbonEntry, {'label': title,
    537          'text': description,
    538          'sublevel': sublevel,
    539          'id': m.medalID,
    540          'line': 1,
    541          'abstractinfo': medalribbondata,
    542          'typeID': const.typeMedal,
    543          'itemID': m.medalID,
    544          'icon': 'ui_51_64_4',
    545          'showinfo': True,
    546          'sort_%s' % medalTitleText: '_%s' % title.lower(),
    547          'iconsize': 26})
    548 
    549     def EditContact(self, wnd, itemID, edit):
    550         addressBookSvc = sm.GetService('addressbook')
    551         addressBookSvc.AddToPersonalMulti(itemID, 'contact', edit)
    552 
    553     def UpdateContactButtons(self, wnd, itemID):
    554         addressBookSvc = sm.GetService('addressbook')
    555         if not addressBookSvc.IsInAddressBook(itemID, 'contact'):
    556             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/PeopleAndPlaces/AddContact'),
    557               self.EditContact,
    558               (wnd, itemID, False),
    559               81)]
    560         else:
    561             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/PeopleAndPlaces/EditContact'),
    562               self.EditContact,
    563               (wnd, itemID, True),
    564               81)]
    565 
    566     def GetCurrentShipCloneCount(self, attributeID, itemID):
    567         if itemID == eveCfg.GetActiveShip():
    568             return len(sm.GetService('clonejump').GetShipClones())
    569         return 0
    570 
    571     def GetShipBayLoad(self, attributeID, itemID):
    572         attributeToInventoryFlagMap = {const.attributeCapacity: const.flagCargo,
    573          const.attributeDroneCapacity: const.flagDroneBay,
    574          const.attributeFrigateEscapeBayCapacity: const.flagFrigateEscapeBay,
    575          const.attributeSpecialAmmoHoldCapacity: const.flagSpecializedAmmoHold,
    576          const.attributeSpecialGasHoldCapacity: const.flagSpecializedGasHold,
    577          const.attributeSpecialIndustrialShipHoldCapacity: const.flagSpecializedIndustrialShipHold,
    578          const.attributeSpecialLargeShipHoldCapacity: const.flagSpecializedLargeShipHold,
    579          const.attributeSpecialMediumShipHoldCapacity: const.flagSpecializedMediumShipHold,
    580          const.attributeSpecialMineralHoldCapacity: const.flagSpecializedMineralHold,
    581          const.attributeGeneralMiningHoldCapacity: const.flagGeneralMiningHold,
    582          const.attributeSpecialAsteroidHoldCapacity: const.flagSpecialAsteroidHold,
    583          const.attributeSpecialIceHoldCapacity: const.flagSpecializedIceHold,
    584          const.attributeSpecialSalvageHoldCapacity: const.flagSpecializedSalvageHold,
    585          const.attributeSpecialShipHoldCapacity: const.flagSpecializedShipHold,
    586          const.attributeSpecialSmallShipHoldCapacity: const.flagSpecializedSmallShipHold,
    587          const.attributeSpecialCommandCenterHoldCapacity: const.flagSpecializedCommandCenterHold,
    588          const.attributeSpecialPlanetaryCommoditiesHoldCapacity: const.flagSpecializedPlanetaryCommoditiesHold,
    589          const.attributeFleetHangarCapacity: const.flagFleetHangar,
    590          const.attributeShipMaintenanceBayCapacity: const.flagShipHangar,
    591          const.attributeSpecialFuelBayCapacity: const.flagSpecializedFuelBay,
    592          const.attributeSpecialSubsystemHoldCapacity: const.flagSubsystemBay,
    593          const.attributeSpecialCorpseHoldCapacity: const.flagCorpseBay,
    594          const.attributeSpecialBoosterHoldCapacity: const.flagBoosterBay,
    595          const.attributeSpecialMobileDepotHoldCapacity: const.flagMobileDepotHold,
    596          const.attributeSpecialColonyResourcesHoldCapacity: const.flagColonyResourcesHold,
    597          const.attributeSpecialExpeditionHoldCapacity: const.flagExpeditionHold}
    598         dogmaLocation = self.GetDogmaLocation(itemID)
    599         shipID = dogmaLocation.GetActiveShipID()
    600         return dogmaLocation.GetCapacity(shipID, attributeID, attributeToInventoryFlagMap[attributeID]).used
    601 
    602     def GetStatusBarEntryForAttribute(self, attributeID, itemID = None, typeID = None, modifiedAttribute = None):
    603         data = self.GetStatusBarDataForAttribute(attributeID, itemID, typeID, modifiedAttribute)
    604         if data is None:
    605             return
    606         return GetFromClass(StatusBar, data=data)
    607 
    608     def GetStatusBarDataForAttribute(self, attributeID, itemID = None, typeID = None, modifiedAttribute = None):
    609         if itemID is None:
    610             return
    611         if itemID != eveCfg.GetActiveShip() and not self.IsItemSimulated(itemID):
    612             return
    613         statusAttributeInfo = self.GetStatusAttributeInfo().get(attributeID, None)
    614         if statusAttributeInfo is None:
    615             return
    616         GAV = self.GetGAVFunc(itemID, typeID)
    617         total = GAV(attributeID)
    618         if total == 0.0:
    619             return
    620         loadAttributeID = statusAttributeInfo.get('loadAttributeID', attributeID)
    621         loadGetterFunc = statusAttributeInfo.get('loadAttributeFunc', None)
    622         if loadGetterFunc:
    623             load = loadGetterFunc(loadAttributeID, itemID)
    624         else:
    625             load = GAV(loadAttributeID)
    626         status = load / float(total)
    627         attributeFormatInfo = attributeFormat.GetAttribute(attributeID)
    628         return {'attributeID': attributeID,
    629          'label': statusAttributeInfo.get('label', dogma_data.get_attribute_display_name(attributeID)),
    630          'text': GetByLabel('UI/InfoWindow/StatusAttributeLabel', numerator=load, denominator=total, unit=FormatUnit(attributeFormatInfo.unitID)),
    631          'value': status,
    632          'iconID': attributeFormatInfo.iconID,
    633          'color': statusAttributeInfo.get('color', Color.GRAY3),
    634          'gradientBrightnessFactor': 1.2,
    635          'modifiedAttribute': modifiedAttribute,
    636          'itemID': itemID}
    637 
    638     def UpdateDataShip(self, wnd, typeID, itemID):
    639         wnd.dynamicTabs.append(TAB_TRAITS)
    640         attributeEntries, _ = self.GetItemAttributeScrolllistAndAttributesList(itemID, typeID, uiAttributeGroups.category_ship_attribute_group_ids)
    641         wnd.data[TAB_ATTIBUTES]['items'] += attributeEntries
    642         data = self.GetWarpSpeedData(typeID, itemID)
    643         if data:
    644             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
    645         wnd.dynamicTabs.append(TAB_FITTING)
    646         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
    647         if typeID in cfg.certificates['masteries']:
    648             wnd.dynamicTabs.append(TAB_MASTERY)
    649         if sm.GetService('shipTree').IsInShipTree(typeID):
    650             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/InfoWindow/ShowInISIS'),
    651               self.ShowShipInISIS,
    652               typeID,
    653               81)]
    654         wnd.dynamicTabs.append(TAB_SHIPAVAILABLESKINLICENSES)
    655 
    656     def GetWarpSpeedData(self, typeID, itemID):
    657         shipinfo = sm.GetService('godma').GetItem(itemID) if itemID is not None else None
    658         warpSpeedText, warpSpeedWithMultipliers, typeWarpSpeedWithMultipliers, corruptionWarpSpeedIncrease = self.GetBaseWarpSpeed(typeID, shipinfo, itemID)
    659         if warpSpeedText:
    660 
    661             def OnBaseWarpClicked(aID, iID):
    662                 logLine = 'Base warp speed for %s = %s' % (iID, warpSpeedText)
    663                 self.LogError(logLine)
    664                 return self.OnAttributeClick(aID, iID)
    665 
    666             attributeID = const.attributeBaseWarpSpeed
    667             iconID = dogma_data.get_attribute_icon_id(attributeID)
    668             displayName = dogma_data.get_attribute_display_name(attributeID)
    669             data = {'attributeID': attributeID,
    670              'line': 1,
    671              'label': displayName,
    672              'text': warpSpeedText,
    673              'iconID': iconID,
    674              'OnClick': (OnBaseWarpClicked, attributeID, itemID),
    675              'itemID': itemID}
    676             if warpSpeedWithMultipliers != typeWarpSpeedWithMultipliers:
    677                 m = CreateAttribute(attributeID, warpSpeedWithMultipliers, typeWarpSpeedWithMultipliers)
    678                 data['modifiedAttribute'] = m
    679                 data['extraModifyingAttrIDs'] = [const.attributeWarpSpeedMultiplier]
    680                 if not FloatCloseEnough(corruptionWarpSpeedIncrease, 0):
    681                     direction = -1 if corruptionWarpSpeedIncrease < 0.0 else 1
    682                     factorText = GetByLabel('UI/PirateInsurgencies/CorruptionWarpSpeedHint', stageThreshold=WARP_SPEED_INCREASE_STAGE_THRESHOLD)
    683                     data['extraModifyingFactors'] = [(factorText, direction)]
    684             return data
    685 
    686     def ApplyAttributeTooltip(self, entries):
    687         for entry in entries:
    688             if not hasattr(entry, 'attributeID'):
    689                 continue
    690             tooltipTitleText, tooltipDescriptionText = GetAttributeTooltipTitleAndDescription(entry.attributeID)
    691             if tooltipTitleText:
    692                 entry.tooltipPanelClassInfo = TooltipHeaderDescriptionWrapper(header=tooltipTitleText, description=tooltipDescriptionText, tooltipPointer=uiconst.POINT_RIGHT_2)
    693 
    694     def GetGroupedAttributesEntry(self, groupedAttributes, itemID, typeID):
    695         attributeDictForType, attributeDict = self.GetAttributeDictForItem(itemID, typeID)
    696         modifiedAttributesDict = self.FindAttributesThatHaveBeenModified(attributeDictForType, attributeDict)
    697         attributeInfoList = []
    698         for eachAttributeID in groupedAttributes:
    699             if eachAttributeID not in attributeDict:
    700                 dogmaAttributeInfo = attributeFormat.GetAttribute(eachAttributeID)
    701                 if dogmaAttributeInfo.unitID in (const.unitInverseAbsolutePercent, const.unitInversedModifierPercent):
    702                     value = 1
    703                 else:
    704                     value = 0
    705             else:
    706                 value = attributeDict[eachAttributeID]
    707             formatInfo = GetFormattedAttributeAndValue(eachAttributeID, value)
    708             if not formatInfo:
    709                 attributeInfoList.append(None)
    710                 continue
    711             attributeTypeInfoUnitID = dogma_data.get_attribute_unit_id(eachAttributeID)
    712             if attributeTypeInfoUnitID in (const.unitInverseAbsolutePercent, const.unitInversedModifierPercent):
    713                 value = 1 - value
    714             modifiedAttribute = modifiedAttributesDict.get(eachAttributeID)
    715             attributeInfo = {'text': formatInfo.displayName,
    716              'iconID': formatInfo.iconID,
    717              'value': value,
    718              'valueText': formatInfo.value,
    719              'attributeID': eachAttributeID,
    720              'modifiedAttribute': modifiedAttribute,
    721              'itemID': itemID}
    722             attributeInfoList.append(attributeInfo)
    723 
    724         return GetFromClass(DamageEntry, {'attributeInfoList': attributeInfoList,
    725          'OnClick': lambda attributeID: self.OnAttributeClick(attributeID, itemID)})
    726 
    727     def ShowShipInISIS(self, typeID):
    728         sm.GetService('shipTreeUI').OpenAndShowShip(typeID)
    729 
    730     def UpdateSkyhook(self, wnd, typeID, itemID):
    731         attributeScroll = wnd.data[TAB_ATTIBUTES]['items']
    732         attributeScroll.append(GetFromClass(Header, {'label': GetByLabel('UI/Common/Other')}))
    733         slimitem = sm.GetService('michelle').GetItem(itemID)
    734         banAttrs = self.GetAttributesSuppressedByComponents(typeID)
    735         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=banAttrs)
    736         attributeScroll += attributeScrollListForItem
    737         if slimitem and slimitem.planetID:
    738             planetSlimItem = sm.GetService('michelle').GetItem(slimitem.planetID)
    739             data = {'line': 1,
    740              'label': evetypes.GetGroupName(planetSlimItem.typeID),
    741              'text': cfg.evelocations.Get(slimitem.planetID).name,
    742              'typeID': planetSlimItem.typeID,
    743              'itemID': planetSlimItem.itemID}
    744             attributeScroll.append(GetFromClass(LabelTextSidesAttributes, data=data))
    745         uthread.new(self.FetchDynamicOrbitalAttributes, wnd, wnd.data[TAB_ATTIBUTES], itemID)
    746 
    747     def UpdateSequenceBinder(self, wnd, typeID, itemID):
    748         wnd.data[DATA_BUTTONS].append((GetByLabel('UI/Personalization/ShipSkins/OpenSKINR'),
    749          uicore.cmd.OpenShipSKINRWindow,
    750          (),
    751          None,
    752          False,
    753          False,
    754          False,
    755          None,
    756          None,
    757          Button,
    758          None,
    759          None,
    760          None,
    761          None,
    762          None,
    763          OPEN_SKINR_BUTTON_INFO_WINDOW_ANALYTIC_ID))
    764 
    765     def UpdateDesignElement(self, wnd, typeID, itemID):
    766         wnd.data[DATA_BUTTONS].append((GetByLabel('UI/Personalization/ShipSkins/OpenSKINR'),
    767          uicore.cmd.OpenShipSKINRWindow,
    768          (),
    769          None,
    770          False,
    771          False,
    772          False,
    773          None,
    774          None,
    775          Button,
    776          None,
    777          None,
    778          None,
    779          None,
    780          None,
    781          OPEN_SKINR_BUTTON_INFO_WINDOW_ANALYTIC_ID))
    782 
    783     def UpdateStructure(self, wnd, typeID, itemID):
    784         if itemID and isinstance(itemID, long):
    785             wnd.dynamicTabs.append(TAB_DESCRIPTION_DYNAMIC)
    786         wnd.dynamicTabs.append(TAB_TRAITS)
    787         attributeEntries, addedAttributes = self.GetItemAttributeScrolllistAndAttributesList(itemID, typeID, uiAttributeGroups.category_ship_attribute_group_ids)
    788         wnd.data[TAB_ATTIBUTES]['items'] += attributeEntries
    789         fittingAttributes = list(dogma_attr_groups.fitting_attribute_ids) + [const.attributeCpuLoad, const.attributePowerLoad]
    790         banAttrs = addedAttributes + self.GetSkillAttrs() + fittingAttributes
    791         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID, typeID, banAttrs=banAttrs)
    792         if attributeScrollListForItem:
    793             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/Miscellaneous')}))
    794             wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
    795         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
    796         wnd.dynamicTabs.append(TAB_FITTING)
    797         structureInfo = None
    798         structureOwner = None
    799         outOfCommissionText = '<b><color=red>%s</color></b>' % GetByLabel('UI/Structures/StructureOutOfCommission')
    800         if itemID is not None:
    801             structureInfo = sm.GetService('structureDirectory').GetStructureInfo(itemID)
    802             if structureInfo:
    803                 structureOwner = structureInfo.ownerID
    804                 solarsystemID = structureInfo.solarSystemID
    805                 mapData = cfg.mapSystemCache.Get(solarsystemID)
    806                 constellationID = mapData.constellationID
    807                 regionID = mapData.regionID
    808                 if not structureInfo.inSpace:
    809                     wnd.data[TAB_LOCATION]['items'].append(GetFromClass(Text, {'line': 1,
    810                      'text': outOfCommissionText}))
    811                 for locID in [regionID, constellationID, solarsystemID]:
    812                     mapItem = self.map.GetItem(locID)
    813                     if mapItem is not None:
    814                         if mapItem.typeID == const.typeSolarSystem:
    815                             text = self.GetColorCodedSecurityStringForSystem(mapItem.itemID, mapItem.itemName)
    816                             text = text.replace('<t>', ' ')
    817                         else:
    818                             text = mapItem.itemName
    819                         entry = GetFromClass(LabelTextTop, {'line': 1,
    820                          'label': evetypes.GetName(mapItem.typeID),
    821                          'text': text,
    822                          'typeID': mapItem.typeID,
    823                          'itemID': mapItem.itemID})
    824                         wnd.data[TAB_LOCATION]['items'].append(entry)
    825 
    826         if itemID is not None and structureInfo is not None:
    827             serviceEntryList = self.GetServicesForStructure(itemID, typeID)
    828             if not structureInfo.inSpace:
    829                 wnd.data[TAB_SERVICES]['items'].append(GetFromClass(Text, {'line': 1,
    830                  'text': outOfCommissionText}))
    831             wnd.data[TAB_SERVICES]['items'] += serviceEntryList
    832             wars = getattr(structureInfo, 'wars', None)
    833             if wars:
    834                 wnd.dynamicTabs.append(TAB_WARHQ)
    835         if structureInfo and evetypes.IsUpwellStargate(typeID):
    836             destinations = sm.RemoteSvc('structureJumpBridgeMgr').GetLinkedStructure(itemID)
    837             if destinations:
    838                 destinationStructureID, destinationSolarsystemID = destinations
    839                 structureInfo = sm.GetService('structureDirectory').GetStructureInfo(destinationStructureID)
    840                 if structureInfo:
    841                     structureLink = GetShowInfoLink(structureInfo.typeID, structureInfo.itemName, destinationStructureID)
    842                     destLabel = GetByLabel('UI/InfoWindow/DestinationJumpBridgeInSolarsystem', structureLink=structureLink, solarsystem=destinationSolarsystemID)
    843                     wnd.data[TAB_JUMPS]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
    844                      'label': GetByLabel('UI/Common/Jump'),
    845                      'text': destLabel,
    846                      'typeID': const.groupSolarSystem,
    847                      'itemID': destinationSolarsystemID}))
    848         if structureOwner is not None:
    849             wnd.data[DATA_BUTTONS] = [(GetByLabel('UI/Inflight/SetDestination'),
    850               self.SetDestination,
    851               (itemID,),
    852               81)]
    853 
    854     def GetServicesForStructure(self, structureID, typeID):
    855         serviceList = []
    856         servicesAndValues = sm.GetService('structureServices').CharacterGetServices(structureID).items()
    857         for serviceID, settingValue in sorted(servicesAndValues):
    858             if serviceID in META_SERVICES:
    859                 continue
    860             if typeID in STRUCTURES_WITHOUT_ONLINE_SERVICES and serviceID in ONLINE_SERVICES:
    861                 continue
    862             valueText = self._GetValueText(serviceID, settingValue)
    863             if valueText is None:
    864                 continue
    865             icon = GetServiceIcon(serviceID)
    866             if icon is None:
    867                 icon = stationServiceConst.serviceDataByServiceID[serviceID].iconID
    868             serviceList.append(GetFromClass(LabelTextSides, {'line': 2,
    869              'selectable': 0,
    870              'label': GetByLabel(GetServiceLabel(serviceID)),
    871              'iconID': icon,
    872              'iconsize': 24,
    873              'height': 28,
    874              'iconoffset': 8,
    875              'labeloffset': 8,
    876              'text': valueText}))
    877 
    878         return serviceList
    879 
    880     def _GetValueText(self, serviceID, settingValue):
    881         settingIDForService = structures.SERVICES_ACCESS_SETTINGS.get(serviceID, None)
    882         if settingIDForService is None:
    883             return
    884         settingInfo = structures.SETTING_OBJECT_BY_SETTINGID.get(settingIDForService, None)
    885         if not settingInfo:
    886             return
    887         valueText = ''
    888         settingType = settingInfo.valueType
    889         if settingType in VALUE_TYPES:
    890             unit = GetUnit(settingType)
    891             value = settingValue
    892             if settingType == structures.SETTINGS_TYPE_ISK:
    893                 valueText = FmtISK(value, 0)
    894             elif settingType == structures.SETTINGS_TYPE_PERCENTAGE:
    895                 if settingInfo.decimals == 2:
    896                     valueText = GetByLabel('UI/Common/Formatting/PercentageDecimals2', percentage=value)
    897                 else:
    898                     valueText = GetByLabel('UI/Common/Formatting/PercentageDecimal', percentage=value)
    899             else:
    900                 if settingType == structures.SETTINGS_TYPE_INT:
    901                     value = int(value)
    902                 valueText = '%s %s' % (value, unit)
    903         return valueText
    904 
    905     def UpdateDataDrone(self, wnd, typeID, itemID):
    906         attributeEntries, addedAttributes = self.GetItemAttributeScrolllistAndAttributesList(itemID, typeID, uiAttributeGroups.category_drone_attribute_group_ids)
    907         wnd.data[TAB_ATTIBUTES]['items'] += attributeEntries
    908         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID, typeID, banAttrs=addedAttributes + self.GetSkillAttrs())
    909         if attributeScrollListForItem:
    910             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/Miscellaneous')}))
    911             wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
    912         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
    913 
    914     def UpdateDataFighter(self, wnd, typeID, itemID):
    915         attributeEntries, addedAttributes = self.GetItemAttributeScrolllistAndAttributesList(itemID, typeID, uiAttributeGroups.category_figther_attribute_group_ids)
    916         wnd.data[TAB_ATTIBUTES]['items'] += attributeEntries
    917         wnd.dynamicTabs.append(TAB_FIGHTER_ABILITIES)
    918         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
    919 
    920     def GetItemAttributeScrolllistAndAttributesList(self, itemID, typeID, attribute_group_ids):
    921         attrDict = self.GetAttributeDictForType(typeID)
    922         addedAttributes = []
    923         scrollList = []
    924         for attr_group_id in attribute_group_ids:
    925             attrs = uiAttributeGroups.attribute_ids_by_attribute_group_id[attr_group_id]
    926             normalAttributes = [ a for a in attrs if a not in dogma_attr_groups.grouped_attributes ]
    927             groupedAttributes = [ a for a in attrs if a in dogma_attr_groups.grouped_attributes ]
    928             shipAttr = [ each for each in normalAttributes if each in attrDict ]
    929             newEntries = []
    930             if shipAttr:
    931                 attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, attrList=shipAttr)
    932                 newEntries += attributeScrollListForItem
    933                 addedAttributes += [ x.attributeID for x in attributeScrollListForItem ]
    934                 for eachNode in attributeScrollListForItem:
    935                     if getattr(eachNode, 'attributeIDs', None):
    936                         addedAttributes += eachNode.attributeIDs
    937 
    938             if groupedAttributes:
    939                 entry = self.GetGroupedAttributesEntry(groupedAttributes, itemID, typeID)
    940                 addedAttributes += groupedAttributes
    941                 newEntries.append(entry)
    942             if newEntries:
    943                 scrollList.append(GetFromClass(Header, {'label': GetByLabel(uiAttributeGroups.name_by_group_id[attr_group_id])}))
    944                 scrollList += newEntries
    945 
    946         return (scrollList, addedAttributes)
    947 
    948     def UpdateDataModule(self, wnd, typeID, itemID):
    949         if not itemID:
    950             damageTypes = dogma_data.get_type_attributes(typeID)
    951             firstAmmoLoaded = itertoolsext.first_or_default([ x for x in damageTypes if x.attributeID == const.attributeAmmoLoaded ])
    952             if firstAmmoLoaded:
    953                 damageScrollList = self.GetAttributeScrollListForType(typeID=firstAmmoLoaded.value, attrList=DAMAGE_ATTRIBUTES)
    954                 wnd.data[TAB_ATTIBUTES]['items'] += damageScrollList
    955         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=[const.attributeCpu,
    956          const.attributePower,
    957          const.attributeRigSize,
    958          const.attributeUpgradeCost,
    959          const.attributeMass] + self.GetSkillAttrs())
    960         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
    961         wnd.data[TAB_ATTIBUTES]['items'] += GetDbuffInfoEntriesForItem(itemID, typeID)
    962         effectTypeScrollList = self.GetEffectTypeInfo(typeID=typeID, effList=[const.effectHiPower,
    963          const.effectMedPower,
    964          const.effectLoPower,
    965          const.effectRigSlot,
    966          const.effectSubSystem,
    967          const.effectServiceSlot,
    968          const.effectTurretFitted,
    969          const.effectLauncherFitted])
    970         wnd.data[TAB_FITTING]['items'] += effectTypeScrollList
    971         fittingScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, attrList=(const.attributeCpu,
    972          const.attributePower,
    973          const.attributeRigSize,
    974          const.attributeServiceSlots,
    975          const.attributeUpgradeCost))
    976         wnd.data[TAB_FITTING]['items'] += fittingScrollListForItem
    977         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
    978         wnd.dynamicTabs.append(TAB_TRAITS)
    979         if self.GetUsedWithTypeIDs(wnd.type_id):
    980             wnd.dynamicTabs.append(TAB_USEDWITH)
    981 
    982     def UpdateComponentData(self, content, typeID, itemID):
    983         attributeScroll = content.data[TAB_ATTIBUTES]['items']
    984         spaceComponentScrollList = self.GetSpaceComponentAttrItemInfo(typeID, itemID)
    985         attributeScroll += spaceComponentScrollList
    986 
    987     def UpdateInfrastructureUpgrades(self, wnd, typeID, itemID):
    988         try:
    989             staticInfo = self.sovHubSvc.GetStaticDataForUpgrade(typeID)
    990         except (SovUpgradeDataUnavailableError, TimeoutException):
    991             return
    992 
    993         if staticInfo is None:
    994             return
    995         consumptionsAttributeEntries = []
    996         if staticInfo.power:
    997             consumptionsAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/PowerCost'),
    998              'text': staticInfo.power}))
    999         if staticInfo.workforce:
   1000             consumptionsAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/WorkforceCost'),
   1001              'text': staticInfo.workforce}))
   1002         if staticInfo.fuel_type_id and (staticInfo.consumption_per_hour or staticInfo.startup_cost):
   1003             consumptionsAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/FuelType'),
   1004              'text': evetypes.GetName(staticInfo.fuel_type_id),
   1005              'iconID': evetypes.GetIconID(staticInfo.fuel_type_id),
   1006              'typeID': staticInfo.fuel_type_id}))
   1007             consumptionsAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/FuelStartupCost'),
   1008              'text': localization.GetByLabel('UI/InfoWindow/ValueAndUnit', value=staticInfo.startup_cost, unit=FormatUnit(const.unitUnits))}))
   1009             consumptionsAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/FuelConsumptionPerHour'),
   1010              'text': localization.GetByLabel('UI/InfoWindow/ValueAndUnit', value=staticInfo.consumption_per_hour, unit=FormatUnit(const.unitUnits))}))
   1011         if consumptionsAttributeEntries:
   1012             consumptionsAttributeEntries.insert(0, GetFromClass(Header, {'label': GetByLabel('UI/Sovereignty/SovHub/Upgrades/ResourceConsumption')}))
   1013         generationAttributeEntries = []
   1014         if staticInfo.power_produced:
   1015             generationAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/PowerProduction'),
   1016              'text': staticInfo.power_produced}))
   1017         if staticInfo.workforce_produced:
   1018             generationAttributeEntries.append(GetFromClass(LabelTextSides, {'label': localization.GetByLabel('UI/Sovereignty/SovHub/Upgrades/WorkforceProduction'),
   1019              'text': staticInfo.workforce_produced}))
   1020         if generationAttributeEntries:
   1021             generationAttributeEntries.insert(0, GetFromClass(Header, {'label': GetByLabel('UI/Sovereignty/SovHub/Upgrades/ResourceProduction')}))
   1022         attributeEntries = consumptionsAttributeEntries + generationAttributeEntries
   1023         attributeScroll = wnd.data[TAB_ATTIBUTES]['items']
   1024         attributeScroll += attributeEntries
   1025 
   1026     def UpdateDataDeployable(self, wnd, typeID, itemID):
   1027         attributeScroll = wnd.data[TAB_ATTIBUTES]['items']
   1028         banAttrs = self.GetAttributesSuppressedByComponents(typeID)
   1029         banAttrs.extend(self.GetSkillAttrs())
   1030         attributeScroll.append(GetFromClass(Header, {'label': GetByLabel('UI/Common/Other')}))
   1031         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=banAttrs)
   1032         attributeScroll += attributeScrollListForItem
   1033         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
   1034 
   1035     def UpdateDataSecureContainer(self, wnd, itemID):
   1036         self.UpdateDataModule(wnd, wnd.type_id, itemID)
   1037         bp = sm.GetService('michelle').GetBallpark()
   1038         if not bp:
   1039             return
   1040         ball = bp.GetBall(itemID)
   1041         if not ball or ball.isFree:
   1042             return
   1043         bpr = sm.GetService('michelle').GetRemotePark()
   1044         if bpr:
   1045             expiry = bpr.GetContainerExpiryDate(itemID)
   1046             daysLeft = max(0, (expiry - blue.os.GetWallclockTime()) / const.DAY)
   1047             expiryText = GetByLabel('UI/Common/NumDays', numDays=daysLeft)
   1048             expiryLabel = GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1049              'label': GetByLabel('UI/Common/Expires'),
   1050              'text': expiryText,
   1051              'iconID': const.iconDuration})
   1052             wnd.data[TAB_ATTIBUTES]['items'].append(expiryLabel)
   1053 
   1054     def UpdateDataCharge(self, wnd, typeID, itemID):
   1055         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=self.GetSkillAttrs())
   1056         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   1057         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
   1058         wnd.data[TAB_ATTIBUTES]['items'] += GetDbuffInfoEntriesForItem(itemID, typeID)
   1059         if self.GetUsedWithTypeIDs(wnd.type_id):
   1060             wnd.dynamicTabs.append(TAB_USEDWITH)
   1061 
   1062     @telemetry.ZONE_METHOD
   1063     def AddUsedWithForOneTypeAndTryConstructForAll(self, typeID):
   1064         if evetypes.GetCategoryID(typeID) == const.categoryCharge:
   1065             self._AddUsedWithForAmmoTypeID(typeID)
   1066         else:
   1067             self._AddUsedWithTypeIDs([typeID])
   1068         self.TryInitializeUsedWith()
   1069 
   1070     def TryInitializeUsedWith(self):
   1071         if not session.charid:
   1072             return
   1073         if not self._usedWithInitializing:
   1074             self._usedWithInitializing = True
   1075             uthread.new(self.ConstructUsedWithAllTypeIDs)
   1076 
   1077     @telemetry.ZONE_METHOD
   1078     def ConstructUsedWithAllTypeIDs(self):
   1079         try:
   1080             typeIDs = evetypes.GetTypeIDsByCategories((const.categoryModule, const.categoryStructureModule))
   1081             self._AddUsedWithTypeIDs(typeIDs)
   1082         finally:
   1083             self._usedWithInitializing = False
   1084 
   1085     @telemetry.ZONE_METHOD
   1086     def _AddUsedWithTypeIDs(self, typeIDs):
   1087         usedWith = defaultdict(set)
   1088         godmaStateManager = sm.GetService('godma').GetStateManager()
   1089         for typeID in typeIDs:
   1090             if not evetypes.IsPublished(typeID):
   1091                 continue
   1092             godmaType = godmaStateManager.GetType(typeID)
   1093             for attrName in ('chargeGroup1', 'chargeGroup2', 'chargeGroup3', 'chargeGroup4'):
   1094                 if not godmaType.AttributeExists(attrName):
   1095                     continue
   1096                 groupID = getattr(godmaType, attrName)
   1097                 if not evetypes.GroupExists(groupID):
   1098                     continue
   1099                 for typeIDInGroup in evetypes.GetTypeIDsByGroup(groupID):
   1100                     if not evetypes.IsPublished(typeIDInGroup):
   1101                         continue
   1102                     if hasattr(godmaType, 'capacity') and godmaType.capacity < evetypes.GetVolume(typeIDInGroup):
   1103                         continue
   1104                     chargeGodmaType = godmaStateManager.GetType(typeIDInGroup)
   1105                     if not godmaType.chargeSize or chargeGodmaType.chargeSize == godmaType.chargeSize:
   1106                         usedWith[typeIDInGroup].add(typeID)
   1107                         usedWith[typeID].add(typeIDInGroup)
   1108 
   1109             blue.pyos.BeNice()
   1110 
   1111         if self._usedWithTypeIDs is None:
   1112             self._usedWithTypeIDs = usedWith
   1113         else:
   1114             self._usedWithTypeIDs.update(usedWith)
   1115 
   1116     def _AddUsedWithForAmmoTypeID(self, chargeTypeID):
   1117         if not evetypes.IsPublished(chargeTypeID):
   1118             return
   1119         dogmaStaticMgr = sm.GetService('clientDogmaStaticSvc')
   1120         launcherGroupAttributes = [const.attributeLauncherGroup,
   1121          const.attributeLauncherGroup2,
   1122          const.attributeLauncherGroup3,
   1123          const.attributeLauncherGroup4,
   1124          const.attributeLauncherGroup5,
   1125          const.attributeLauncherGroup6]
   1126         moduleTypeIDs = set()
   1127         for attributeID in launcherGroupAttributes:
   1128             launhcerGroupID = dogmaStaticMgr.GetTypeAttribute(chargeTypeID, attributeID)
   1129             if launhcerGroupID is None:
   1130                 continue
   1131             moduleTypeIDs.update(evetypes.GetTypeIDsByGroup(int(launhcerGroupID)))
   1132 
   1133         self._AddUsedWithTypeIDs(moduleTypeIDs)
   1134 
   1135     @telemetry.ZONE_METHOD
   1136     def GetUsedWithTypeIDs(self, typeID):
   1137         if self._usedWithTypeIDs is None:
   1138             self.AddUsedWithForOneTypeAndTryConstructForAll(typeID)
   1139         return self._usedWithTypeIDs.get(typeID, None)
   1140 
   1141     def UpdateDataCharacter(self, wnd, typeID, itemID):
   1142         if not idCheckers.IsNPC(itemID):
   1143             if session.charid != itemID:
   1144                 wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Chat/StartConversation'), lambda : GetChatService().Invite(itemID))]
   1145                 self.UpdateContactButtons(wnd, itemID)
   1146             wnd.dynamicTabs.append(TAB_EMPLOYMENTHISTORY)
   1147             self.UpdateDataDecorations(wnd, typeID, itemID)
   1148         else:
   1149             self.UpdateDataAgent(wnd, typeID, itemID)
   1150         wnd.dynamicTabs.append(TAB_NOTES)
   1151         if itemID != session.charid:
   1152             wnd.dynamicTabs.append(TAB_STANDINGS)
   1153 
   1154     def UpdateDataDecorations(self, wnd, typeID, itemID):
   1155         medalsEntries = GetMedalScrollEntries(itemID, True, True)
   1156         wnd.data[TAB_MEDALS]['items'] = medalsEntries
   1157         rank = sm.GetService('facwar').GetCharacterRankInfo(itemID)
   1158         if rank:
   1159             wnd.data[TAB_RANKS]['items'].append(self.GetRankEntry(rank))
   1160         if not medalsEntries and not rank:
   1161             wnd.dynamicTabs.append(TAB_DECORATIONS)
   1162 
   1163     def UpdateDataCorp(self, wnd, typeID, itemID):
   1164         if not idCheckers.IsNPC(itemID):
   1165             self.UpdateContactButtons(wnd, itemID)
   1166             wnd.dynamicTabs.append(TAB_ALLIANCEHISTORY)
   1167             wnd.dynamicTabs.append(TAB_WARHISTORY)
   1168             wnd.dynamicTabs.append(TAB_FREELANCE_PROJECTS)
   1169         parallelCalls = []
   1170         parallelCalls.append((sm.RemoteSvc('config').GetStationSolarSystemsByOwner, (itemID,)))
   1171         if idCheckers.IsNPC(itemID):
   1172             parallelCalls.append((sm.RemoteSvc('corporationSvc').GetCorpInfo, (itemID,)))
   1173         else:
   1174             parallelCalls.append((lambda : None, ()))
   1175         parallelCalls.append((get_npc_corporation, (itemID,)))
   1176         systems, corpmktinfo, npcCorpInfo = uthread.parallel(parallelCalls)
   1177         if npcCorpInfo and getattr(npcCorpInfo, 'factionID', None):
   1178             wnd.dynamicTabs.append(TAB_WARHISTORY)
   1179         founderdone = 0
   1180         if evetypes.GetGroupID(cfg.eveowners.Get(wnd.corp_info.ceoID).typeID) == const.groupCharacter:
   1181             if wnd.corp_info.creatorID == wnd.corp_info.ceoID:
   1182                 ceoLabel = GetByLabel('UI/Corporations/CorpUIHome/CeoAndFounder')
   1183                 founderdone = 1
   1184             else:
   1185                 ceoLabel = GetByLabel('UI/Corporations/Common/CEO')
   1186             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1187              'label': ceoLabel,
   1188              'text': cfg.eveowners.Get(wnd.corp_info.ceoID).name,
   1189              'typeID': cfg.eveowners.Get(wnd.corp_info.ceoID).typeID,
   1190              'itemID': wnd.corp_info.ceoID}))
   1191         if not founderdone and evetypes.GetGroupID(cfg.eveowners.Get(wnd.corp_info.creatorID).typeID) == const.groupCharacter:
   1192             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1193              'label': GetByLabel('UI/Corporations/Common/Founder'),
   1194              'text': cfg.eveowners.Get(wnd.corp_info.creatorID).name,
   1195              'typeID': cfg.eveowners.Get(wnd.corp_info.creatorID).typeID,
   1196              'itemID': wnd.corp_info.creatorID}))
   1197         if wnd.corp_info.allianceID:
   1198             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1199              'label': GetByLabel('UI/Common/Alliance'),
   1200              'text': cfg.eveowners.Get(wnd.corp_info.allianceID).name,
   1201              'typeID': const.typeAlliance,
   1202              'itemID': wnd.corp_info.allianceID}))
   1203         for configName, label in [('tickerName', GetByLabel('UI/Corporations/CorpUIHome/TickerName')),
   1204          ('shares', GetByLabel('UI/Corporations/CorpUIHome/Shares')),
   1205          ('memberCount', GetByLabel('UI/Corporations/CorpUIHome/MemberCount')),
   1206          ('taxRate', GetByLabel('UI/Corporations/CorpUIHome/ISKTaxRate')),
   1207          ('loyaltyPointTaxRate', GetByLabel('UI/Corporations/CorpUIHome/LPTaxRate')),
   1208          ('friendlyFire', GetByLabel('UI/Corporations/CorpUIHome/FriendlyFire'))]:
   1209             if configName == 'memberCount' and idCheckers.IsNPC(itemID):
   1210                 continue
   1211             val = getattr(wnd.corp_info, configName, 0.0)
   1212             decoClass = LabelTextSidesAttributes
   1213             moreInfoHint = ''
   1214             if configName == 'taxRate':
   1215                 val = GetByLabel('UI/Common/Percentage', percentage=val * 100)
   1216                 decoClass = LabelTextSidesMoreInfo
   1217                 min_isk_amount_text = FmtWalletCurrency(amt=const.minCorporationTaxAmount, currency=const.creditsISK)
   1218                 moreInfoHint = GetByLabel('UI/Corporations/BaseCorporationUI/ISKTaxRateDescription', min_isk_amount=min_isk_amount_text)
   1219             elif configName == 'loyaltyPointTaxRate':
   1220                 val = GetByLabel('UI/Common/Percentage', percentage=val * 100)
   1221                 decoClass = LabelTextSidesMoreInfo
   1222                 moreInfoHint = GetByLabel('UI/Corporations/BaseCorporationUI/LPTaxRateDescription')
   1223             elif isinstance(val, int):
   1224                 val = localization.formatters.FormatNumeric(val, useGrouping=True, decimalPlaces=0)
   1225             elif configName == 'friendlyFire':
   1226                 corpsvc = sm.GetService('corp')
   1227                 statusText = corpsvc.GetCorpFriendlyFireStatus(corpsvc.GetAggressionSettings(itemID))
   1228                 val = statusText
   1229                 decoClass = LabelTextSidesMoreInfo
   1230                 moreInfoHint = GetByLabel('UI/Corporations/FriendlyFire/Description')
   1231             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(decoClass, {'line': 1,
   1232              'label': label,
   1233              'text': val,
   1234              'moreInfoHint': moreInfoHint}))
   1235 
   1236         if not idCheckers.IsNPC(itemID):
   1237             allowedFactionIDs = sm.GetService('fwEnlistmentSvc').GetCorpAllowedEnlistmentFactions(itemID)
   1238             factionNames = sorted([ cfg.eveowners.Get(factionID).name for factionID in allowedFactionIDs ])
   1239             rightTextLabels = [ (x, None) for x in factionNames ] or [(GetByLabel('UI/Corporations/CorpUIHome/NoFwFactionsPermitted'), None)]
   1240             label = GetByLabel('UI/Corporations/CorpUIHome/PermittedFwFactions')
   1241             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelMultilineTextTop, {'label': label,
   1242              'rightTextLabels': rightTextLabels}))
   1243             allowWar = getattr(wnd.corp_info, 'allowWar', None)
   1244             label = GetByLabel('UI/WarPermit/WarPermitStatus')
   1245             text = GetByLabel(GetLabelPathForAllowWar(allowWar))
   1246             moreInfoHint = GetByLabel('UI/WarPermit/WarPermitExplanation')
   1247             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesMoreInfo, {'line': 1,
   1248              'label': label,
   1249              'text': text,
   1250              'moreInfoHint': moreInfoHint}))
   1251         if wnd.corp_info.url:
   1252             linkTag = '<url=%s>' % wnd.corp_info.url
   1253             url = GetByLabel('UI/Corporations/CorpUIHome/URLPlaceholder', linkTag=linkTag, url=wnd.corp_info.url)
   1254             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1255              'label': GetByLabel('UI/Corporations/CorpUIHome/URL'),
   1256              'text': url}))
   1257         if npcCorpInfo is not None and idCheckers.IsNPC(itemID):
   1258             sizeDict = {'T': GetByLabel('UI/Corporations/TinyCorp'),
   1259              'S': GetByLabel('UI/Corporations/SmallCorp'),
   1260              'M': GetByLabel('UI/Corporations/MediumCorp'),
   1261              'L': GetByLabel('UI/Corporations/LargeCorp'),
   1262              'H': GetByLabel('UI/Corporations/HugeCorp')}
   1263             txt = sizeDict[npcCorpInfo.size]
   1264             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1265              'label': GetByLabel('UI/Corporations/CorpSize'),
   1266              'text': txt}))
   1267             extentDict = {'N': GetByLabel('UI/Corporations/NationalCrop'),
   1268              'G': GetByLabel('UI/Corporations/GlobalCorp'),
   1269              'R': GetByLabel('UI/Corporations/RegionalCorp'),
   1270              'L': GetByLabel('UI/Corporations/LocalCorp'),
   1271              'C': GetByLabel('UI/Corporations/ConstellationCorp')}
   1272             txt = extentDict[npcCorpInfo.extent]
   1273             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1274              'label': GetByLabel('UI/Corporations/CorpExtent'),
   1275              'text': txt}))
   1276         if itemID == session.corpid:
   1277             for charinfo in sm.GetService('corp').GetMembersAsEveOwners():
   1278                 if not idCheckers.IsNPC(charinfo.ownerID):
   1279                     entry = GetFromClass(User, {'info': charinfo,
   1280                      'charID': charinfo.ownerID})
   1281                     wnd.data[TAB_CORPMEMBERS]['items'].append(entry)
   1282 
   1283             wnd.data[TAB_CORPMEMBERS]['headers'].append(GetByLabel('UI/Common/NameCharacter'))
   1284         solarSystemDict = {}
   1285         corpName = cfg.eveowners.Get(itemID).name
   1286         mapHintCallback = lambda : GetByLabel('UI/InfoWindow/SystemSettledByCorp', corpName=corpName)
   1287         for solarSys in systems:
   1288             solarSystemDict[solarSys.solarSystemID] = (2.0,
   1289              1.0,
   1290              (mapHintCallback, ()),
   1291              None)
   1292 
   1293         pathfinder = sm.GetService('clientPathfinderService')
   1294         stationIDs = set()
   1295         stationIDsBySolarSystemID = {}
   1296         solarSystems = []
   1297         for solarSys in systems:
   1298             solarSystemID = solarSys.solarSystemID
   1299             parentConstellation = self.map.GetParent(solarSystemID)
   1300             if not parentConstellation:
   1301                 continue
   1302             parentRegion = self.map.GetParent(parentConstellation)
   1303             name_with_path = ' / '.join([ self.map.GetItem(each).itemName for each in (solarSys.solarSystemID, parentConstellation, parentRegion) ])
   1304             autopilotNumJumps = pathfinder.GetAutopilotJumpCount(session.solarsystemid2, solarSystemID)
   1305             if IsUnreachableJumpCount(autopilotNumJumps):
   1306                 solarSystemText = GetByLabel('UI/InfoWindow/LocationNoRoute', locationName=name_with_path)
   1307             else:
   1308                 solarSystemText = GetByLabel('UI/InfoWindow/LocationAndRoute', locationName=name_with_path, numJump=autopilotNumJumps)
   1309             sortKey = (autopilotNumJumps, solarSystemText)
   1310             solarSystemText = self.GetColorCodedSecurityStringForSystem(solarSystemID, solarSystemText)
   1311             systemInfo = (solarSystemID, solarSystemText)
   1312             solarSystems.append((sortKey, systemInfo))
   1313             solarsystemItems = cfg.GetLocationsLocalBySystem(solarSystemID, False)
   1314             stationsInSystem = [ each for each in solarsystemItems if evetypes.GetGroupID(each.typeID) == const.groupStation ]
   1315             for eachStation in stationsInSystem:
   1316                 stationIDs.add(eachStation.itemID)
   1317 
   1318             stationIDsBySolarSystemID[solarSystemID] = stationsInSystem
   1319 
   1320         solarSystems = SortListOfTuples(solarSystems)
   1321         if len(stationIDs):
   1322             cfg.evelocations.Prime(stationIDs)
   1323             cfg.stations.Prime(stationIDs)
   1324         for eachSolarSystemID, solarSystemText in solarSystems:
   1325 
   1326             def GetSolarSystemMenu(solarSystemEntry):
   1327                 n = solarSystemEntry.sr.node
   1328                 return sm.GetService('menu').GetMenuFromItemIDTypeID(n.solarSystemID, const.typeSolarSystem)
   1329 
   1330             data = {'label': solarSystemText,
   1331              'solarSystemID': eachSolarSystemID,
   1332              'tabs': [30],
   1333              'OnGetMenu': lambda args: GetSolarSystemMenu(args),
   1334              'labelState': uiconst.UI_DISABLED}
   1335             entry = GetFromClass(SystemNameHeader, data)
   1336             wnd.data[TAB_STATIONS]['items'].append(entry)
   1337             stationsInSystem = stationIDsBySolarSystemID.get(eachSolarSystemID, [])
   1338             stationsInSystem = filter(lambda x: getattr(cfg.stations.GetIfExists(x.itemID), 'ownerID', None) == itemID, stationsInSystem)
   1339             stationEntryList = self.GetStationEntryList(stationsInSystem, 1)
   1340             wnd.data[TAB_STATIONS]['items'] += stationEntryList
   1341 
   1342         def ShowOnMap(*args):
   1343             OpenMap(hightlightedSolarSystems=solarSystemDict, starColorMode=(mapcommon.STARMODE_SETTLED_SYSTEMS_BY_CORP, itemID))
   1344 
   1345         wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Commands/ShowLocationOnMap'),
   1346           ShowOnMap,
   1347           (),
   1348           66)]
   1349         if not idCheckers.IsNPC(itemID) and not wnd.corp_info.deleted:
   1350             if sm.GetService('corp').GetActiveApplication(itemID) is not None:
   1351                 buttonLabel = GetByLabel('UI/Corporations/CorpApplications/ViewApplication')
   1352             else:
   1353                 buttonLabel = GetByLabel('UI/Corporations/CorporationWindow/Alliances/Rankings/ApplyToJoin')
   1354             wnd.data[DATA_BUTTONS] += [(buttonLabel, sm.GetService('corp').ApplyForMembership, (itemID,))]
   1355 
   1356         def SortStuff(a, b):
   1357             for i in range(3):
   1358                 x, y = a[i], b[i]
   1359                 if x < y:
   1360                     return -1
   1361                 if x > y:
   1362                     return 1
   1363 
   1364             return 0
   1365 
   1366         if corpmktinfo is not None:
   1367             sellStuff = []
   1368             buyStuff = []
   1369             for each in corpmktinfo:
   1370                 if evetypes.Exists(each.typeID):
   1371                     typeName = evetypes.GetName(each.typeID)
   1372                     groupName = evetypes.GetGroupName(each.typeID)
   1373                     categoryName = evetypes.GetCategoryName(each.typeID)
   1374                     if each.sellPrice is not None:
   1375                         sellStuff.append((typeName,
   1376                          groupName,
   1377                          categoryName,
   1378                          each.typeID,
   1379                          each.sellPrice,
   1380                          each.sellQuantity,
   1381                          each.sellDate,
   1382                          each.sellStationID))
   1383                     if each.buyPrice is not None:
   1384                         buyStuff.append((typeName,
   1385                          groupName,
   1386                          categoryName,
   1387                          each.typeID,
   1388                          each.buyPrice,
   1389                          each.buyQuantity,
   1390                          each.buyDate,
   1391                          each.buyStationID))
   1392 
   1393             sellStuff.sort(SortStuff)
   1394             buyStuff.sort(SortStuff)
   1395             for stuff, label in ((sellStuff, GetByLabel('UI/InfoWindow/Supply')), (buyStuff, GetByLabel('UI/InfoWindow/Demand'))):
   1396                 if stuff:
   1397                     wnd.data[TAB_MARKETACTIVITY]['items'].append(GetFromClass(Header, {'label': label}))
   1398                     for each in stuff:
   1399                         typeName, groupName, categoryName, typeID, price, quantity, lastActivity, station = each
   1400                         if lastActivity:
   1401                             txt = GetByLabel('UI/InfoWindow/CategoryGroupTypeForPrice', categoryName=categoryName, groupName=groupName, typeName=typeName, price=price)
   1402                         else:
   1403                             txt = GetByLabel('UI/InfoWindow/CategoryGroupTypeForPriceAndLastTransaction', categoryName=categoryName, groupName=groupName, typeName=typeName, price=price, date=FmtDate(lastActivity, 'ls'), amount=quantity, location=station)
   1404                         wnd.data[TAB_MARKETACTIVITY]['items'].append(GetFromClass(Text, {'line': 1,
   1405                          'typeID': typeID,
   1406                          'text': txt}))
   1407 
   1408         if idCheckers.IsNPC(itemID):
   1409             wnd.dynamicTabs.append(TAB_AGENTS)
   1410         wnd.dynamicTabs.append(TAB_STANDINGS)
   1411 
   1412     def UpdateDataAlliance(self, wnd):
   1413         if not idCheckers.IsNPC(wnd.item_id):
   1414             self.UpdateContactButtons(wnd, wnd.item_id)
   1415             wnd.dynamicTabs.append(TAB_WARHISTORY)
   1416         rec = wnd.allianceinfo
   1417         executor = cfg.eveowners.Get(rec.executorCorpID)
   1418         data = {'line': 1,
   1419          'label': GetByLabel('UI/Corporations/CorporationWindow/Alliances/Home/Executor'),
   1420          'text': executor.ownerName,
   1421          'typeID': const.typeCorporation,
   1422          'itemID': rec.executorCorpID}
   1423         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1424         data = {'line': 1,
   1425          'label': GetByLabel('UI/Corporations/CorporationWindow/Alliances/Home/ShortName'),
   1426          'text': rec.shortName}
   1427         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1428         data = {'line': 1,
   1429          'label': GetByLabel('UI/InfoWindow/CreatedByCorp'),
   1430          'text': cfg.eveowners.Get(rec.creatorCorpID).ownerName,
   1431          'typeID': const.typeCorporation,
   1432          'itemID': rec.creatorCorpID}
   1433         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1434         data = {'line': 1,
   1435          'label': GetByLabel('UI/Corporations/CorporationWindow/Alliances/Home/CreatedBy'),
   1436          'text': cfg.eveowners.Get(rec.creatorCharID).ownerName,
   1437          'typeID': const.typeCharacter,
   1438          'itemID': rec.creatorCharID}
   1439         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1440         data = {'line': 1,
   1441          'label': GetByLabel('UI/InfoWindow/StartDate'),
   1442          'text': FmtDate(rec.startDate, 'ls'),
   1443          'typeID': None,
   1444          'itemID': None}
   1445         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1446         primeTimeInfo = KeyVal(currentPrimeHour=rec.currentPrimeHour, newPrimeHour=rec.newPrimeHour, newPrimeHourValidAfter=rec.newPrimeHourValidAfter)
   1447         params = {'line': 1,
   1448          'label': GetByLabel('UI/Sovereignty/DefaultVulnerabilityTime'),
   1449          'text': '',
   1450          'primeTimeInfo': primeTimeInfo}
   1451         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(PrimeTimeHourEntryHorizontal, params))
   1452         allowWar = getattr(rec, 'allowWar', None)
   1453         label = GetByLabel('UI/WarPermit/WarPermitStatus')
   1454         text = GetByLabel(GetLabelPathForAllowWar(allowWar))
   1455         moreInfoHint = GetByLabel('UI/WarPermit/WarPermitExplanation')
   1456         data = {'line': 1,
   1457          'label': label,
   1458          'text': text,
   1459          'moreInfoHint': moreInfoHint}
   1460         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesMoreInfo, data))
   1461         if rec.currentCapital:
   1462             allianceCapital = cfg.evelocations.Get(rec.currentCapital, None)
   1463             if allianceCapital:
   1464                 capitalLink = GetShowInfoLink(const.typeSolarSystem, allianceCapital.name, rec.currentCapital)
   1465                 data = {'line': 1,
   1466                  'label': GetByLabel('UI/Sovereignty/CurrentCapital'),
   1467                  'text': capitalLink}
   1468                 wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1469         if rec.url:
   1470             linkTag = '<url=%s>' % rec.url
   1471             url = GetByLabel('UI/Corporations/CorpUIHome/URLPlaceholder', linkTag=linkTag, url=rec.url)
   1472             data = {'line': 1,
   1473              'label': GetByLabel('UI/Common/URL'),
   1474              'text': url}
   1475             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1476         wnd.dynamicTabs.append(TAB_MEMBERS)
   1477         wnd.dynamicTabs.append(TAB_STANDINGS)
   1478 
   1479     def UpdateDataStargate(self, wnd, itemID):
   1480         bp = sm.GetService('michelle').GetBallpark()
   1481         if bp is not None:
   1482             slimItem = bp.GetInvItem(itemID)
   1483             if slimItem is not None:
   1484                 locs = []
   1485                 for each in slimItem.jumps:
   1486                     if each.locationID not in locs:
   1487                         locs.append(each.locationID)
   1488                     if each.toCelestialID not in locs:
   1489                         locs.append(each.toCelestialID)
   1490 
   1491                 if len(locs):
   1492                     cfg.evelocations.Prime(locs)
   1493                 for each in slimItem.jumps:
   1494                     destLabel = GetByLabel('UI/InfoWindow/DestinationInSolarsystem', destination=each.toCelestialID, solarsystem=each.locationID)
   1495                     wnd.data[TAB_JUMPS]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   1496                      'label': GetByLabel('UI/Common/Jump'),
   1497                      'text': destLabel,
   1498                      'typeID': const.groupSolarSystem,
   1499                      'itemID': each.locationID}))
   1500 
   1501                 wnd.dynamicTabs.append(TAB_GATE_ICONS)
   1502 
   1503     def GetCelestialStatisticsForCelestial(self, celestialID, celestialGroupID):
   1504         statistics = OrderedDict()
   1505         celestial = cfg.mapSolarSystemContentCache.celestials[celestialID]
   1506         if not hasattr(celestial, 'statistics'):
   1507             return statistics
   1508         celestialStatistics = celestial.statistics
   1509         attributeNames = CELESTIAL_STATISTICS_ATTRIBUTES_BY_GROUPID[celestialGroupID]
   1510         attributeNames.sort()
   1511         for attributeName in attributeNames:
   1512             statistics[attributeName] = getattr(celestialStatistics, attributeName)
   1513 
   1514         return statistics
   1515 
   1516     def GetCelestialStatisticsForSun(self, sun):
   1517         statistics = OrderedDict()
   1518         if not hasattr(sun, 'statistics'):
   1519             return statistics
   1520         sunStatistics = sun.statistics
   1521         attributeNames = SUN_STATISTICS_ATTRIBUTES
   1522         sovereigntyResourceSvc = sm.GetService('sovereigntyResourceSvc')
   1523         starPowerMax = None
   1524         starPower = sovereigntyResourceSvc.planetProductionStaticData.get_power_production_for_star(sun.id)
   1525         if starPower:
   1526             starPowerMax = max(starPower, 0)
   1527         for attributeName in attributeNames:
   1528             if attributeName == 'power':
   1529                 if starPowerMax is not None:
   1530                     statistics[attributeName] = starPowerMax
   1531             else:
   1532                 statistics[attributeName] = getattr(sunStatistics, attributeName)
   1533 
   1534         return statistics
   1535 
   1536     def GetSovStatisticsForPlanet(self, planetID):
   1537         sovereigntyResourceSvc = sm.GetService('sovereigntyResourceSvc')
   1538         try:
   1539             reagentTypeID, reagentAmountsInfo, power, workforce = sovereigntyResourceSvc.GetPlanetResourceInfoParallel(planetID)
   1540         except DataUnavailableError:
   1541             return {}
   1542 
   1543         ret = {}
   1544         if reagentTypeID:
   1545             ret['reagentType'] = reagentTypeID
   1546         if reagentAmountsInfo and reagentAmountsInfo[0]:
   1547             amount, periodInSec = reagentAmountsInfo
   1548             amountPerMinute = round(float(amount) / (float(periodInSec) / 60), 1)
   1549             ret['reagentAmountPerMinute'] = amountPerMinute
   1550         if power:
   1551             ret['power'] = power
   1552         if workforce:
   1553             ret['workforce'] = workforce
   1554         return ret
   1555 
   1556     def UpdateDataCelestial(self, wnd, typeID, itemID, parentID):
   1557         if not itemID:
   1558             self.LogWarn('Failed to update info data for celestial item: itemID is %s' % itemID)
   1559             return
   1560         _, regionID, constellationID, solarsystemID, _itemID = self.map.GetParentLocationID(itemID)
   1561         if idCheckers.IsCelestial(itemID):
   1562             if wnd.groupID == const.groupSun:
   1563                 statistics = self.GetCelestialStatisticsForSun(cfg.mapSolarSystemContentCache[solarsystemID].star)
   1564             else:
   1565                 statistics = self.GetCelestialStatisticsForCelestial(itemID, wnd.groupID)
   1566                 if wnd.groupID == const.groupPlanet:
   1567                     sovStats = self.GetSovStatisticsForPlanet(itemID)
   1568                     statistics.update(sovStats)
   1569             for attributeName, attributeValue in statistics.iteritems():
   1570                 label, value, tID = FmtPlanetAttributeKeyVal(attributeName, attributeValue)
   1571                 data = {'line': 1,
   1572                  'label': label,
   1573                  'text': value}
   1574                 if tID:
   1575                     data['typeID'] = tID
   1576                 wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data=data))
   1577 
   1578         if solarsystemID is not None:
   1579             itemID = self.GetOrbitalBodies(wnd, itemID, solarsystemID, typeID)
   1580             if typeID == const.typeSolarSystem:
   1581                 self.GetStationTab(wnd, itemID)
   1582                 if sm.GetService('sov').IsSystemConquarable(solarsystemID):
   1583                     wnd.dynamicTabs.append(TAB_SOV)
   1584                 if sm.GetService('fwWarzoneSvc').IsWarzoneSolarSystem(solarsystemID):
   1585                     wnd.dynamicTabs.append(TAB_FW)
   1586                 if is_directional_scanner_suppressed(itemID):
   1587                     entry = GetFromClass(Generic, {'line': 1,
   1588                      'label': GetByLabel('UI/InfoWindow/DscanDisabled')})
   1589                     wnd.data[TAB_ATTIBUTES]['items'].append(entry)
   1590         typeGroupID = evetypes.GetGroupID(typeID)
   1591         neighborGrouping = {const.groupConstellation: GetByLabel('UI/InfoWindow/AdjacentConstellations'),
   1592          const.groupRegion: GetByLabel('UI/InfoWindow/AdjacentRegions'),
   1593          const.groupSolarSystem: GetByLabel('UI/InfoWindow/AdjacentSolarSystem')}
   1594         childGrouping = {const.groupRegion: GetByLabel('UI/InfoWindow/RelatedConstellation'),
   1595          const.groupConstellation: GetByLabel('UI/InfoWindow/RelatedSolarSystem')}
   1596         if typeGroupID == const.groupConstellation:
   1597             children = self.map.GetLocationChildren(itemID)
   1598             childrenEntriesToSort = []
   1599             for childID in children:
   1600                 childItem = self.map.GetItem(childID)
   1601                 if childItem is not None:
   1602                     text = self.GetColorCodedSecurityStringForSystem(childItem.itemID, childItem.itemName)
   1603                     childTypeName = evetypes.GetName(childItem.typeID)
   1604                     genericDisplayLabel = '%s - %s' % (childTypeName, childItem.itemName)
   1605                     entry = GetFromClass(LabelLocationTextTop, {'line': 1,
   1606                      'label': childTypeName,
   1607                      'text': text,
   1608                      'typeID': childItem.typeID,
   1609                      'itemID': childItem.itemID,
   1610                      'tabs': [35],
   1611                      'tabMargin': -2,
   1612                      'genericDisplayLabel': genericDisplayLabel})
   1613                     childrenEntriesToSort.append((childItem.itemName, entry))
   1614 
   1615             if childrenEntriesToSort:
   1616                 childrenEntries = SortListOfTuples(childrenEntriesToSort)
   1617                 wnd.data[TAB_CHILDREN]['items'] += childrenEntries
   1618             wnd.data[TAB_CHILDREN]['name'] = childGrouping.get(const.groupConstellation, GetByLabel('UI/InfoWindow/UnknownTabName'))
   1619             sovSvc = sm.GetService('sov')
   1620             if any([ sovSvc.IsSystemConquarable(solarSystemID) for solarSystemID in children ]):
   1621                 wnd.dynamicTabs.append(TAB_SOV_CONSTELLATION)
   1622         elif typeGroupID == const.groupRegion:
   1623             children = self.map.GetLocationChildren(itemID)
   1624             childrenEntriesToSort = []
   1625             for childID in children:
   1626                 childItem = self.map.GetItem(childID)
   1627                 if childItem is not None:
   1628                     childTypeName = evetypes.GetName(childItem.typeID)
   1629                     genericDisplayLabel = '%s - %s' % (childTypeName, childItem.itemName)
   1630                     entry = GetFromClass(LabelLocationTextTop, {'line': 1,
   1631                      'label': childTypeName,
   1632                      'text': childItem.itemName,
   1633                      'typeID': childItem.typeID,
   1634                      'itemID': childItem.itemID,
   1635                      'genericDisplayLabel': genericDisplayLabel})
   1636                     childrenEntriesToSort.append((childItem.itemName, entry))
   1637 
   1638             if childrenEntriesToSort:
   1639                 childrenEntries = SortListOfTuples(childrenEntriesToSort)
   1640                 wnd.data[TAB_CHILDREN]['items'] += childrenEntries
   1641             wnd.data[TAB_CHILDREN]['name'] = childGrouping.get(const.groupRegion, GetByLabel('UI/InfoWindow/UnknownTabName'))
   1642         if typeGroupID in [const.groupConstellation, const.groupRegion, const.groupSolarSystem]:
   1643             neigbors = self.map.GetNeighbors(itemID)
   1644             childrenEntriesToSort = []
   1645             for childID in neigbors:
   1646                 childItem = self.map.GetItem(childID)
   1647                 if childItem is not None:
   1648                     if childItem.typeID == const.groupSolarSystem:
   1649                         text = self.GetColorCodedSecurityStringForSystem(childID, childItem.itemName)
   1650                     else:
   1651                         text = childItem.itemName
   1652                     childTypeName = evetypes.GetName(childItem.typeID)
   1653                     genericDisplayLabel = '%s - %s' % (childTypeName, childItem.itemName)
   1654                     entry = GetFromClass(LabelLocationTextTop, {'line': 1,
   1655                      'label': childTypeName,
   1656                      'text': text,
   1657                      'typeID': childItem.typeID,
   1658                      'itemID': childItem.itemID,
   1659                      'tabs': [35],
   1660                      'tabMargin': -2,
   1661                      'genericDisplayLabel': genericDisplayLabel})
   1662                     childrenEntriesToSort.append((childItem.itemName, entry))
   1663 
   1664             if childrenEntriesToSort:
   1665                 childrenEntries = SortListOfTuples(childrenEntriesToSort)
   1666                 wnd.data[TAB_NEIGHBORS]['items'] += childrenEntries
   1667             wnd.data[TAB_NEIGHBORS]['name'] = neighborGrouping.get(typeGroupID, GetByLabel('UI/InfoWindow/UnknownTabName'))
   1668         if evetypes.GetGroupID(typeID) in [const.groupConstellation, const.groupSolarSystem]:
   1669             shortestRoute = sm.GetService('starmap').ShortestGeneralPath(itemID)
   1670             shortestRoute = shortestRoute[1:]
   1671             wasRegion = None
   1672             wasConstellation = None
   1673             if len(shortestRoute) > 0:
   1674                 wnd.data[TAB_ROUTE]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/Market/MarketQuote/NumberOfJumps', num=len(shortestRoute))}))
   1675             for i in range(len(shortestRoute)):
   1676                 childID = shortestRoute[i]
   1677                 childItem = self.map.GetItem(childID)
   1678                 parentConstellation = self.map.GetParent(childID)
   1679                 parentRegion = self.map.GetParent(parentConstellation)
   1680                 nameWithPath = GetByLabel('UI/InfoWindow/SolarsystemLocation', region=parentRegion, constellation=parentConstellation, solarsystem=childID)
   1681                 nameWithPath = self.GetColorCodedSecurityStringForSystem(childID, nameWithPath)
   1682                 jumpDescription = GetByLabel('UI/InfoWindow/RegularJump', numJumps=i + 1)
   1683                 if i > 0:
   1684                     if wasRegion != parentRegion:
   1685                         jumpDescription = GetByLabel('UI/InfoWindow/RegionJump', numJumps=i + 1)
   1686                     elif wasConstellation != parentConstellation:
   1687                         jumpDescription = GetByLabel('UI/InfoWindow/ConstellationJump', numJumps=i + 1)
   1688                 wasRegion = parentRegion
   1689                 wasConstellation = parentConstellation
   1690                 if childItem is not None:
   1691                     genericDisplayLabel = cfg.evelocations.Get(childID).name
   1692                     wnd.data[TAB_ROUTE]['items'].append(GetFromClass(LabelLocationTextTop, {'line': 1,
   1693                      'label': jumpDescription,
   1694                      'text': nameWithPath,
   1695                      'typeID': childItem.typeID,
   1696                      'itemID': childItem.itemID,
   1697                      'tabs': [35],
   1698                      'tabMargin': -2,
   1699                      'genericDisplayLabel': genericDisplayLabel}))
   1700 
   1701         groupID = evetypes.GetGroupID(typeID)
   1702 
   1703         def ShowMap(idx, *args):
   1704             OpenMap(interestID=itemID)
   1705 
   1706         if groupID in [const.groupSolarSystem, const.groupConstellation, const.groupRegion]:
   1707             if groupID == const.groupSolarSystem:
   1708                 systemID = itemID
   1709                 constellationID = self.map.GetParent(itemID)
   1710                 regionID = self.map.GetParent(constellationID)
   1711             elif groupID == const.groupConstellation:
   1712                 constellationID = itemID
   1713                 regionID = self.map.GetParent(constellationID)
   1714             elif groupID == const.groupRegion:
   1715                 regionID = itemID
   1716             wnd.data[DATA_BUTTONS] = [(GetByLabel('UI/Inflight/BookmarkLocation'),
   1717               self.Bookmark,
   1718               (itemID, typeID, parentID),
   1719               81)]
   1720             if idCheckers.IsKnownSpaceSystem(itemID) or idCheckers.IsKnownSpaceConstellation(itemID) or idCheckers.IsKnownSpaceRegion(itemID):
   1721                 wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Commands/ShowLocationOnMap'),
   1722                   ShowMap,
   1723                   [const.groupSolarSystem, const.groupConstellation, const.groupRegion].index(groupID),
   1724                   81)]
   1725         itemTraderComponent = GetItemTraderComponent(typeID)
   1726         if itemTraderComponent:
   1727             recipes = {Recipe(recipeID) for recipeID in itemTraderComponent.recipes}
   1728             recipesByGroup = GetSortedRecipeGroupsAndData(recipes)
   1729             for groupName, recipeDataList in recipesByGroup:
   1730                 entry = GetFromClass(Generic, {'line': 1,
   1731                  'label': groupName})
   1732                 wnd.data[TAB_TRADES]['items'].append(entry)
   1733                 for recipeData in recipeDataList:
   1734                     entry = GetFromClass(RecipeEntry, recipeData)
   1735                     wnd.data[TAB_TRADES]['items'].append(entry)
   1736 
   1737     def GetOrbitalBodies(self, wnd, itemID, solarsystemID, typeID):
   1738         solarsystem = self.map.GetSolarsystemItems(solarsystemID, False)
   1739         sun = None
   1740         if evetypes.GetGroupID(typeID) == const.groupSolarSystem:
   1741             for each in solarsystem:
   1742                 if evetypes.GetGroupID(each.typeID) == const.groupSun:
   1743                     sun = each.itemID
   1744 
   1745             if sun:
   1746                 itemID = sun
   1747         if solarsystemID == itemID and sun:
   1748             rootID = [ each for each in solarsystem if evetypes.GetGroupID(each.typeID) == const.groupSun ][0].itemID
   1749         else:
   1750             rootID = itemID
   1751         groupSort = {const.groupStargate: -1,
   1752          const.groupAsteroidBelt: 1,
   1753          const.groupMoon: 2,
   1754          const.groupPlanet: 3}
   1755 
   1756         def DrawOrbitItems(rootID, indent):
   1757             tmp = [ each for each in solarsystem if each.orbitID == rootID and evetypes.GetCategoryID(each.typeID) != const.categoryStructure ]
   1758             tmp.sort(lambda a, b: cmp(*[ groupSort.get(evetypes.GetGroupID(each.typeID), 0) for each in (a, b) ]) or cmp(a.celestialIndex, b.celestialIndex) or cmp(a.orbitIndex, b.orbitIndex))
   1759             for each in tmp:
   1760                 name = cfg.evelocations.Get(each.itemID).name
   1761                 planet = False
   1762                 if idCheckers.IsStation(each.itemID):
   1763                     continue
   1764                 elif each.groupID == const.groupMoon:
   1765                     name = '<color=0xff888888>' + name + '</color>'
   1766                 elif each.groupID == const.groupAsteroidBelt:
   1767                     name = '<color=0xffdddddd>' + name + '</color>'
   1768                 elif each.groupID == const.groupPlanet:
   1769                     planet = True
   1770                 if planet:
   1771                     planetTypeName = evetypes.GetName(each.typeID)
   1772                     genericDisplayLabel = '%s - %s' % (planetTypeName, name)
   1773                     data = {'line': 1,
   1774                      'text': indent * '    ' + name + ' %s' % planetTypeName,
   1775                      'typeID': each.typeID,
   1776                      'itemID': each.itemID,
   1777                      'locationID': solarsystemID,
   1778                      'genericDisplayLabel': genericDisplayLabel,
   1779                      'isDragObject': True}
   1780                     entry = GetFromClass(LocationTextEntry, data)
   1781                     wnd.data[TAB_ORBITALBODIES]['items'].append(entry)
   1782                 else:
   1783                     data = {'line': 1,
   1784                      'text': indent * '    ' + name,
   1785                      'genericDisplayLabel': StripTags(name),
   1786                      'typeID': each.typeID,
   1787                      'itemID': each.itemID,
   1788                      'isDragObject': True}
   1789                     entry = GetFromClass(LocationTextEntry, data)
   1790                     wnd.data[TAB_ORBITALBODIES]['items'].append(entry)
   1791                 DrawOrbitItems(each.itemID, indent + 1)
   1792 
   1793         if sun:
   1794             DrawOrbitItems(rootID, 0)
   1795         if evetypes.GetGroupID(typeID) == const.groupSolarSystem:
   1796             structuresInSolarsystem = [ x for x in solarsystem if evetypes.GetCategoryID(x.typeID) == const.categoryStructure ]
   1797             structureEntryList = []
   1798             for eachStructure in structuresInSolarsystem:
   1799                 name = cfg.evelocations.Get(eachStructure.itemID).name
   1800                 data = {'line': 1,
   1801                  'text': name,
   1802                  'genericDisplayLabel': StripTags(name),
   1803                  'typeID': eachStructure.typeID,
   1804                  'itemID': eachStructure.itemID,
   1805                  'isDragObject': True}
   1806                 entry = GetFromClass(LocationTextEntry, data)
   1807                 structureEntryList.append((name.lower(), entry))
   1808 
   1809             sortedStructureEntryList = SortListOfTuples(structureEntryList)
   1810             wnd.data[TAB_STRUCTURES]['items'].extend(sortedStructureEntryList)
   1811         itemID = solarsystemID
   1812         return itemID
   1813 
   1814     def GetStationTab(self, wnd, solarsystemID):
   1815         solarsystem = self.map.GetSolarsystemItems(solarsystemID, False)
   1816         allStations = [ each for each in solarsystem if evetypes.GetGroupID(each.typeID) == const.groupStation ]
   1817         if not allStations:
   1818             return
   1819         stationEntryList = self.GetStationEntryList(allStations)
   1820         wnd.data[TAB_STATIONS]['items'] += stationEntryList
   1821 
   1822     def GetStationEntryList(self, stationList, sublevel = 0):
   1823         entryList = []
   1824         stationList.sort(lambda a, b: cmp(a.celestialIndex, b.celestialIndex) or cmp(a.orbitIndex, b.orbitIndex))
   1825         stationIDs = []
   1826         for each in stationList:
   1827             stationIDs.append(each.itemID)
   1828 
   1829         if len(stationIDs):
   1830             cfg.evelocations.Prime(stationIDs)
   1831         for each in stationList:
   1832             name = cfg.evelocations.Get(each.itemID).name
   1833             entry = GetFromClass(LocationGroup, {'GetSubContent': self.GetStationSubContent,
   1834              'label': name,
   1835              'MenuFunction': self.GetMenuLocationMenu,
   1836              'id': ('infownd_stations', each.itemID),
   1837              'groupItems': [],
   1838              'iconMargin': 18,
   1839              'allowCopy': 1,
   1840              'showicon': 'hide',
   1841              'showlen': 0,
   1842              'itemID': each.itemID,
   1843              'typeID': each.typeID,
   1844              'state': 'locked',
   1845              'sublevel': sublevel})
   1846             entryList.append(entry)
   1847 
   1848         return entryList
   1849 
   1850     def GetStationSubContent(self, nodedata, *args):
   1851         itemID = nodedata.itemID
   1852         stationInfo = self.map.GetStation(itemID)
   1853         serviceEntryList = self.GetServicesForStation(stationInfo, itemID, iconoffset=20)
   1854         return serviceEntryList
   1855 
   1856     def GetMenuLocationMenu(self, node):
   1857         stationInfo = sm.GetService('ui').GetStationStaticInfo(node.itemID)
   1858         return StartMenuService().CelestialMenu(node.itemID, typeID=stationInfo.stationTypeID, parentID=stationInfo.solarSystemID)
   1859 
   1860     def UpdateDataControlTower(self, wnd, typeID, itemID):
   1861         self.UpdateDataModule(wnd, typeID, itemID)
   1862         wnd.dynamicTabs.append(TAB_FUELREQ)
   1863 
   1864     def UpdateDataGasCloud(self, wnd, typeID, itemID):
   1865         self._update_data_harvestable(wnd, typeID, itemID)
   1866 
   1867     def UpdateDataAsteroid(self, wnd, typeID, itemID):
   1868         self._update_data_harvestable(wnd, typeID, itemID)
   1869         if evetypes.GetGroupID(typeID) == appConst.groupIce:
   1870             func = lambda *args: AgencyWndNew.OpenAndShowContentGroup(contentGroupID=contentGroupConst.contentGroupIceBelts)
   1871             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Agency/ContentGroups/ContentGroupIceBelts'), func)]
   1872         else:
   1873             func = lambda *args: AgencyWndNew.OpenAndShowContentGroup(contentGroupID=contentGroupConst.contentGroupAsteroidBelts)
   1874             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Common/AsteroidBelts'), func)]
   1875             if not classic_map_enabled_setting.is_enabled():
   1876                 func = lambda *args: MapViewPanel.show_ore_distribution_filter(typeID)
   1877                 wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Commands/ShowLocationOnMap'), func)]
   1878 
   1879     def _update_data_harvestable(self, wnd, typeID, itemID):
   1880         self._AddVolumeAttributeEntry(wnd, typeID)
   1881         try:
   1882             radiusHeader = GetByLabel('UI/Generic/FormatPlanetAttributes/attributeRadius')
   1883             radiusText = FormatValue(sm.GetService('michelle').GetBallpark().GetBall(itemID).radius, const.unitLength)
   1884             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1885              'label': radiusHeader,
   1886              'text': radiusText}))
   1887         except:
   1888             sys.exc_clear()
   1889 
   1890         if not HasMineableComponent(typeID):
   1891             slimItem = sm.GetService('michelle').GetItem(itemID)
   1892             if slimItem:
   1893                 wnd.data[TAB_ATTIBUTES]['items'].extend([GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/HarvestedOutput')}), GetFromClass(Item, {'line': 1,
   1894                   'label': evetypes.GetName(typeID),
   1895                   'typeID': typeID,
   1896                   'getIcon': 1})])
   1897 
   1898     def UpdateDataMaterial(self, wnd, typeID, itemID):
   1899         self._AddVolumeAttributeEntry(wnd, typeID)
   1900 
   1901     def ShowReprocessingRequirements(self, wnd, typeID, itemID):
   1902         if not is_reprocessable_type(typeID):
   1903             return
   1904         portionSize = int(evetypes.GetPortionSize(typeID))
   1905         if portionSize > 1:
   1906             data = {'line': 1,
   1907              'label': GetByLabel('UI/InfoWindow/UnitsToRefine'),
   1908              'text': localization.formatters.FormatNumeric(portionSize, useGrouping=True)}
   1909             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, data))
   1910         attributesScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, attrList=(const.attributeReprocessingSkillType,))
   1911         wnd.data[TAB_ATTIBUTES]['items'] += attributesScrollListForItem
   1912 
   1913     def UpdateDataFaction(self, wnd, typeID, itemID):
   1914         races = get_faction_races(itemID) or [const.raceCaldari,
   1915          const.raceMinmatar,
   1916          const.raceAmarr,
   1917          const.raceGallente]
   1918         stations = get_station_count(itemID)
   1919         systems = get_station_system_count(itemID)
   1920         memberRaceList = []
   1921         for raceID in races:
   1922             memberRaceList.append(get_race_name(raceID))
   1923 
   1924         if len(memberRaceList) > 0:
   1925             memberRaceText = localization.formatters.FormatGenericList(memberRaceList)
   1926             wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1927              'label': GetByLabel('UI/InfoWindow/MemberRaces'),
   1928              'text': memberRaceText}))
   1929         text = localization.formatters.FormatNumeric(systems, useGrouping=True)
   1930         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1931          'label': GetByLabel('UI/InfoWindow/SettledSystems'),
   1932          'text': text}))
   1933         text = localization.formatters.FormatNumeric(stations, useGrouping=True)
   1934         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   1935          'label': GetByLabel('UI/Common/Stations'),
   1936          'text': text}))
   1937         wnd.data[TAB_ATTIBUTES]['name'] = GetByLabel('UI/InfoWindow/TabNames/Statistics')
   1938 
   1939         def SortFunc(x, y):
   1940             xname = cfg.eveowners.Get(x).name
   1941             if xname.startswith('The '):
   1942                 xname = xname[4:]
   1943             yname = cfg.eveowners.Get(y).name
   1944             if yname.startswith('The '):
   1945                 yname = yname[4:]
   1946             if xname < yname:
   1947                 return -1
   1948             if xname > yname:
   1949                 return 1
   1950             return 0
   1951 
   1952         corpsOfFaction = get_corporation_ids_by_faction_id(itemID, default=[])
   1953         corpsOfFaction = copy.copy(corpsOfFaction)
   1954         corpsOfFaction.sort(SortFunc)
   1955         for corpID in corpsOfFaction:
   1956             corp = cfg.eveowners.Get(corpID)
   1957             entry = GetFromClass(User, {'info': corp,
   1958              'charID': corp.ownerID})
   1959             wnd.data[TAB_MEMBEROFCORPS]['items'].append(entry)
   1960 
   1961         newEntries = []
   1962         regions, constellations, solarsystems = sm.GetService('faction').GetFactionLocations(itemID)
   1963         if regions:
   1964             wnd.data[TAB_SYSTEMS]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/Common/Regions')}))
   1965         for regionID in regions:
   1966             nameWithPath = self.map.GetItem(regionID).itemName
   1967             entry = GetFromClass(LabelTextSides, {'line': 1,
   1968              'label': nameWithPath,
   1969              'text': '',
   1970              'typeID': const.typeRegion,
   1971              'itemID': regionID})
   1972             newEntries.append((nameWithPath, entry))
   1973 
   1974         newEntries = SortListOfTuples(newEntries)
   1975         wnd.data[TAB_SYSTEMS]['items'].extend(newEntries)
   1976         newEntries = []
   1977         if constellations:
   1978             wnd.data[TAB_SYSTEMS]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/Common/Constellations')}))
   1979         for constellationID in constellations:
   1980             regionID = self.map.GetParent(constellationID)
   1981             nameWithPath = GetByLabel('UI/InfoWindow/ConstellationLocation', region=regionID, constellation=constellationID)
   1982             sortValue = [ cfg.evelocations.Get(x).name for x in [regionID, constellationID] ]
   1983             entry = GetFromClass(LabelTextSides, {'line': 1,
   1984              'label': nameWithPath,
   1985              'text': '',
   1986              'typeID': const.typeConstellation,
   1987              'itemID': constellationID})
   1988             newEntries.append((sortValue, entry))
   1989 
   1990         newEntries = SortListOfTuples(newEntries)
   1991         wnd.data[TAB_SYSTEMS]['items'].extend(newEntries)
   1992         newEntries = []
   1993         if solarsystems:
   1994             wnd.data[TAB_SYSTEMS]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/Common/SolarSystems')}))
   1995         for solarsystemID in solarsystems:
   1996             constellationID = self.map.GetParent(solarsystemID)
   1997             regionID = self.map.GetParent(constellationID)
   1998             nameWithPath = GetByLabel('UI/InfoWindow/SolarsystemLocation', region=regionID, constellation=constellationID, solarsystem=solarsystemID)
   1999             sortValue = [ cfg.evelocations.Get(x).name for x in [regionID, constellationID, solarsystemID] ]
   2000             entry = GetFromClass(LabelTextSides, {'line': 1,
   2001              'label': nameWithPath,
   2002              'text': '',
   2003              'typeID': const.typeSolarSystem,
   2004              'itemID': solarsystemID})
   2005             newEntries.append((sortValue, entry))
   2006 
   2007         newEntries = SortListOfTuples(newEntries)
   2008         wnd.data[TAB_SYSTEMS]['items'].extend(newEntries)
   2009         wnd.data[TAB_SYSTEMS]['name'] = GetByLabel('UI/InfoWindow/ControlledTerritory')
   2010         illegalities = get_contraband_types_in_faction(itemID)
   2011         illegalitiesItems = illegalities.items()
   2012         illegalitiesItems.sort(key=lambda x: evetypes.GetName(x[0]))
   2013         for tmpTypeID, illegality in illegalitiesItems:
   2014             txtList = self.__GetIllegalityStringList(illegality)
   2015             wnd.data[TAB_LEGALITY]['items'].append(GetFromClass(Item, {'line': 1,
   2016              'label': evetypes.GetName(tmpTypeID),
   2017              'typeID': tmpTypeID,
   2018              'getIcon': True}))
   2019             for eachTxt in txtList:
   2020                 wnd.data[TAB_LEGALITY]['items'].append(GetFromClass(Generic, {'line': 1,
   2021                  'label': eachTxt,
   2022                  'sublevel': 2}))
   2023 
   2024         if illegalities:
   2025             wnd.data[TAB_LEGALITY]['items'].insert(0, GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/IllegalTypes')}))
   2026         wnd.dynamicTabs.append(TAB_STANDINGS)
   2027 
   2028     def UpdateDataAgent(self, wnd, typeID, itemID):
   2029         agentID = itemID or sm.GetService('godma').GetType(typeID).agentID
   2030         try:
   2031             details = sm.GetService('agents').GetAgentMoniker(agentID).GetInfoServiceDetails()
   2032             if details is not None:
   2033                 agentInfo = sm.GetService('agents').GetAgentByID(agentID)
   2034                 if agentInfo:
   2035                     typeDict = {const.agentTypeGenericStorylineMissionAgent: GetByLabel('UI/InfoWindow/AgentTypeStorylineImportant'),
   2036                      const.agentTypeStorylineMissionAgent: GetByLabel('UI/InfoWindow/AgentTypeStorylineImportant'),
   2037                      const.agentTypeEventMissionAgent: GetByLabel('UI/InfoWindow/AgentTypeEvent'),
   2038                      const.agentTypeCareerAgent: GetByLabel('UI/InfoWindow/AgentTypeCareer')}
   2039                     t = typeDict.get(agentInfo.agentTypeID, None)
   2040                     if t:
   2041                         wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2042                          'label': GetByLabel('UI/InfoWindow/AgentType'),
   2043                          'text': t}))
   2044                 if agentInfo and agentInfo.agentTypeID not in (const.agentTypeGenericStorylineMissionAgent, const.agentTypeStorylineMissionAgent):
   2045                     wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2046                      'label': GetByLabel('UI/InfoWindow/AgentDivision'),
   2047                      'text': get_division_name(agentInfo.divisionID).replace('&', '&amp;')}))
   2048                 if details.stationID:
   2049                     stationinfo = sm.GetService('ui').GetStationStaticInfo(details.stationID)
   2050                     wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2051                      'label': GetByLabel('UI/InfoWindow/AgentLocation'),
   2052                      'text': cfg.evelocations.Get(details.stationID).name,
   2053                      'typeID': stationinfo.stationTypeID,
   2054                      'itemID': details.stationID}))
   2055                 else:
   2056                     agentSolarSystemID = sm.GetService('agents').GetSolarSystemOfAgent(agentID)
   2057                     if agentSolarSystemID is not None:
   2058                         wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2059                          'label': GetByLabel('UI/InfoWindow/AgentLocation'),
   2060                          'text': cfg.evelocations.Get(agentSolarSystemID).name,
   2061                          'typeID': const.typeSolarSystem,
   2062                          'itemID': agentSolarSystemID}))
   2063                 if agentInfo and agentInfo.agentTypeID not in (const.agentTypeGenericStorylineMissionAgent, const.agentTypeStorylineMissionAgent):
   2064                     level = localization.formatters.FormatNumeric(details.level, decimalPlaces=0)
   2065                     wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2066                      'label': GetByLabel('UI/InfoWindow/AgentLevel'),
   2067                      'text': level}))
   2068                 for data in details.services:
   2069                     serviceInfo = sm.GetService('agents').ProcessAgentInfoKeyVal(data)
   2070                     for entry in serviceInfo:
   2071                         wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(Header, {'label': entry[0]}))
   2072                         for entryDetails in entry[1]:
   2073                             wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2074                              'label': entryDetails[0],
   2075                              'text': entryDetails[1]}))
   2076 
   2077                 if details.incompatible:
   2078                     if type(details.incompatible) is tuple:
   2079                         incText = GetByLabel(details.incompatible[0], **details.incompatible[1])
   2080                     elif details.incompatible == 'Not really an agent':
   2081                         incText = None
   2082                     else:
   2083                         incText = details.incompatible
   2084                     if incText:
   2085                         wnd.data[TAB_AGENTINFO]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2086                          'label': GetByLabel('UI/InfoWindow/AgentCompatibility'),
   2087                          'text': incText}))
   2088             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Chat/StartConversationAgent'),
   2089               sm.StartService('agents').OpenDialogueWindow,
   2090               (itemID,),
   2091               66)]
   2092         except (UserError, RuntimeError):
   2093             pass
   2094 
   2095     def UpdateDataOrbital(self, wnd, itemID):
   2096         self.UpdateDataModule(wnd, wnd.type_id, itemID)
   2097         uthread.new(self.FetchDynamicOrbitalAttributes, wnd, wnd.data[TAB_ATTIBUTES], itemID)
   2098 
   2099     def FetchDynamicOrbitalAttributes(self, wnd, data, itemID):
   2100         ballpark = sm.GetService('michelle').GetBallpark()
   2101         if not ballpark:
   2102             return
   2103         if ballpark.GetBall(itemID) is not None:
   2104             taxRate = eveMoniker.GetPlanetOrbitalRegistry(session.solarsystemid).GetTaxRate(itemID)
   2105             if taxRate is not None:
   2106                 text = GetByLabel('UI/Common/Percentage', percentage=taxRate * 100)
   2107             else:
   2108                 text = GetByLabel('UI/PI/Common/CustomsOfficeAccessDenied')
   2109             data['items'].append(GetFromClass(LabelTextSides, {'line': 1,
   2110              'label': GetByLabel('UI/PI/Common/CustomsOfficeTaxRateLabel'),
   2111              'text': text,
   2112              'icon': 'ui_77_32_46'}))
   2113             wnd.maintabs.ReloadVisible()
   2114         else:
   2115             log.LogInfo('Unable to fetch tax rate for customs office in a different system')
   2116 
   2117     def UpdateDataIllegal(self, wnd, typeID):
   2118         illegalities = inventorycommon.typeHelpers.GetIllegality(typeID)
   2119         if illegalities:
   2120             wnd.data[TAB_LEGALITY]['items'].append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/LegalImplications')}))
   2121         illegalitiesItems = illegalities.items()
   2122         illegalitiesItems.sort(key=lambda x: cfg.eveowners.Get(x[0]).name)
   2123         for tmpFactionID, illegality in illegalities.iteritems():
   2124             txtList = self.__GetIllegalityStringList(illegality)
   2125             wnd.data[TAB_LEGALITY]['items'].append(GetFromClass(User, {'line': 1,
   2126              'charID': tmpFactionID,
   2127              'typeID': const.typeFaction}))
   2128             for eachTxt in txtList:
   2129                 wnd.data[TAB_LEGALITY]['items'].append(GetFromClass(Generic, {'line': 1,
   2130                  'label': eachTxt,
   2131                  'sublevel': 2}))
   2132 
   2133     def UpdateDataGenericItem(self, wnd, typeID, itemID):
   2134         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=self.GetSkillAttrs())
   2135         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   2136         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
   2137 
   2138     def UpdateDataSecurityTag(self, wnd, typeID, itemID):
   2139         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID)
   2140         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   2141         ShowSecurityOfficeMap = lambda : OpenMap(starColorMode=mapcommon.STARMODE_SERVICE_SecurityOffice)
   2142         wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Commands/ShowSecurityOffices'),
   2143           ShowSecurityOfficeMap,
   2144           (),
   2145           66)]
   2146 
   2147     def UpdateDataSkill(self, wnd, typeID, itemID):
   2148         self.UpdateDataGenericItem(wnd, typeID, itemID)
   2149         if len(get_types_with_skill_type(typeID)) > 0:
   2150             wnd.dynamicTabs.append(TAB_REQUIREDFOR)
   2151 
   2152     def UpdateDataStation(self, wnd, typeID, itemID):
   2153         stationInfo = self.map.GetStation(itemID)
   2154         if stationInfo:
   2155             serviceEntryList = self.GetServicesForStation(stationInfo, itemID)
   2156             wnd.data[TAB_SERVICES]['items'] += serviceEntryList
   2157             stationLocationInfo = [stationInfo.regionID, stationInfo.constellationID, stationInfo.solarSystemID]
   2158         elif itemID in cfg.oldStations:
   2159             solarSystemID = cfg.oldStations.Get(itemID).solarSystemID
   2160             solarSystemInfo = cfg.mapSystemCache.Get(solarSystemID)
   2161             stationLocationInfo = [solarSystemID, solarSystemInfo.constellationID, solarSystemInfo.regionID]
   2162         else:
   2163             return
   2164         for locID in stationLocationInfo:
   2165             mapItem = self.map.GetItem(locID)
   2166             if mapItem is not None:
   2167                 if mapItem.typeID == const.typeSolarSystem:
   2168                     text = self.GetColorCodedSecurityStringForSystem(mapItem.itemID, mapItem.itemName)
   2169                     text = text.replace('<t>', ' ')
   2170                 else:
   2171                     text = mapItem.itemName
   2172                 wnd.data[TAB_LOCATION]['items'].append(GetFromClass(LabelTextTop, {'line': 1,
   2173                  'label': evetypes.GetName(mapItem.typeID),
   2174                  'text': text,
   2175                  'typeID': mapItem.typeID,
   2176                  'itemID': mapItem.itemID}))
   2177 
   2178         stationOwnerID = None
   2179         if session.solarsystemid is not None:
   2180             ballpark = sm.GetService('michelle').GetBallpark()
   2181             if ballpark:
   2182                 slimitem = ballpark.GetInvItem(itemID)
   2183                 if slimitem is not None:
   2184                     stationOwnerID = slimitem.ownerID
   2185         if stationOwnerID is None and stationInfo and stationInfo.ownerID:
   2186             stationOwnerID = stationInfo.ownerID
   2187         if stationOwnerID is not None:
   2188             wnd.CreateCorpLogo(stationOwnerID, parent=wnd.subinfolinkcontainer)
   2189             wnd.subinfolinkcontainer.height = 64
   2190         wnd.data[DATA_BUTTONS] = [(GetByLabel('UI/Inflight/SetDestination'),
   2191           self.SetDestination,
   2192           (itemID,),
   2193           81)]
   2194 
   2195     def IsServiceAvailable(self, serviceID, stationInfo):
   2196         stationOperationID = stationInfo.operationID
   2197         serviceAlwaysPresent = serviceID == stationServiceConst.serviceIDAlwaysPresent
   2198         if serviceAlwaysPresent or service_in_station_operation(stationOperationID, serviceID):
   2199             return True
   2200         repairServiceID = const.stationServiceRepairFacilities
   2201         solarSystemID = session.solarsystemid2
   2202         return serviceID == repairServiceID and IsStationServiceAvailable(solarSystemID, stationInfo, serviceID)
   2203 
   2204     def GetServicesForStation(self, stationInfo, itemID, iconoffset = 4):
   2205         serviceEntryList = []
   2206         sortServices = []
   2207         for info in stationServiceConst.serviceData:
   2208             if info.serviceID == structures.SERVICE_FACTION_WARFARE:
   2209                 factionID = get_corporation_faction_id(stationInfo.ownerID)
   2210                 if not factionID or factionID not in const.factionsEmpires:
   2211                     continue
   2212             elif info.serviceID == structures.SERVICE_SECURITY_OFFICE:
   2213                 if not sm.GetService('securityOfficeSvc').CanAccessServiceInStation(itemID):
   2214                     continue
   2215             for stationServiceID in info.stationServiceIDs:
   2216                 if self.IsServiceAvailable(stationServiceID, stationInfo):
   2217                     if hasattr(info, 'iconID'):
   2218                         icon = info.iconID
   2219                     else:
   2220                         icon = info.texturePath
   2221                     sortServices.append((info.label, (info.label, icon, get_station_standings_restriction_info_many(info.stationServiceIDs, itemID))))
   2222                     break
   2223 
   2224         if sortServices:
   2225             sortServices = SortListOfTuples(sortServices)
   2226             for displayName, iconpath, standingsRestriction in sortServices:
   2227                 serviceEntryList.append(GetFromClass(StationServiceEntry, {'line': 1,
   2228                  'label': displayName,
   2229                  'selectable': 0,
   2230                  'iconoffset': iconoffset,
   2231                  'icon': iconpath,
   2232                  'standingsRestriction': standingsRestriction}))
   2233 
   2234         return serviceEntryList
   2235 
   2236     def UpdateDataRank(self, content):
   2237         characterRanks = sm.StartService('facwar').GetCharacterRankOverview(session.charid)
   2238         characterRanks = [ each for each in characterRanks if each.factionID == content.abstract_info.warFactionID ]
   2239         for x in range(9, -1, -1):
   2240             hilite = False
   2241             if characterRanks:
   2242                 if characterRanks[0].currentRank == x:
   2243                     hilite = True
   2244             rank = utillib.KeyVal(currentRank=x, factionID=content.abstract_info.warFactionID)
   2245             content.data[TAB_HIERARCHY]['items'].append(self.GetRankEntry(rank, hilite=hilite))
   2246 
   2247     def UpdateDataCertificate(self, content):
   2248         content.dynamicTabs.append(TAB_CERTSKILLS)
   2249         recommendedForScrollList = self.GetRecommendedFor(content.abstract_info.certificateID)
   2250         content.data[TAB_CERTRECOMMENDEDFOR]['items'] += recommendedForScrollList
   2251 
   2252     def UpdateDataPlanetPin(self, wnd, typeID, itemID):
   2253         banAttrs = self.GetSkillAttrs()
   2254         if evetypes.GetGroupID(typeID) == const.groupExtractorPins:
   2255             banAttrs.extend([const.attributePinCycleTime, const.attributePinExtractionQuantity])
   2256         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID, banAttrs=banAttrs)
   2257         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   2258         wnd.dynamicTabs.append(TAB_REQUIREMENTS)
   2259         if evetypes.GetGroupID(typeID) == const.groupProcessPins:
   2260             wnd.dynamicTabs.append(TAB_SCHEMATICS)
   2261 
   2262     def UpdateDataPlanet(self, wnd, typeID, itemID, parentID):
   2263         if sm.GetService('machoNet').GetGlobalConfig().get('enableDustLink'):
   2264             if session.solarsystemid is not None:
   2265                 slimitem = sm.GetService('michelle').GetBallpark().GetInvItem(itemID)
   2266                 if slimitem is not None and slimitem.corpID is not None:
   2267                     wnd.dynamicTabs.append(TAB_PLANETCONTROL)
   2268         wnd.dynamicTabs.append(TAB_PLANETARYPRODUCTIONPLANET)
   2269         if itemID:
   2270             wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/PI/Common/ViewInPlanetMode'), sm.GetService('menu').ViewPlanetaryProduction, (itemID,))]
   2271         self.UpdateDataCelestial(wnd, typeID, itemID, parentID)
   2272 
   2273     def UpdateDataDogma(self, wnd, typeID):
   2274         container = wnd.data[TAB_DOGMA]['items']
   2275         container.append(GetFromClass(Header, {'label': 'Type Attributes'}))
   2276         typeattribs = dogma_data.get_type_attributes(typeID)
   2277         tattribs = []
   2278         for ta in typeattribs:
   2279             v = ta.value
   2280             a = dogma_data.get_attribute(ta.attributeID)
   2281             if v is None:
   2282                 v = a.defaultValue
   2283             tattribs.append([a.attributeID,
   2284              a.name,
   2285              v,
   2286              a.dataType,
   2287              a.description])
   2288 
   2289         tattribs.sort(lambda x, y: cmp(x[1], y[1]))
   2290         for ta in tattribs:
   2291             attributeName = ta[1]
   2292             v = ta[2]
   2293             dataType = ta[3]
   2294             description = ta[4]
   2295             if dataType == dogma_const.attributeDataTypeTypeHex:
   2296                 v = hex(int(v))
   2297             entry = GetFromClass(LabelTextTop, {'line': 1,
   2298              'label': attributeName,
   2299              'text': '%s<br>%s' % (v, description)})
   2300             container.append(entry)
   2301 
   2302         container.append(GetFromClass(Header, {'label': 'Effects'}))
   2303         teffects = []
   2304         for te in dogma_data.get_type_effects(typeID):
   2305             e = dogma_data.get_effect(te.effectID)
   2306             teffects.append([e, e.effectName])
   2307 
   2308         teffects.sort(lambda x, y: cmp(x[1], y[1]))
   2309         for e, effectName in teffects:
   2310             entry = GetFromClass(Subheader, {'label': effectName})
   2311             container.append(entry)
   2312             header = sorted([ k for k in dir(e) if '__' not in k ])
   2313             for columnName in header:
   2314                 entry = GetFromClass(LabelTextTop, {'line': 1,
   2315                  'label': columnName,
   2316                  'text': '%s' % getattr(e, columnName)})
   2317                 container.append(entry)
   2318 
   2319     def UpdateDataEntity(self, wnd):
   2320         with ExceptionEater():
   2321             damageEntryScrollList = self.GetEntityDamageScrollList(wnd.type_id)
   2322             wnd.data[TAB_ATTIBUTES]['items'] += damageEntryScrollList
   2323         attributeEntries, _ = self.GetItemAttributeScrolllistAndAttributesList(None, wnd.type_id, uiAttributeGroups.npc_attribute_group_ids)
   2324         wnd.data[TAB_ATTIBUTES]['items'] += attributeEntries
   2325 
   2326     def UpdateDataMutator(self, wnd, typeID):
   2327         attributes = wnd.data[TAB_ATTIBUTES]['items']
   2328         attributes.extend(self.GetAttributeScrollListForType(typeID=typeID))
   2329         mutator = dynamicitemattributes.GetMutator(typeID)
   2330         mutations = []
   2331         for attributeID, attribute in mutator.attributeIDs.iteritems():
   2332             mutations.append(GetFromClass(LabelTextSidesAttributes, {'attributeID': attributeID,
   2333              'line': 1,
   2334              'label': dogma_data.get_attribute_display_name(attributeID),
   2335              'text': FormatAttributeBonusRange(attributeID, attribute.min, attribute.max),
   2336              'iconID': dogma_data.get_attribute_icon_id(attributeID)}))
   2337 
   2338         if mutations:
   2339             attributes.append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/Mutations')}))
   2340             attributes.extend(sorted(mutations, key=lambda e: e.label))
   2341         wnd.dynamicTabs.append(TAB_MUTATOR_USED_WITH)
   2342 
   2343     def UpdateExpertSystem(self, wnd, typeID):
   2344         wnd.dynamicTabs.append(TAB_EXPERT_SYSTEM_SKILLS)
   2345         wnd.dynamicTabs.append(TAB_EXPERT_SYSTEM_SHIPS)
   2346         if expertSystems.is_expert_systems_enabled():
   2347             browseInStoreLabel = GetByLabel('UI/InfoWindow/ViewExpertSystemInStore')
   2348             wnd.data[DATA_BUTTONS] = [(browseInStoreLabel,
   2349               self.ViewExpertSystemInStore,
   2350               typeID,
   2351               81)]
   2352 
   2353     def UpdateMarketButtons(self, content):
   2354         typeID = content.type_id
   2355         if not typeID:
   2356             return
   2357         if can_view_market_details(typeID):
   2358             showMarketDetailsLabel = GetByLabel('UI/Inventory/ItemActions/ViewTypesMarketDetails')
   2359             content.data[DATA_BUTTONS] += [(showMarketDetailsLabel,
   2360               self.ShowMarketDetails,
   2361               typeID,
   2362               81)]
   2363         elif is_contractable(typeID) and evetypes.IsPublished(typeID):
   2364             findInContractsLabel = GetByLabel('UI/Inventory/ItemActions/FindInContracts')
   2365             content.data[DATA_BUTTONS] += [(findInContractsLabel,
   2366               self.FindInContracts,
   2367               typeID,
   2368               81)]
   2369         if industryCommon.IsBlueprintCategory(evetypes.GetCategoryID(content.type_id)):
   2370             from eve.client.script.ui.shared.industry.industryWnd import Industry
   2371             itemID = content.item_id
   2372             bpData = content.GetBlueprintData()
   2373             viewInIndustryLabel = GetByLabel('UI/Industry/ViewInIndustry')
   2374             content.data[DATA_BUTTONS] += [(viewInIndustryLabel,
   2375               Industry.OpenOrShowBlueprint,
   2376               (itemID, typeID, bpData),
   2377               81)]
   2378 
   2379     def UpdateWindowData(self, content, typeID, itemID, parentID = None):
   2380         evetypes.RaiseIFNotExists(typeID)
   2381         self.UpdateMarketButtons(content)
   2382         if content.IsType(TYPE_CHARACTER):
   2383             self.UpdateDataCharacter(content, typeID, itemID)
   2384         elif content.IsType(TYPE_CORPORATION):
   2385             self.UpdateDataCorp(content, typeID, itemID)
   2386         elif content.IsType(TYPE_ALLIANCE):
   2387             self.UpdateDataAlliance(content)
   2388         elif content.IsType(TYPE_FACTION):
   2389             self.UpdateDataFaction(content, typeID, itemID)
   2390         elif content.IsType(TYPE_SHIP):
   2391             self.UpdateDataShip(content, typeID, itemID)
   2392         elif content.IsType(TYPE_STRUCTURE):
   2393             self.UpdateStructure(content, typeID, itemID)
   2394         elif content.IsType(TYPE_MODULE, TYPE_STRUCTURE_OLD, TYPE_STRUCTUREUPGRADE, TYPE_APPAREL, TYPE_STRUCTURE_MODULE):
   2395             self.UpdateDataModule(content, typeID, itemID)
   2396         elif content.IsType(TYPE_DRONE):
   2397             self.UpdateDataDrone(content, typeID, itemID)
   2398         elif content.IsType(TYPE_FIGHTER):
   2399             self.UpdateDataFighter(content, typeID, itemID)
   2400         elif content.IsType(TYPE_CUSTOMSOFFICE):
   2401             self.UpdateDataOrbital(content, itemID)
   2402         elif content.IsType(TYPE_SECURECONTAINER):
   2403             self.UpdateDataSecureContainer(content, itemID)
   2404         elif content.IsType(TYPE_CHARGE):
   2405             self.UpdateDataCharge(content, typeID, itemID)
   2406         elif content.IsType(TYPE_BLUEPRINT):
   2407             content.dynamicTabs.append(TAB_INDUSTRY)
   2408         elif content.IsType(TYPE_STARGATE):
   2409             self.UpdateDataStargate(content, itemID)
   2410         elif content.IsType(TYPE_CELESTIAL):
   2411             self.UpdateDataCelestial(content, typeID, itemID, parentID)
   2412         elif content.IsType(TYPE_ASTEROID):
   2413             self.UpdateDataAsteroid(content, typeID, itemID)
   2414         elif content.IsType(TYPE_ASTEROID_BELT):
   2415             self.update_data_asteroid_belt(itemID, parentID, typeID, content)
   2416             content.dynamicTabs.append(TAB_ASTEROID_BELT_ORE_TYPES)
   2417         elif content.IsType(TYPE_GAS):
   2418             self.UpdateDataGasCloud(content, typeID, itemID)
   2419         elif content.IsType(TYPE_CONTROLTOWER):
   2420             self.UpdateDataControlTower(content, typeID, itemID)
   2421         elif content.IsType(TYPE_GENERICITEM):
   2422             self.UpdateDataGenericItem(content, typeID, itemID)
   2423         elif content.IsType(TYPE_SKILL):
   2424             self.UpdateDataSkill(content, typeID, itemID)
   2425         elif content.IsType(TYPE_SECURITYTAG):
   2426             self.UpdateDataSecurityTag(content, typeID, itemID)
   2427         elif content.IsType(TYPE_STATION) and itemID is not None:
   2428             self.UpdateDataStation(content, typeID, itemID)
   2429         elif content.IsType(TYPE_RANK) and content.abstract_info is not None:
   2430             self.UpdateDataRank(content)
   2431         elif content.IsType(TYPE_CERTIFICATE) and content.abstract_info is not None:
   2432             self.UpdateDataCertificate(content)
   2433         elif content.IsType(TYPE_PLANETPIN):
   2434             self.UpdateDataPlanetPin(content, typeID, itemID)
   2435         elif content.IsType(TYPE_PLANETCOMMODITY):
   2436             content.dynamicTabs.append(TAB_PLANETARYPRODUCTION)
   2437         elif content.IsType(TYPE_PLANET):
   2438             self.UpdateDataPlanet(content, typeID, itemID, parentID)
   2439         elif content.IsType(TYPE_ENTITY):
   2440             self.UpdateDataEntity(content)
   2441         elif content.IsType(TYPE_DEPLOYABLE):
   2442             self.UpdateDataDeployable(content, typeID, itemID)
   2443         elif content.IsType(TYPE_SKINLICENSE):
   2444             content.dynamicTabs.append(TAB_SKINLICENSE)
   2445         elif content.IsType(TYPE_SKINMATERIAL):
   2446             content.dynamicTabs.append(TAB_SKINMATERIAL)
   2447         elif content.IsType(TYPE_MUTATOR):
   2448             self.UpdateDataMutator(content, typeID)
   2449         elif content.IsType(TYPE_EXPERT_SYSTEM):
   2450             self.UpdateExpertSystem(content, typeID)
   2451         elif content.IsType(TYPE_SKYHOOK):
   2452             self.UpdateSkyhook(content, typeID, itemID)
   2453         elif content.IsType(TYPE_SEQUENCE_BINDERS):
   2454             self.UpdateSequenceBinder(content, typeID, itemID)
   2455         elif content.IsType(TYPE_DESIGN_ELEMENTS):
   2456             self.UpdateDesignElement(content, typeID, itemID)
   2457         elif content.IsType(TYPE_PHASE_STABILIZER):
   2458             content.dynamicTabs.append(TAB_PHASE_STABILIZER_MECHANICS)
   2459         elif content.IsType(TYPE_PHASED_ASTEROID):
   2460             self.UpdateDataAsteroid(content, typeID, itemID)
   2461             content.dynamicTabs.append(TAB_PHASE_ASTEROID_MECHANICS)
   2462         elif content.IsType(TYPE_MATERIAL):
   2463             self.UpdateDataMaterial(content, typeID, itemID)
   2464         elif content.IsType(TYPE_JUMP_BRIDGE):
   2465             content.dynamicTabs.append(TAB_JUMP_BRIDGE_MECHANICS)
   2466         if self.HasVariations(typeID):
   2467             content.dynamicTabs.append(TAB_VARIATIONS)
   2468         if self.IsIndustryItem(typeID):
   2469             content.dynamicTabs.append(TAB_ITEMINDUSTRY)
   2470         if content.is_upgradable():
   2471             content.dynamicTabs.append(TAB_UPGRADEMATERIALREQ)
   2472         if not content.IsType(TYPE_FACTION):
   2473             self.UpdateDataIllegal(content, typeID)
   2474         if evetypes.GetGroupID(typeID) == const.groupAgentsinSpace and sm.GetService('godma').GetType(typeID).agentID:
   2475             self.UpdateDataAgent(content, typeID, itemID)
   2476         if typeID == const.typePlasticWrap:
   2477             attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=itemID, typeID=typeID)
   2478             content.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   2479         if evetypes.GetCategoryID(typeID) == const.categoryInfrastructureUpgrade:
   2480             self.UpdateInfrastructureUpgrades(content, typeID, itemID)
   2481         self.ShowReprocessingRequirements(content, typeID, itemID)
   2482         if self.IsAttributesTabShown(content) and not content.data[TAB_ATTIBUTES]['items']:
   2483             self.UpdateAttributes(content)
   2484         self.UpdateComponentData(content, typeID, itemID)
   2485         if prefs.GetValue('showdogmatab', 0) == 1:
   2486             self.UpdateDataDogma(content, typeID)
   2487         if content.IsType(TYPE_SHIP) or content.IsType(TYPE_DRONE):
   2488             self.ApplyAttributeTooltip(content.data[TAB_ATTIBUTES]['items'])
   2489 
   2490     def update_data_asteroid_belt(self, itemID, parentID, typeID, wnd):
   2491         self.UpdateDataCelestial(wnd, typeID, itemID, parentID)
   2492         func = lambda *args: AgencyWndNew.OpenAndShowContentGroup(contentGroupID=contentGroupConst.contentGroupAsteroidBelts)
   2493         wnd.data[DATA_BUTTONS] += [(GetByLabel('UI/Common/AsteroidBelts'), func)]
   2494 
   2495     def IsIndustryItem(self, typeID):
   2496         if evetypes.GetGroupID(typeID) == const.groupStation:
   2497             return False
   2498         if is_reprocessable_type(typeID):
   2499             return True
   2500         if typeID in cfg.blueprintsByMaterialTypeIDs:
   2501             return True
   2502         if is_compressible_type(typeID) or is_compressed_type(typeID):
   2503             return True
   2504         return False
   2505 
   2506     def HasVariations(self, typeID):
   2507         if evetypes.GetGroupID(typeID) == const.groupCommandPins:
   2508             return False
   2509         variants = evetypes.GetVariations(typeID)
   2510         return variants is not None and len(variants) > 0
   2511 
   2512     def _AddVolumeAttributeEntry(self, wnd, typeID):
   2513         wnd.data[TAB_ATTIBUTES]['items'].append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   2514          'label': GetByLabel('UI/Common/Volume'),
   2515          'text': volume_from_type(typeID)}))
   2516 
   2517     def UpdateAttributes(self, wnd):
   2518         attributeScrollListForItem = self.GetAttributeScrollListForItem(itemID=wnd.item_id, typeID=wnd.type_id)
   2519         wnd.data[TAB_ATTIBUTES]['items'] += attributeScrollListForItem
   2520         try:
   2521             effectTypeScrollList = self.GetEffectTypeInfo(wnd.type_id, dogma_data.get_all_effect_ids())
   2522             wnd.data[TAB_ATTIBUTES]['items'] += effectTypeScrollList
   2523         except Exception:
   2524             sys.exc_clear()
   2525 
   2526     def IsAttributesTabShown(self, wnd):
   2527         noShowCatergories = (const.categoryEntity,
   2528          const.categoryStation,
   2529          const.categoryAncientRelic,
   2530          const.categoryBlueprint,
   2531          const.categoryShipSkin,
   2532          const.categoryExpertSystems)
   2533         noShowGroups = (const.groupMoon,
   2534          const.groupPlanet,
   2535          const.groupConstellation,
   2536          const.groupSolarSystem,
   2537          const.groupRegion,
   2538          const.groupLargeCollidableObject,
   2539          const.groupCharacter,
   2540          const.groupCorporation,
   2541          const.groupAlliance,
   2542          const.groupMoonChunk,
   2543          const.groupIndustrialSupportFacility,
   2544          const.groupStationConversionMonument,
   2545          const.groupTournamentChampionMonument)
   2546         return wnd.categoryID not in noShowCatergories and wnd.groupID not in noShowGroups
   2547 
   2548     def GetEntityDamageScrollList(self, typeID):
   2549         attributeDictForType = self.GetAttributeDictForType(typeID)
   2550         totalDps = 0
   2551         missileTypeID = attributeDictForType.get(const.attributeEntityMissileTypeID, None)
   2552         isShootingMissiles = self.TypeHasEffect(const.effectMissileLaunchingForEntity, typeID=typeID)
   2553         if missileTypeID and isShootingMissiles:
   2554             missileRof = attributeDictForType.get(const.attributeMissileLaunchDuration, 1000.0) / 1000
   2555             missileMultiplier = attributeDictForType.get(const.attributeMissileDamageMultiplier, 1.0) / missileRof
   2556             attributeDictForMissile = self.GetAttributeDictForType(missileTypeID)
   2557             missileDpsByDamageType = {x:attributeDictForMissile.get(x, 0.0) * missileMultiplier for x in DAMAGE_ATTRIBUTES}
   2558             totalDps += sum((x for x in missileDpsByDamageType.itervalues()))
   2559         else:
   2560             missileDpsByDamageType = {}
   2561         isShootingTurrets = self.TypeHasEffect(const.effectTargetAttack, typeID=typeID) or self.TypeHasEffect(const.effectTargetDisintegratorAttack, typeID=typeID)
   2562         if isShootingTurrets:
   2563             turretRof = attributeDictForType.get(const.attributeRateOfFire, 1.0) / 1000
   2564             turretDamageMultiplier = attributeDictForType.get(const.attributeDamageMultiplier, 1.0) / turretRof
   2565             turretDpsByDamageType = {x:attributeDictForType.get(x, 0.0) * turretDamageMultiplier for x in DAMAGE_ATTRIBUTES}
   2566             totalDps += sum((x for x in turretDpsByDamageType.itervalues()))
   2567         else:
   2568             turretDpsByDamageType = {}
   2569         if totalDps <= 0:
   2570             return []
   2571         dpsByDamageType = {}
   2572         for eachDamageType in DAMAGE_ATTRIBUTES:
   2573             turretValue = turretDpsByDamageType.get(eachDamageType, 0.0)
   2574             missileValue = missileDpsByDamageType.get(eachDamageType, 0.0)
   2575             dpsByDamageType[eachDamageType] = round((turretValue + missileValue) / totalDps, 2)
   2576 
   2577         unitDict = {x:const.unitAbsolutePercent for x in DAMAGE_ATTRIBUTES}
   2578         scrolllist, _ = self.GetAttributeRows(DAMAGE_ATTRIBUTES, dpsByDamageType, None, overrideUnitDict=unitDict)
   2579         return scrolllist
   2580 
   2581     def GetInsuranceName(self, fraction):
   2582         fraction = '%.1f' % fraction
   2583         label = {'0.5': 'UI/Insurance/BasicInsurance',
   2584          '0.6': 'UI/Insurance/StandardInsurance',
   2585          '0.7': 'UI/Insurance/BronzeInsurance',
   2586          '0.8': 'UI/Insurance/SilverInsurance',
   2587          '0.9': 'UI/Insurance/GoldInsurance',
   2588          '1.0': 'UI/Insurance/PlatinumInsurance'}.get(fraction, fraction)
   2589         return GetByLabel(label)
   2590 
   2591     def GetGAVFunc(self, itemID, typeID):
   2592         info = sm.GetService('godma').GetItem(itemID)
   2593         if info is not None:
   2594             return lambda attributeID: getattr(info, dogma_data.get_attribute_name(attributeID))
   2595         dogmaLocation = self.GetDogmaLocation(itemID)
   2596         if dogmaLocation.IsItemLoaded(itemID):
   2597             return lambda attributeID: dogmaLocation.GetAttributeValue(itemID, attributeID)
   2598         info = sm.GetService('godma').GetStateManager().GetShipType(typeID)
   2599         return lambda attributeID: getattr(info, dogma_data.get_attribute_name(attributeID))
   2600 
   2601     def GetCertEntry(self, certificate, level):
   2602         entry = {'label': certificate.GetName(),
   2603          'level': level,
   2604          'iconID': 'res:/UI/Texture/Classes/Certificates/level%sSmall.png' % level,
   2605          'id': ('CertEntry', '%s_%s' % (certificate.certificateID, level)),
   2606          'certificate': certificate,
   2607          'certID': certificate.certificateID,
   2608          'GetSubContent': CertEntry.GetSubContent,
   2609          'genericDisplayLabel': StripTags(certificate.GetName())}
   2610         return entry
   2611 
   2612     def GetAgentScrollGroups(self, agents, scroll):
   2613         dudesToPrime = []
   2614         locationsToPrime = []
   2615         for each in agents:
   2616             dudesToPrime.append(each.agentID)
   2617             if each.stationID:
   2618                 locationsToPrime.append(each.stationID)
   2619             locationsToPrime.append(each.solarsystemID)
   2620 
   2621         cfg.eveowners.Prime(dudesToPrime)
   2622         cfg.evelocations.Prime(locationsToPrime)
   2623 
   2624         def SortFunc(level, agentID, x, y):
   2625             if x[level] < y[level]:
   2626                 return -1
   2627             if x[level] > y[level]:
   2628                 return 1
   2629             xname = cfg.eveowners.Get(x[agentID]).name
   2630             yname = cfg.eveowners.Get(y[agentID]).name
   2631             if xname < yname:
   2632                 return -1
   2633             if xname > yname:
   2634                 return 1
   2635             return 0
   2636 
   2637         agents.sort(lambda x, y: SortFunc(agents.header.index('level'), agents.header.index('agentID'), x, y))
   2638         allAgents = sm.RemoteSvc('agentMgr').GetAgents().Index('agentID')
   2639         divisions = {}
   2640         for each in agents:
   2641             if allAgents[each[0]].divisionID not in divisions:
   2642                 divisions[allAgents[each[0]].divisionID] = 1
   2643 
   2644         for divisionID in sorted(divisions, key=lambda _divisionID: get_division_name(_divisionID).lower()):
   2645             amt = 0
   2646             for agent in agents:
   2647                 if agent.divisionID == divisionID:
   2648                     amt += 1
   2649 
   2650             label = GetByLabel('UI/InfoWindow/AgentDivisionWithCount', divisionName=get_division_name(divisionID).replace('&', '&amp;'), numAgents=amt)
   2651             scroll.append(GetFromClass(ListGroup, {'GetSubContent': self.GetCorpAgentListSubContent,
   2652              'label': label,
   2653              'agentdata': (divisionID, agents),
   2654              'id': ('AGENTDIVISIONS', divisionID),
   2655              'tabs': [],
   2656              'state': 'locked',
   2657              'showicon': 'hide',
   2658              'showlen': 0}))
   2659 
   2660     def GetBaseWarpSpeed(self, typeID, shipinfo = None, itemID = None):
   2661         defaultWSM = 1.0
   2662         defaultBWS = 3.0
   2663         wsm = dogma_data.get_type_attribute(typeID, const.attributeWarpSpeedMultiplier, defaultWSM)
   2664         bws = dogma_data.get_type_attribute(typeID, const.attributeBaseWarpSpeed, defaultBWS)
   2665         typeWsm = wsm
   2666         typeBws = bws
   2667         if shipinfo:
   2668             wsm = getattr(shipinfo, 'warpSpeedMultiplier', defaultWSM)
   2669             bws = getattr(shipinfo, 'baseWarpSpeed', defaultBWS)
   2670         elif self.IsItemSimulated(itemID):
   2671             dogmaLocation = self.GetDogmaLocation(itemID)
   2672             dogmaItem = dogmaLocation.SafeGetDogmaItem(itemID)
   2673             if dogmaItem:
   2674                 wsm = dogmaLocation.GetAttributeValue(itemID, const.attributeWarpSpeedMultiplier)
   2675                 bws = dogmaLocation.GetAttributeValue(itemID, const.attributeBaseWarpSpeed)
   2676         multipliers = max(1.0, bws) * wsm
   2677         corruptionWarpSpeedIncrease = 0.0
   2678         if itemID == session.shipid:
   2679             corruptionWarpSpeedChecker = CorruptionWarpSpeedIncreaserCheckerClient(session.solarsystemid2)
   2680             corruptionWarpSpeedIncrease = corruptionWarpSpeedChecker.GetWarpSpeedIncrease(session.warfactionid)
   2681             multipliers += corruptionWarpSpeedIncrease
   2682         warpSpeedWithMultipliers = multipliers * const.AU
   2683         typeWarpSpeedWithMultipliers = max(1.0, typeBws) * typeWsm * const.AU
   2684         warpSpeedText = GetByLabel('UI/Fitting/FittingWindow/WarpSpeed', distText=FmtDist(warpSpeedWithMultipliers, 2))
   2685         return (warpSpeedText,
   2686          warpSpeedWithMultipliers,
   2687          typeWarpSpeedWithMultipliers,
   2688          corruptionWarpSpeedIncrease)
   2689 
   2690     def GetKillsRecentKills(self, num, startIndex):
   2691         shipKills = sm.RemoteSvc('charMgr').GetRecentShipKillsAndLosses(num, startIndex)
   2692         return [ k for k in shipKills if k.finalCharacterID == session.charid ]
   2693 
   2694     def GetKillsRecentLosses(self, num, startIndex):
   2695         shipKills = sm.RemoteSvc('charMgr').GetRecentShipKillsAndLosses(num, startIndex)
   2696         return [ k for k in shipKills if k.victimCharacterID == session.charid ]
   2697 
   2698     def FindInContracts(self, typeID):
   2699         sm.GetService('contracts').FindRelated(typeID, None, None, None, None, None)
   2700 
   2701     def ShowMarketDetails(self, typeID):
   2702         uthread.new(sm.StartService('marketutils').ShowMarketDetails, typeID, None)
   2703 
   2704     def ViewExpertSystemInStore(self, typeID):
   2705         from expertSystems.client.util import browse_expert_systems
   2706         browse_expert_systems(typeID)
   2707 
   2708     def GetAllianceHistorySubContent(self, itemID):
   2709         scrolllist = []
   2710         allianceHistory = sm.RemoteSvc('allianceRegistry').GetEmploymentRecord(itemID)
   2711 
   2712         def AddToScroll(**data):
   2713             scrolllist.append(GetFromClass(LabelTextTop, data))
   2714 
   2715         if len(allianceHistory) == 0:
   2716             AddToScroll(line=True, text='', label=GetByLabel('UI/InfoWindow/NoRecordsFound'), typeID=None, itemID=None)
   2717         toPrime = set()
   2718         for allianceRec in allianceHistory[:-1]:
   2719             toPrime.add(allianceRec.allianceID)
   2720 
   2721         toPrime = filter(None, toPrime)
   2722         cfg.eveowners.Prime(toPrime)
   2723         lastQuit = None
   2724         for allianceRec in allianceHistory[:-1]:
   2725             if allianceRec.allianceID is None:
   2726                 lastQuit = allianceRec.startDate
   2727             else:
   2728                 alliance = cfg.eveowners.Get(allianceRec.allianceID)
   2729                 if allianceRec.startDate:
   2730                     sd = FmtDate(allianceRec.startDate, 'ln')
   2731                 else:
   2732                     sd = GetByLabel('UI/InfoWindow/UnknownAllianceStartDate')
   2733                 if allianceRec.deleted:
   2734                     nameTxt = GetByLabel('UI/InfoWindow/AllianceClosed', allianceName=alliance.name)
   2735                 else:
   2736                     nameTxt = alliance.name
   2737                 if lastQuit:
   2738                     ed = FmtDate(lastQuit, 'ln')
   2739                     text = GetByLabel('UI/InfoWindow/InAllianceFromAndTo', allianceName=nameTxt, fromDate=sd, toDate=ed)
   2740                 else:
   2741                     text = GetByLabel('UI/InfoWindow/InAllianceFromAndToThisDay', allianceName=nameTxt, fromDate=sd)
   2742                 AddToScroll(line=True, label=GetByLabel('UI/Common/Alliance'), text=text, typeID=alliance.typeID, itemID=allianceRec.allianceID)
   2743                 lastQuit = None
   2744 
   2745         if len(allianceHistory) > 1:
   2746             scrolllist.append(GetFromClass(DividerEntry))
   2747         if len(allianceHistory) >= 1:
   2748             AddToScroll(line=True, label=GetByLabel('UI/InfoWindow/CorporationFounded'), text=FmtDate(allianceHistory[-1].startDate, 'ln'), typeID=None, itemID=None)
   2749         return scrolllist
   2750 
   2751     def GetWarHistorySubContent(self, itemID, warFactionID = None):
   2752         regwars = sm.RemoteSvc('warsInfoMgr').GetWarsByOwnerID(itemID)
   2753         facwars = []
   2754         scrolllist = []
   2755         if (idCheckers.IsAlliance(itemID) or idCheckers.IsCorporation(itemID)) and warFactionID:
   2756             facwars = sm.GetService('facwar').GetFactionWarsForWarFactionID(warFactionID).values()
   2757         notStartedWars = []
   2758         ongoingWars = []
   2759         finishedWars = []
   2760         currentTime = blue.os.GetWallclockTime()
   2761         for war in regwars:
   2762             warFinished = war.timeFinished
   2763             timeStarted = war.timeStarted
   2764             if warFinished and warFinished < currentTime:
   2765                 finishedWars.append(war)
   2766             elif timeStarted > currentTime:
   2767                 notStartedWars.append(war)
   2768             else:
   2769                 ongoingWars.append(war)
   2770 
   2771         warsGroupedByTypes = [facwars, ongoingWars, notStartedWars]
   2772         if len(finishedWars) < FINISHED_WARS_FOLDER_THRESHOLD:
   2773             warsGroupedByTypes.append(finishedWars)
   2774         self.PrimeWarTypes(warsGroupedByTypes)
   2775         if ongoingWars:
   2776             myLabel = GetByLabel('UI/Corporations/Wars/ActiveWars')
   2777             warGroup = self.GetNormalWarGroup(sorted(ongoingWars, key=lambda w: w.timeStarted), myLabel, 'ongoingWars')
   2778             scrolllist.append(warGroup)
   2779         if facwars:
   2780             myLabel = GetByLabel('UI/Corporations/Wars/FactionalWars')
   2781             warGroup = self.GetNormalWarGroup(facwars, myLabel, 'factional')
   2782             scrolllist.append(warGroup)
   2783         if notStartedWars:
   2784             myLabel = GetByLabel('UI/Corporations/Wars/PendingWars')
   2785             warGroup = self.GetNormalWarGroup(sorted(notStartedWars, key=lambda w: w.timeStarted), myLabel, 'notStartedWars')
   2786             scrolllist.append(warGroup)
   2787         if finishedWars:
   2788             myLabel = GetByLabel('UI/Corporations/Wars/FinishedWars')
   2789             warGroup = self.GetFinishedWarsGroup(sorted(finishedWars, key=lambda w: w.timeFinished), myLabel, 'finished')
   2790             scrolllist.append(warGroup)
   2791         return scrolllist
   2792 
   2793     def PrimeWarTypes(self, warsGroupedByTypes):
   2794         owners = set()
   2795         for wars in warsGroupedByTypes:
   2796             ownersForWars = self.GetOwnersForWars(wars)
   2797             owners.update(ownersForWars)
   2798 
   2799         if len(owners):
   2800             cfg.eveowners.Prime(owners)
   2801             cfg.corptickernames.Prime(owners)
   2802 
   2803     def GetOwnersForWars(self, wars):
   2804         owners = set()
   2805         for war in wars:
   2806             if war.declaredByID not in owners:
   2807                 owners.add(war.declaredByID)
   2808             if war.againstID not in owners:
   2809                 owners.add(war.againstID)
   2810 
   2811         return owners
   2812 
   2813     def GetFinishedWarsGroup(self, groupItems, label, groupType):
   2814         subContentFunc = self.GetFinishedWarSubContent
   2815         return self.GetWarGroup(groupItems, label, groupType, subContentFunc)
   2816 
   2817     def GetNormalWarGroup(self, groupItems, label, groupType, sublevel = 0):
   2818         subContentFunc = self.GetWarSubContent
   2819         return self.GetWarGroup(groupItems, label, groupType, subContentFunc, sublevel)
   2820 
   2821     def GetWarGroup(self, groupItems, label, groupType, subContentFunc, sublevel = 0):
   2822         return GetFromClass(ListGroup, {'GetSubContent': subContentFunc,
   2823          'label': label,
   2824          'id': ('war', groupType, label),
   2825          'state': 'locked',
   2826          'BlockOpenWindow': 1,
   2827          'showicon': 'hide',
   2828          'showlen': 1,
   2829          'groupName': groupType,
   2830          'groupItems': groupItems,
   2831          'updateOnToggle': 0,
   2832          'sublevel': sublevel})
   2833 
   2834     def GetWarSubContent(self, items, *args):
   2835         scrolllist = []
   2836         data = utillib.KeyVal()
   2837         data.label = ''
   2838         wars = items.groupItems
   2839         if items.groupName != 'factional':
   2840             wars = sorted(wars, key=lambda x: x.timeDeclared, reverse=True)
   2841         for war in wars:
   2842             data.war = war
   2843             scrolllist.append(GetFromClass(WarEntry, data))
   2844 
   2845         return scrolllist
   2846 
   2847     def GetFinishedWarSubContent(self, items, *args):
   2848         finishedWars = items.groupItems
   2849         if len(finishedWars) < FINISHED_WARS_FOLDER_THRESHOLD:
   2850             self.PrimeWarTypes([finishedWars])
   2851             return self.GetWarSubContent(items)
   2852         warsByYears = self.GetWarsByYearList(finishedWars)
   2853         scrolllist = []
   2854         for eachYear, warList in warsByYears:
   2855             warGroup = self.GetWarGroup(warList, eachYear, 'eachYear_%s' % eachYear, self.GetYearSubcontentForFinishedWars, sublevel=1)
   2856             scrolllist.append(warGroup)
   2857 
   2858         return scrolllist
   2859 
   2860     def GetWarsByYearList(self, warList):
   2861         warsByYears = defaultdict(set)
   2862         for eachWar in warList:
   2863             year, _, _, _, _, _, _, _ = blue.os.GetTimeParts(eachWar.timeFinished)
   2864             warsByYears[year].add(eachWar)
   2865 
   2866         if not warsByYears:
   2867             return []
   2868         warsByYearsList = warsByYears.items()
   2869         warsByYearsList.sort(key=lambda x: x[0], reverse=True)
   2870         return warsByYearsList
   2871 
   2872     def GetYearSubcontentForFinishedWars(self, items, *args):
   2873         wars = items.groupItems
   2874         self.PrimeWarTypes([wars])
   2875         return self.GetWarSubContent(items)
   2876 
   2877     def GetEmploymentHistorySubContent(self, itemID):
   2878         scrolllist = []
   2879         employmentHistory, charTransfers = sm.RemoteSvc('corporationSvc').GetEmployementRecordAndCharacterTransfers(itemID)
   2880         nextDate = None
   2881         nextDateRaw = None
   2882         corpIDsToPrime = {j.corporationID for j in employmentHistory}
   2883         cfg.eveowners.Prime(corpIDsToPrime)
   2884         for job in employmentHistory:
   2885             corp = cfg.eveowners.Get(job.corporationID)
   2886             corpName = evelink.client.owner_link(job.corporationID)
   2887             if job.deleted:
   2888                 nameText = GetByLabel('UI/InfoWindow/CorporationClosed', corpName=corpName)
   2889             else:
   2890                 nameText = corpName
   2891             date = FmtDate(job.startDate, 'ls')
   2892             if nextDate is None:
   2893                 text = GetByLabel('UI/InfoWindow/InCorpFromAndToThisDay', corpName=nameText, fromDate=date)
   2894             else:
   2895                 text = GetByLabel('UI/InfoWindow/InCorpFromAndTo', corpName=nameText, fromDate=date, toDate=nextDate)
   2896             endDate = nextDateRaw or blue.os.GetWallclockTime()
   2897             diff = endDate - job.startDate
   2898             numDays = max(1, diff / const.DAY)
   2899             numDaysText = GetByLabel('UI/Common/NumDays', numDays=numDays).strip()
   2900             text = '%s (%s)' % (text, numDaysText)
   2901             nextDate = date
   2902             nextDateRaw = job.startDate
   2903             entry = GetFromClass(Text, {'text': text,
   2904              'typeID': corp.typeID,
   2905              'itemID': job.corporationID})
   2906             scrolllist.append(entry)
   2907 
   2908         if charTransfers:
   2909             scrolllist.append(GetFromClass(Space, {'height': 20}))
   2910             groupEntry = GetFromClass(ListGroup, {'GetSubContent': self.GetCharacterTranfersSubContent,
   2911              'label': GetByLabel('UI/InfoWindow/CharacterTransfers'),
   2912              'groupItems': charTransfers,
   2913              'id': ('character_transfers', 1),
   2914              'showlen': 1,
   2915              'showicon': 'hide',
   2916              'state': 'locked'})
   2917             scrolllist.append(groupEntry)
   2918         return scrolllist
   2919 
   2920     def GetCharacterTranfersSubContent(self, nodedata, *args):
   2921         charTransfers = nodedata.groupItems
   2922         scrollList = []
   2923         for eachTransfer in charTransfers:
   2924             text = GetByLabel('UI/InfoWindow/CharacterTransferredDate', transferDate=eachTransfer.transferDate)
   2925             entry = GetFromClass(Generic, {'label': text,
   2926              'sublevel': 1})
   2927             scrollList.append((eachTransfer.transferDate, entry))
   2928 
   2929         scrollList = SortListOfTuples(scrollList, reverse=True)
   2930         return scrollList
   2931 
   2932     def GetAllianceMembersSubContent(self, itemID):
   2933         members = sm.RemoteSvc('allianceRegistry').GetAllianceMembers(itemID)
   2934         cfg.eveowners.Prime([ m.corporationID for m in members ])
   2935         scrolllist = []
   2936         for m in members:
   2937             corp = cfg.eveowners.Get(m.corporationID)
   2938             scrolllist.append(GetFromClass(LabelTextTop, {'line': True,
   2939              'label': GetByLabel('UI/Common/Corporation'),
   2940              'text': corp.name,
   2941              'typeID': corp.typeID,
   2942              'itemID': m.corporationID}))
   2943 
   2944         return scrolllist
   2945 
   2946     def GetCorpAgentListSubContent(self, tmp, *args):
   2947         divisionID, agents = tmp.agentdata
   2948         scrolllist = []
   2949         scrolllist.append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/AvailableToYou')}))
   2950         noadd = 1
   2951         for agent in agents:
   2952             if agent.divisionID != divisionID:
   2953                 continue
   2954             isLimitedToFacWar = False
   2955             if agent.agentTypeID == const.agentTypeFactionalWarfareAgent and sm.StartService('facwar').GetCorporationWarFactionID(agent.corporationID) != session.warfactionid:
   2956                 isLimitedToFacWar = True
   2957             if sm.GetService('standing').CanUseAgent(agent.factionID, agent.corporationID, agent.agentID, agent.level, agent.agentTypeID) and isLimitedToFacWar == False:
   2958                 scrolllist.append(GetFromClass(AgentEntry, {'charID': agent.agentID,
   2959                  'defaultDivisionID': agent.divisionID}))
   2960                 noadd = 0
   2961 
   2962         if noadd:
   2963             scrolllist.pop(-1)
   2964         scrolllist.append(GetFromClass(Header, {'label': GetByLabel('UI/InfoWindow/NotAvailableToYou')}))
   2965         noadd = 1
   2966         for agent in agents:
   2967             if agent.divisionID != divisionID:
   2968                 continue
   2969             isLimitedToFacWar = False
   2970             if agent.agentTypeID == const.agentTypeFactionalWarfareAgent and sm.StartService('facwar').GetCorporationWarFactionID(agent.corporationID) != session.warfactionid:
   2971                 isLimitedToFacWar = True
   2972             if not sm.GetService('standing').CanUseAgent(agent.factionID, agent.corporationID, agent.agentID, agent.level, agent.agentTypeID) or isLimitedToFacWar == True:
   2973                 scrolllist.append(GetFromClass(AgentEntry, {'charID': agent.agentID,
   2974                  'defaultDivisionID': agent.divisionID}))
   2975                 noadd = 0
   2976 
   2977         if noadd:
   2978             scrolllist.pop(-1)
   2979         return scrolllist
   2980 
   2981     def __GetIllegalityString(self, illegality):
   2982         textList = self.__GetIllegalityStringList(illegality)
   2983         if len(textList) > 0:
   2984             text = ' / '.join(textList)
   2985         else:
   2986             text = ''
   2987         return text
   2988 
   2989     def __GetIllegalityStringList(self, illegality):
   2990         textList = []
   2991         if illegality.standingLoss > 0.0:
   2992             t = GetByLabel('UI/InfoWindow/StandingLoss', standingLoss=illegality.standingLoss)
   2993             textList.append(t)
   2994         if illegality.confiscateMinSec <= 1.0:
   2995             t = GetByLabel('UI/InfoWindow/ConfiscationInSec', confiscateMinSec=max(illegality.confiscateMinSec, 0.0))
   2996             textList.append(t)
   2997         if illegality.fineByValue > 0.0:
   2998             t = GetByLabel('UI/InfoWindow/FineOfEstimatedMarketValue', fine=illegality.fineByValue * 100.0)
   2999             textList.append(t)
   3000         if illegality.attackMinSec <= 1.0:
   3001             t = GetByLabel('UI/InfoWindow/AttackInSec', attackMinSec=max(illegality.attackMinSec, 0.0))
   3002             textList.append(t)
   3003         return textList
   3004 
   3005     def GetAttributeScrollListForItem(self, itemID, typeID, attrList = None, banAttrs = []):
   3006         attributeDictForType, attributeDict = self.GetAttributeDictForItem(itemID, typeID)
   3007         modifiedAttributesDict = self.FindAttributesThatHaveBeenModified(attributeDictForType, attributeDict)
   3008         modifiedAttributesDict = self.FindMutatedAttributes(typeID, itemID, attributeDictForType, modifiedAttributesDict)
   3009         if not attributeDict:
   3010             attributeDict = attributeDictForType
   3011         scrolllist = self.GetAttributeScrollListFromAttributeDict(attrdict=attributeDict, attrList=attrList, banAttrs=banAttrs, itemID=itemID, typeID=typeID, modifiedAttributesDict=modifiedAttributesDict)
   3012         return scrolllist
   3013 
   3014     def FindAttributesThatHaveBeenModified(self, typeDict, itemDict):
   3015         modifiedAttributes = {}
   3016         for itemAttributeKey, itemValue in itemDict.iteritems():
   3017             typeValue = typeDict.get(itemAttributeKey, dogma_data.get_attribute_default_value(itemAttributeKey))
   3018             if itemValue != typeValue:
   3019                 m = CreateAttribute(itemAttributeKey, itemValue, typeValue)
   3020                 modifiedAttributes[itemAttributeKey] = m
   3021 
   3022         return modifiedAttributes
   3023 
   3024     def FindMutatedAttributes(self, typeID, itemID, typeAttributes = None, attributes = None):
   3025         if typeAttributes is None:
   3026             typeAttributes = self.GetAttributeDictForType(typeID)
   3027         if attributes is None:
   3028             attributes = {}
   3029         dynamicItemSvc = sm.GetService('dynamicItemSvc')
   3030         if not dynamicItemSvc.IsDynamicItem(typeID) or itemID is None:
   3031             return attributes
   3032         item = dynamicItemSvc.GetDynamicItem(itemID)
   3033         sourceAttributes = self.GetAttributeDictForType(item.sourceTypeID)
   3034         mutatorAttributes = dynamicitemattributes.GetMutatorAttributes(item.mutatorTypeID)
   3035         for attributeID, mutatorAttribute in mutatorAttributes.iteritems():
   3036             if attributeID in attributes:
   3037                 attribute = attributes[attributeID]
   3038             else:
   3039                 attribute = Attribute(attributeID, typeAttributes[attributeID])
   3040             sourceValue = sourceAttributes[attributeID]
   3041             attributes[attributeID] = MutatedAttribute(attribute, sourceValue, mutatorAttribute.min * sourceValue, mutatorAttribute.max * sourceValue, getattr(mutatorAttribute, 'highIsGood', None))
   3042 
   3043         return attributes
   3044 
   3045     def GetDogmaLocation(self, itemID):
   3046         if self.IsItemSimulated(itemID):
   3047             dogmaLocation = sm.GetService('clientDogmaIM').GetFittingDogmaLocation()
   3048         else:
   3049             dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation()
   3050         return dogmaLocation
   3051 
   3052     def IsItemSimulated(self, itemID):
   3053         if isinstance(itemID, tuple):
   3054             itemID = itemID[0]
   3055         if isinstance(itemID, basestring):
   3056             return True
   3057         return False
   3058 
   3059     def GetSpaceComponentAttrItemInfo(self, typeID, itemID):
   3060         scrolllist = []
   3061         attributeCollection = {}
   3062         componentNames = get_space_component_names_for_type(typeID)
   3063         if len(componentNames) == 0:
   3064             return scrolllist
   3065         componentInstances = self.GetComponentInstance(itemID)
   3066         for componentName in componentNames:
   3067             try:
   3068                 componentClass = factory.GetComponentClass(componentName)
   3069                 if hasattr(componentClass, 'GetAttributeInfo'):
   3070                     instance = componentInstances.get(componentName)
   3071                     attributes = get_space_component_for_type(typeID, componentName)
   3072                     attributeList = componentClass.GetAttributeInfo(typeID, attributes, instance, localization)
   3073                     attributeCollection[componentName] = attributeList
   3074             except KeyError:
   3075                 pass
   3076 
   3077         for attributeList in IterAttributeCollectionInInfoOrder(attributeCollection):
   3078             for entryClass, entryData in attributeList:
   3079                 scrolllist.append(GetFromClass(entryClass, entryData))
   3080 
   3081         return scrolllist
   3082 
   3083     def GetComponentInstance(self, itemID):
   3084         componentInstances = {}
   3085         if itemID:
   3086             ballpark = sm.GetService('michelle').GetBallpark()
   3087             if ballpark:
   3088                 try:
   3089                     componentInstances = ballpark.componentRegistry.GetComponentsByItemID(itemID)
   3090                 except (AttributeError, KeyError):
   3091                     pass
   3092 
   3093         return componentInstances
   3094 
   3095     def GetAttributesSuppressedByComponents(self, typeID):
   3096         componentNames = get_space_component_names_for_type(typeID)
   3097         suppressedAttributeIDs = []
   3098         for componentName in componentNames:
   3099             self._TryAddSuppressedComponentAttributeIDs(componentName, suppressedAttributeIDs)
   3100 
   3101         return suppressedAttributeIDs
   3102 
   3103     def _TryAddSuppressedComponentAttributeIDs(self, componentName, suppressedAttributeIDs):
   3104         try:
   3105             componentClass = factory.GetComponentClass(componentName)
   3106             if hasattr(componentClass, 'GetSuppressedDogmaAttributeIDs'):
   3107                 suppressedAttributeIDs.extend(componentClass.GetSuppressedDogmaAttributeIDs())
   3108         except KeyError:
   3109             pass
   3110 
   3111     def GetAttributeScrollListForType(self, typeID, attrList = None, attrValues = None, banAttrs = [], itemID = None):
   3112         attributeDict, itemAttributeDict = self.GetAttributeDictForItem(itemID, typeID)
   3113         if itemAttributeDict:
   3114             attributeDict = itemAttributeDict
   3115         scrolllist = self.GetAttributeScrollListFromAttributeDict(attrdict=attributeDict, attrList=attrList, attrValues=attrValues, banAttrs=banAttrs, itemID=itemID, typeID=typeID)
   3116         return scrolllist
   3117 
   3118     def GetAttributeRows(self, tryAddAttributeIDs, attrdict, itemID, modifiedAttributesDict = {}, overrideUnitDict = None):
   3119         overrideUnitDict = overrideUnitDict or {}
   3120         newScrollEntries = []
   3121         attributeListInfo = [(0, dogma_attr_groups.damage_type_attribute_ids, 'UI/Common/Damage'),
   3122          (1, dogma_attr_groups.damage_resistance_bonuse_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/DamageResistanceBonuses'),
   3123          (2, dogma_attr_groups.hull_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/HullDamageResistanceHeader'),
   3124          (3, dogma_attr_groups.armor_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader'),
   3125          (4, dogma_attr_groups.shield_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/ShieldDamageResistanceHeader'),
   3126          (5, dogma_attr_groups.ecm_sensor_strength_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/SensorStrength'),
   3127          (6, dogma_attr_groups.ecm_jammer_strength_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/EcmJammerStrength'),
   3128          (7, dogma_attr_groups.sensor_strength_bonus_attrs, 'UI/Inflight/ModuleRacks/Tooltips/SensorStrengthBonuses'),
   3129          (8, dogma_attr_groups.passive_armor_damage_type_resonance_attributes, 'UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader'),
   3130          (9, dogma_attr_groups.passive_shield_damage_type_resonance_attributes, 'UI/Inflight/ModuleRacks/Tooltips/ShieldDamageResistanceHeader')]
   3131         allGroupedAttributes = []
   3132         for attributeGroup in attributeListInfo:
   3133             allGroupedAttributes += attributeGroup[1]
   3134 
   3135         attributesAdded = []
   3136         for eachAttributeID in tryAddAttributeIDs:
   3137             if eachAttributeID not in allGroupedAttributes or eachAttributeID in attributesAdded:
   3138                 continue
   3139             for eachAttributeListInfo in attributeListInfo:
   3140                 sortIdx, eachAttributeList, textPath = eachAttributeListInfo
   3141                 if eachAttributeID not in eachAttributeList:
   3142                     continue
   3143                 allAttributes = []
   3144                 for xID in eachAttributeList:
   3145                     value = attrdict.get(xID, 0)
   3146                     formatInfo = GetFormattedAttributeAndValue(xID, value, overrideUnitDict.get(xID, None))
   3147                     if formatInfo:
   3148                         formatValue = formatInfo.value
   3149                     else:
   3150                         formatValue = None
   3151                     allAttributes.append((xID, formatValue))
   3152 
   3153                 validValues = filter(None, [ a[1] for a in allAttributes ])
   3154                 if not validValues:
   3155                     continue
   3156                 modifiedAttributes = {x:modifiedAttributesDict[x] for x in eachAttributeList if x in modifiedAttributesDict}
   3157                 entry = GetFromClass(AttributeRowEntry, {'labelPath': textPath,
   3158                  'attributeValues': allAttributes,
   3159                  'attributeIDs': [ a[0] for a in allAttributes ],
   3160                  'OnClickAttr': lambda attributeID: self.OnAttributeClick(attributeID, itemID),
   3161                  'modifiedAttributesDict': modifiedAttributes,
   3162                  'itemID': itemID})
   3163                 newScrollEntries.append((sortIdx, entry))
   3164                 attributesAdded += eachAttributeList
   3165                 break
   3166 
   3167         newScrollEntries = SortListOfTuples(newScrollEntries)
   3168         return (newScrollEntries, attributesAdded)
   3169 
   3170     def GetAttributeRowData(self, tryAddAttributeIDs, attrdict, itemID, modifiedAttributesDict = {}, overrideUnitDict = None):
   3171         overrideUnitDict = overrideUnitDict or {}
   3172         newScrollEntries = []
   3173         attributeListInfo = [(0, dogma_attr_groups.damage_type_attribute_ids, 'UI/Common/Damage'),
   3174          (1, dogma_attr_groups.damage_resistance_bonuse_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/DamageResistanceBonuses'),
   3175          (2, dogma_attr_groups.hull_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/HullDamageResistanceHeader'),
   3176          (3, dogma_attr_groups.armor_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader'),
   3177          (4, dogma_attr_groups.shield_resistance_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/ShieldDamageResistanceHeader'),
   3178          (5, dogma_attr_groups.ecm_sensor_strength_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/SensorStrength'),
   3179          (6, dogma_attr_groups.ecm_jammer_strength_attribute_ids, 'UI/Inflight/ModuleRacks/Tooltips/EcmJammerStrength'),
   3180          (7, dogma_attr_groups.sensor_strength_bonus_attrs, 'UI/Inflight/ModuleRacks/Tooltips/SensorStrengthBonuses'),
   3181          (8, dogma_attr_groups.passive_armor_damage_type_resonance_attributes, 'UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader'),
   3182          (9, dogma_attr_groups.passive_shield_damage_type_resonance_attributes, 'UI/Inflight/ModuleRacks/Tooltips/ShieldDamageResistanceHeader')]
   3183         allGroupedAttributes = []
   3184         for attributeGroup in attributeListInfo:
   3185             allGroupedAttributes += attributeGroup[1]
   3186 
   3187         attributesAdded = []
   3188         for eachAttributeID in tryAddAttributeIDs:
   3189             if eachAttributeID not in allGroupedAttributes or eachAttributeID in attributesAdded:
   3190                 continue
   3191             for eachAttributeListInfo in attributeListInfo:
   3192                 sortIdx, eachAttributeList, textPath = eachAttributeListInfo
   3193                 if eachAttributeID not in eachAttributeList:
   3194                     continue
   3195                 allAttributes = []
   3196                 for xID in eachAttributeList:
   3197                     value = attrdict.get(xID, 0)
   3198                     formatInfo = GetFormattedAttributeAndValue(xID, value, overrideUnitDict.get(xID, None))
   3199                     if formatInfo:
   3200                         formatValue = formatInfo.value
   3201                     else:
   3202                         formatValue = None
   3203                     allAttributes.append((xID, formatValue))
   3204 
   3205                 validValues = filter(None, [ a[1] for a in allAttributes ])
   3206                 if not validValues:
   3207                     continue
   3208                 modifiedAttributes = {x:modifiedAttributesDict[x] for x in eachAttributeList if x in modifiedAttributesDict}
   3209                 entry = {'labelPath': textPath,
   3210                  'attributeValues': allAttributes,
   3211                  'attributeIDs': [ a[0] for a in allAttributes ],
   3212                  'OnClickAttr': lambda attributeID: self.OnAttributeClick(attributeID, itemID),
   3213                  'modifiedAttributesDict': modifiedAttributes,
   3214                  'itemID': itemID}
   3215                 newScrollEntries.append(entry)
   3216                 attributesAdded += eachAttributeList
   3217                 break
   3218 
   3219         return (newScrollEntries, attributesAdded)
   3220 
   3221     def GetAttributeScrollListFromAttributeDict(self, attrdict, attrList = None, attrValues = None, banAttrs = [], itemID = None, typeID = None, modifiedAttributesDict = {}):
   3222         scrolllist = []
   3223         if attrValues:
   3224             for each in attrValues.displayAttributes:
   3225                 attrdict[each.attributeID] = each.value
   3226 
   3227         attrList = attrList or attrdict.keys()
   3228         aggregateAttributes = defaultdict(list)
   3229         for attrID in tuple(attrList):
   3230             if attrID in const.canFitShipGroups or attrID in const.canFitShipTypes:
   3231                 dgmType = dogma_data.get_attribute(attrID)
   3232                 value = attrdict[attrID]
   3233                 formattedValue = GetFormatAndValue(dgmType, value)
   3234                 groupOrType = 'group' if attrID in const.canFitShipGroups else 'type'
   3235                 aggregateAttributes['canFitShip'].append((formattedValue, groupOrType, value))
   3236                 attrList.remove(attrID)
   3237 
   3238         order = dogma_attr_groups.required_skill_attribute_ids
   3239         tryAddAttributeIDs = []
   3240         for attrID_ in order:
   3241             if attrID_ in attrList and attrID_ not in banAttrs:
   3242                 tryAddAttributeIDs.append(attrID_)
   3243 
   3244         for attrID_ in attrList:
   3245             if attrID_ not in order and attrID_ not in banAttrs:
   3246                 tryAddAttributeIDs.append(attrID_)
   3247 
   3248         newAttributeRows, attributesAddedInRows = self.GetAttributeRows(tryAddAttributeIDs, attrdict, itemID, modifiedAttributesDict)
   3249 
   3250         def TryAddAttributeEntry(attrID):
   3251             if attrID not in attrdict:
   3252                 return
   3253             modifiedAttribute = modifiedAttributesDict.get(attrID)
   3254             listItem = self.GetEntryForAttribute(attrID, attrdict[attrID], itemID, typeID=typeID, modifiedAttribute=modifiedAttribute)
   3255             if listItem:
   3256                 scrolllist.append(listItem)
   3257 
   3258         for attrID_ in tryAddAttributeIDs:
   3259             if attrID_ not in attributesAddedInRows:
   3260                 TryAddAttributeEntry(attrID_)
   3261 
   3262         attributeValues = aggregateAttributes.get('canFitShip')
   3263         if attributeValues is not None:
   3264             attrID = const.canFitShipTypes[0]
   3265             iconID = dogma_data.get_attribute_icon_id(attrID)
   3266             displayName = dogma_data.get_attribute_display_name(attrID)
   3267             rightTextLabels = []
   3268             for text, groupOrType, value in attributeValues:
   3269                 if groupOrType == 'group':
   3270                     groupID = int(value)
   3271                     typeIDs = evetypes.GetTypeIDsByGroup(groupID)
   3272                     typeNames = [ evetypes.GetName(x) for x in typeIDs if evetypes.IsPublished(x) ]
   3273                     typeNames.sort()
   3274                     if typeNames:
   3275                         headerLabelPath = 'UI/InfoWindow/StructureTypes' if evetypes.GetCategoryIDByGroup(groupID) == const.categoryStructure else 'UI/InfoWindow/ShipTypes'
   3276                         typeNames.insert(0, localization.GetByLabel(headerLabelPath))
   3277                     hintText = '<br>'.join(typeNames)
   3278                     rightTextLabels.append((text, hintText))
   3279                 else:
   3280                     rightTextLabels.append((text, None))
   3281 
   3282             listItem = GetFromClass(LabelMultilineTextTop, {'attributeID': attrID,
   3283              'OnClick': (self.OnAttributeClick, attrID, itemID),
   3284              'line': 1,
   3285              'label': displayName,
   3286              'rightTextLabels': rightTextLabels,
   3287              'iconID': iconID,
   3288              'typeID': None,
   3289              'itemID': itemID})
   3290             scrolllist.append(listItem)
   3291         scrolllist += newAttributeRows
   3292         return scrolllist
   3293 
   3294     def GetAttributeDictForItem(self, itemID, typeID):
   3295         attributeDictForType = self.GetAttributeDictForType(typeID)
   3296         if not itemID:
   3297             return (attributeDictForType, attributeDictForType)
   3298         if dynamicitemattributes.IsDynamicType(typeID):
   3299             attributeDictForType = sm.GetService('dynamicItemSvc').GetDynamicItemAttributes(itemID)
   3300         attributeDictForItem = {}
   3301         attributeDictForItem.update(attributeDictForType)
   3302         itemAttributesDict = self.GetDisplayAttributesForItem(itemID)
   3303         if not itemAttributesDict:
   3304             itemAttributesDict = self.GetDisplayAttributeForDogmaItem(itemID, attributeDictForType.keys())
   3305         attributeDictForItem.update(itemAttributesDict)
   3306         return (attributeDictForType, attributeDictForItem)
   3307 
   3308     def GetAttributeDictForType(self, typeID):
   3309         typeAttributesByAttributeID = dogma_data.get_type_attributes_by_id(typeID)
   3310         attributeIDs = {const.attributeCapacity, const.attributeVolume}
   3311         attributeIDs.update(typeAttributesByAttributeID.keys())
   3312         ret = {}
   3313         for attributeID in attributeIDs:
   3314             attribute = dogma_data.get_attribute(attributeID)
   3315             if attribute.dataType == dogma_const.attributeDataTypeTypeMirror:
   3316                 try:
   3317                     ret[attributeID] = evetypes.GetAttributeForType(typeID, attribute.name)
   3318                 except Exception:
   3319                     pass
   3320 
   3321             else:
   3322                 ret[attributeID] = typeAttributesByAttributeID[attributeID].value
   3323 
   3324         return ret
   3325 
   3326     def GetDisplayAttributesForItem(self, itemID):
   3327         godmaItem = sm.GetService('godma').GetItem(itemID)
   3328         if not godmaItem:
   3329             return {}
   3330         displayAttributes = {a.attributeID:a.value for a in godmaItem.displayAttributes}
   3331         if evetypes.GetCategoryID(godmaItem.typeID) in (const.categoryCharge, const.groupFrequencyCrystal):
   3332             self._UpdateChargeDamageWithDamageModifier(godmaItem, displayAttributes)
   3333         return displayAttributes
   3334 
   3335     def _UpdateChargeDamageWithDamageModifier(self, godmaChargeItem, displayAttributes):
   3336         if not godmaChargeItem.IsFitted():
   3337             return
   3338         dogmaLocation = self.GetDogmaLocation(godmaChargeItem.itemID)
   3339         moduleID = dogmaLocation.GetSlotOther(godmaChargeItem.locationID, godmaChargeItem.flagID)
   3340         if not moduleID:
   3341             return
   3342         moduleItem = dogmaLocation.SafeGetDogmaItem(moduleID)
   3343         if self.TypeHasEffect(const.effectLauncherFitted, typeID=moduleItem.typeID):
   3344             damageModifier = dogmaLocation.GetAccurateAttributeValue(session.charid, const.attributeMissileDamageMultiplier)
   3345         else:
   3346             damageModifier = dogmaLocation.GetAccurateAttributeValue(moduleID, const.attributeDamageMultiplier)
   3347         if not damageModifier:
   3348             return
   3349         for eachAttributeID in DAMAGE_ATTRIBUTES:
   3350             if eachAttributeID in displayAttributes:
   3351                 displayAttributes[eachAttributeID] *= damageModifier
   3352 
   3353     def GetDisplayAttributeForDogmaItem(self, itemID, attributeKeys):
   3354         dogmaLocation = self.GetDogmaLocation(itemID)
   3355         if not dogmaLocation.IsItemLoaded(itemID):
   3356             return {}
   3357         attributeDict = {}
   3358         for attributeID in attributeKeys:
   3359             value = dogmaLocation.GetAttributeValue(itemID, attributeID)
   3360             attributeDict[attributeID] = value
   3361 
   3362         return attributeDict
   3363 
   3364     def GetEntryForAttribute(self, attributeID, value, itemID = None, typeID = None, modifiedAttribute = None):
   3365         listItem = self.GetStatusBarEntryForAttribute(attributeID, itemID=itemID, typeID=typeID, modifiedAttribute=modifiedAttribute)
   3366         if listItem:
   3367             return listItem
   3368         data = self.GetDataForAttribute(attributeID, value, itemID, typeID, modifiedAttribute)
   3369         if data is None:
   3370             return
   3371         listItem = GetFromClass(LabelTextSidesAttributes, data=data)
   3372         return listItem
   3373 
   3374     def GetDataForAttribute(self, attributeID, value, itemID = None, typeID = None, modifiedAttribute = None):
   3375         if attributeID == const.attributeMetaLevel:
   3376             metaLevel = evetypes.GetMetaLevel(typeID)
   3377             if metaLevel is not None:
   3378                 value = metaLevel
   3379         attribute = GetAttribute(attributeID)
   3380         formatInfo = GetFormattedAttributeAndValue(attributeID, value)
   3381         if not formatInfo:
   3382             return
   3383         if itemID and formatInfo.infoTypeID and typeID != formatInfo.infoTypeID:
   3384             itemID = None
   3385         if attributeID == const.attributeVolume:
   3386             if typeID == const.typePlasticWrap and itemID is not None:
   3387                 packagedVolume = GetVolumeForPlasticItem(itemID)
   3388                 value = packagedVolume
   3389             else:
   3390                 packagedVolume = GetTypeVolume(typeID, 1)
   3391             if value != packagedVolume:
   3392                 text = GetByLabel('UI/InfoWindow/ItemVolumeWithPackagedVolume', volume=value, packaged=packagedVolume, unit=FormatUnit(const.unitVolume))
   3393             else:
   3394                 formatedValue = FormatValue(value, const.attributeVolume)
   3395                 text = GetByLabel('UI/InfoWindow/ValueAndUnit', value=formatedValue, unit=FormatUnit(const.unitVolume))
   3396         else:
   3397             text = formatInfo.value
   3398         return {'attributeID': attributeID,
   3399          'OnClick': (self.OnAttributeClick, attributeID, itemID),
   3400          'line': 1,
   3401          'label': formatInfo.displayName,
   3402          'text': text,
   3403          'iconID': formatInfo.iconID,
   3404          'typeID': formatInfo.infoTypeID,
   3405          'itemID': itemID,
   3406          'modifiedAttribute': modifiedAttribute}
   3407 
   3408     def OnAttributeClick(self, id_, itemID):
   3409         ctrl = uicore.uilib.Key(uiconst.VK_CONTROL)
   3410         shift = uicore.uilib.Key(uiconst.VK_SHIFT)
   3411         if not ctrl:
   3412             return
   3413         if not shift and itemID is not None and (itemID >= const.minPlayerItem or idCheckers.IsCharacter(itemID)):
   3414             sm.GetService('godma').LogAttributeViaGodma(itemID, id_)
   3415         if session.role & ROLE_CONTENT == ROLE_CONTENT and ctrl and shift:
   3416             self.GetUrlAdamDogmaAttribute(id_)
   3417 
   3418     def GetUrlAdamDogmaAttribute(self, id_):
   3419         uthread.new(self.ClickURL, 'http://adam:50001/gd/type.py?action=DogmaModifyAttributeForm&attributeID=%s' % id_)
   3420 
   3421     def ClickURL(self, url, *args):
   3422         blue.os.ShellExecute(url)
   3423 
   3424     def GetSkillAttrs(self):
   3425         skillAttrs = [ getattr(const, 'attributeRequiredSkill%s' % i, None) for i in xrange(1, 7) if hasattr(const, 'attributeRequiredSkill%s' % i) ] + [ getattr(const, 'attributeRequiredSkill%sLevel' % i, None) for i in xrange(1, 7) if hasattr(const, 'attributeRequiredSkill%sLevel' % i) ]
   3426         return skillAttrs
   3427 
   3428     def GetReqSkillInfo(self, typeID, reqSkills = [], showPrereqSkills = True):
   3429         scrolllist = []
   3430         i = 1
   3431         commands = []
   3432         skills = None
   3433         if typeID is not None:
   3434             skills = sm.GetService('skills').GetRequiredSkills(typeID).items()
   3435         if reqSkills:
   3436             skills = reqSkills
   3437         if skills is None:
   3438             return
   3439         for skillID, lvl in skills:
   3440             ret = self.DrawSkillTree(skillID, lvl, scrolllist, 0, showPrereqSkills=showPrereqSkills)
   3441             commands += ret
   3442             i += 1
   3443 
   3444         cmds = {}
   3445         for typeID, level in commands:
   3446             typeID, level = int(typeID), int(level)
   3447             currentLevel = cmds.get(typeID, 0)
   3448             cmds[typeID] = max(currentLevel, level)
   3449 
   3450         if i > 1 and session.role & ROLE_GML == ROLE_GML:
   3451             scrolllist.append(GetFromClass(ButtonEntry, {'label': 'GM: Give me these skills',
   3452              'caption': 'Give',
   3453              'OnClick': self.DoGiveSkills,
   3454              'args': (cmds,)}))
   3455         return scrolllist
   3456 
   3457     def GetRecommendedFor(self, certID):
   3458         recommendedFor = sm.StartService('certificates').GetCertificateRecommendationsFromCertificateID(certID)
   3459         recommendedGroups = {}
   3460         for typeID in recommendedFor:
   3461             if not evetypes.IsPublished(typeID):
   3462                 continue
   3463             groupID = evetypes.GetGroupID(typeID)
   3464             current = recommendedGroups.get(groupID, [])
   3465             current.append(typeID)
   3466             recommendedGroups[groupID] = current
   3467 
   3468         scrolllist = []
   3469         for groupID, value in recommendedGroups.iteritems():
   3470             label = evetypes.GetGroupNameByGroup(groupID)
   3471             scrolllist.append((label, GetFromClass(ListGroup, {'GetSubContent': self.GetEntries,
   3472               'label': label,
   3473               'groupItems': value,
   3474               'id': ('cert_shipGroups', groupID),
   3475               'sublevel': 0,
   3476               'showlen': 1,
   3477               'showicon': 'hide',
   3478               'state': 'locked'})))
   3479 
   3480         scrolllist = SortListOfTuples(scrolllist)
   3481         return scrolllist
   3482 
   3483     def GetEntries(self, data, *args):
   3484         scrolllist = []
   3485         for typeID in data.groupItems:
   3486             entry = self.CreateEntry(typeID)
   3487             scrolllist.append(entry)
   3488 
   3489         return scrolllist
   3490 
   3491     def CreateEntry(self, typeID, *args):
   3492         return GetFromClass(Item, {'line': 1,
   3493          'label': evetypes.GetName(typeID),
   3494          'sublevel': 1,
   3495          'showinfo': 1,
   3496          'typeID': typeID,
   3497          'getIcon': True})
   3498 
   3499     def DoGiveSkills(self, cmds, button):
   3500         cntFrom = 1
   3501         cntTo = len(cmds) + 1
   3502         sm.GetService('loading').ProgressWnd('GM Skill Gift', '', cntFrom, cntTo)
   3503         for typeID, level in cmds.iteritems():
   3504             cntFrom = cntFrom + 1
   3505             sm.GetService('loading').ProgressWnd('GM Skill Gift', 'Training of the skill %s to level %d has been completed' % (evetypes.GetName(typeID), level), cntFrom, cntTo)
   3506             sm.RemoteSvc('slash').SlashCmd('/giveskill me %s %s' % (typeID, level))
   3507 
   3508         sm.GetService('loading').ProgressWnd('Done', '', cntTo, cntTo)
   3509         sm.GetService('skills').ForceRefresh()
   3510 
   3511     def DoRemoveSkill(self, typeID):
   3512         sm.RemoteSvc('slash').SlashCmd('/removeskill me %s' % typeID)
   3513         message_player('Skill %s has been removed' % evetypes.GetName(typeID))
   3514 
   3515     def GetGMGiveSkillMenu(self, typeID):
   3516         subMenu = (('Remove', self.DoRemoveSkill, (typeID,)),
   3517          ('0', self.DoGiveSkills, ({typeID: 0}, None)),
   3518          ('1', self.DoGiveSkills, ({typeID: 1}, None)),
   3519          ('2', self.DoGiveSkills, ({typeID: 2}, None)),
   3520          ('3', self.DoGiveSkills, ({typeID: 3}, None)),
   3521          ('4', self.DoGiveSkills, ({typeID: 4}, None)),
   3522          ('5', self.DoGiveSkills, ({typeID: 5}, None)))
   3523         return (('GM: Modify skill level', subMenu), ('GM: typeID: %s' % typeID, blue.pyos.SetClipboardData, (str(typeID),)))
   3524 
   3525     def DoCreateMaterials(self, commands, header = 'GML: Create in cargo', qty = 10, button = None):
   3526         runs = {'qty': qty}
   3527         if qty > 1:
   3528             runs = uix.QtyPopup(100000, 1, qty, None, header)
   3529         if runs is not None and 'qty' in runs and runs['qty'] > 0:
   3530             cntFrom = 1
   3531             cntTo = len(commands) + 1
   3532             sm.GetService('loading').ProgressWnd(GetByLabel('UI/Common/GiveLoot'), '', cntFrom, cntTo)
   3533             for typeID, quantity in commands:
   3534                 cntFrom = cntFrom + 1
   3535                 actualQty = quantity * runs['qty']
   3536                 qtyText = '%(quantity)s items(s) of %(typename)s' % {'quantity': quantity * runs['qty'],
   3537                  'typename': evetypes.GetName(typeID)}
   3538                 sm.GetService('loading').ProgressWnd(GetByLabel('UI/Common/GiveLoot'), qtyText, cntFrom, cntTo)
   3539                 if actualQty > 0:
   3540                     if session.role & ROLE_WORLDMOD:
   3541                         sm.RemoteSvc('slash').SlashCmd('/create %s %d' % (typeID, actualQty))
   3542                     elif session.role & ROLE_GML:
   3543                         sm.RemoteSvc('slash').SlashCmd('/load me %s %d' % (typeID, actualQty))
   3544 
   3545             sm.GetService('loading').ProgressWnd('Done', '', cntTo, cntTo)
   3546 
   3547     def DrawSkillTree(self, typeID, lvl, scrolllist, indent, done = None, firstID = None, showPrereqSkills = True):
   3548         thisSet = [(typeID, lvl)]
   3549         if done is None:
   3550             done = []
   3551         if firstID is None:
   3552             firstID = typeID
   3553         scrolllist.append(GetFromClass(SkillTreeEntry, {'line': 1,
   3554          'typeID': typeID,
   3555          'lvl': lvl,
   3556          'indent': indent + 1,
   3557          'origin': ORIGIN_SHOWINFO}))
   3558         done.append(typeID)
   3559         current = typeID
   3560         if showPrereqSkills:
   3561             for typeID, lvl in sm.GetService('skills').GetRequiredSkills(typeID).iteritems():
   3562                 if typeID == current:
   3563                     log.LogWarn('Here I have skill which has it self as required skill... skillTypeID is ' + str(typeID))
   3564                     continue
   3565                 newSet = self.DrawSkillTree(typeID, lvl, scrolllist, indent + 1, done, firstID)
   3566                 thisSet = thisSet + newSet
   3567 
   3568         return thisSet
   3569 
   3570     def GetEffectTypeInfo(self, typeID, effList):
   3571         scrolllist = []
   3572         thisTypeEffects = dogma_data.get_type_effects(typeID)
   3573         for effectID in effList:
   3574             itemDgmEffect = self.TypeHasEffect(effectID, thisTypeEffects)
   3575             if not itemDgmEffect:
   3576                 continue
   3577             effTypeInfo = dogma_data.get_effect(effectID)
   3578             if effTypeInfo.published:
   3579                 scrolllist.append(GetFromClass(LabelTextSidesAttributes, {'line': 1,
   3580                  'label': dogma_data.get_effect_display_name(effectID),
   3581                  'text': dogma_data.get_effect_description(effectID),
   3582                  'iconID': effTypeInfo.iconID}))
   3583 
   3584         return scrolllist
   3585 
   3586     def FilterZero(self, value):
   3587         if value == 0:
   3588             return None
   3589         return value
   3590 
   3591     def TypeHasEffect(self, effectID, itemEffectTypeInfo = None, typeID = None):
   3592         if itemEffectTypeInfo is None:
   3593             itemEffectTypeInfo = dogma_data.get_type_effects(typeID)
   3594         for itemDgmEffect in itemEffectTypeInfo:
   3595             if itemDgmEffect.effectID == effectID:
   3596                 return itemDgmEffect
   3597 
   3598         return 0
   3599 
   3600     def SetDestination(self, itemID):
   3601         sm.StartService('starmap').SetWaypoint(itemID, clearOtherWaypoints=True)
   3602 
   3603     def Bookmark(self, itemID, typeID, parentID, *args):
   3604         sm.GetService('addressbook').BookmarkLocationPopup(itemID, typeID, parentID)
   3605 
   3606     def GetColorCodedSecurityStringForSystem(self, solarsystemID, itemName):
   3607         return u'{security_status}<t>{item_name}'.format(security_status=eveformat.solar_system_security_status(solarsystemID), item_name=itemName)
   3608 
   3609     def OnShowOwnerDetailsWindow(self, targetID):
   3610         if idCheckers.IsCharacter(targetID):
   3611             self.ShowInfo(const.typeCharacter, targetID)
   3612         elif idCheckers.IsCorporation(targetID):
   3613             self.ShowInfo(const.typeCorporation, targetID)
   3614         elif idCheckers.IsAlliance(targetID):
   3615             self.ShowInfo(const.typeAlliance, targetID)