compare.py (33341B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\compare.py 2 from collections import OrderedDict 3 import eveformat 4 import telemetry 5 import carbonui.const as uiconst 6 import dogma.data as dogma_data 7 import evetypes 8 import inventorycommon 9 import localization 10 import metaGroups 11 from carbonui.control.checkbox import Checkbox 12 from carbonui.control.dragResizeCont import DragResizeCont 13 from carbonui.primitives.container import Container 14 from clientsettings.setting import UserSettingBool 15 from dogma.attributes import uiAttributeGroups 16 from dogma.attributes.format import FormatUnit, GetFormatAndValue 17 import dogma.const as dogma_const 18 import dogma.attributes.groups as dogma_groups 19 from eve.client.script.ui.control import eveScroll 20 from carbonui.button.group import ButtonGroup, ButtonSizeMode 21 from eve.client.script.ui.control.entries.checkbox import CheckboxEntry 22 from eve.client.script.ui.control.entries.header import Header 23 from eve.client.script.ui.control.entries.item import Item 24 from eve.client.script.ui.control.entries.label_text import LabelTextTop 25 from eve.client.script.ui.control.entries.util import GetFromClass 26 from carbonui.control.window import Window 27 from player_messaging.client.ui_message import message_player, prompt_player_fsd_dialog 28 from eve.common.script.util import eveFormat 29 from eveservices.menu import GetMenuService 30 from inventorycommon.const import compareCategories 31 from inventorycommon.typeHelpers import GetAveragePrice 32 from localization import GetByLabel 33 from utillib import KeyVal 34 LEFT_PANEL_MIN_WIDTH = 160 35 LEFT_PANEL_MAX_WIDTH = 280 36 allowedGuids = ['xtriui.InvItem', 37 'xtriui.FittingSlot', 38 'listentry.InvItem', 39 'listentry.GenericMarketItem', 40 'listentry.QuickbarItem', 41 'listentry.InvAssetItem', 42 'xtriui.ShipUIModule', 43 'uicls.GenericDraggableForTypeID', 44 'listentry.Item', 45 'listentry.KillItems', 46 'listentry.FittingModuleEntry'] 47 EST_PRICE_CONFIG = 'compare_estPriceChecked' 48 only_show_diffrentiators = UserSettingBool('compare_onlyShowDifferent', False) 49 50 class TypeData(object): 51 52 def __init__(self, typeID, itemID = None, godmaAttributes = None): 53 if godmaAttributes is not None: 54 self.godmaAttributes = godmaAttributes 55 else: 56 self.godmaAttributes = {} 57 dynamicItemSvc = sm.GetService('dynamicItemSvc') 58 if dynamicItemSvc.IsDynamicItem(typeID): 59 for attributeID, value in dynamicItemSvc.GetDynamicItemAttributes(itemID).iteritems(): 60 self.godmaAttributes[attributeID] = value 61 62 else: 63 for attribute in sm.GetService('godma').GetType(typeID).displayAttributes: 64 self.godmaAttributes[attribute.attributeID] = attribute.value 65 66 self.typeID = typeID 67 self.itemID = itemID 68 69 def GetAttributeValue(self, attributeID): 70 return self.godmaAttributes.get(attributeID, None) 71 72 73 class TypeCompare(Window): 74 default_windowID = 'typecompare' 75 default_iconNum = 'res:/ui/Texture/WindowIcons/comparetool.png' 76 default_captionLabelPath = 'Tooltips/Neocom/CompareTool' 77 default_descriptionLabelPath = 'Tooltips/Neocom/CompareTool_description' 78 default_minSize = (350, 400) 79 default_width = 600 80 default_height = 500 81 82 def ApplyAttributes(self, attributes): 83 super(TypeCompare, self).ApplyAttributes(attributes) 84 typeID = attributes.typeID 85 self.dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 86 self.types = [] 87 self.attributeIDsUserSelectable = [] 88 self.attributesCombined = [] 89 self.attributeIDsCurrentlyChecked = [] 90 self.activeAttributesChecked = set() 91 self.banAttrs = sm.GetService('info').GetSkillAttrs() 92 self.attributeLimit = 10 93 self.typeLimit = 40 94 self.settingsinited = 0 95 self.graphinited = 0 96 self.topLevelMarketGroup = None 97 self.ConstructLayout() 98 if typeID: 99 typeIDs = evetypes.GetVariations(typeID) 100 for _typeID in typeIDs: 101 if not evetypes.IsDynamicType(_typeID): 102 self.AddTypeID(_typeID) 103 104 only_show_diffrentiators.on_change.connect(self.OnOnlyShowDiffrentiatorsSetting) 105 106 def ConstructLayout(self): 107 self.mainCont = Container(name='mainCont', parent=self.sr.main) 108 self.ConstructAttributeScroll() 109 self.ConstructTypeScroll() 110 self.ConstructButtonGroup() 111 112 def ConstructButtonGroup(self): 113 btns = ((localization.GetByLabel('UI/Commands/UncheckAll'), 114 self.SelectAll, 115 (0,), 116 None), (localization.GetByLabel('UI/Commands/ResetAll'), 117 self.RemoveAllEntries, 118 (), 119 None)) 120 ButtonGroup(btns=btns, parent=self.sr.main, padTop=8, idx=0, button_size_mode=ButtonSizeMode.DYNAMIC) 121 122 def ConstructAttributeScroll(self): 123 self.leftCont = DragResizeCont(parent=self.mainCont, align=uiconst.TOLEFT, state=uiconst.UI_HIDDEN, settingsID='compare_DragResizeCont', minSize=LEFT_PANEL_MIN_WIDTH, defaultSize=200, maxSize=LEFT_PANEL_MAX_WIDTH) 124 self.attributeScroll = eveScroll.Scroll(name='attributescroll', parent=self.leftCont, padding=(0, 125 20, 126 0, 127 const.defaultPadding)) 128 self.attributeScroll.sr.id = 'typecompare_attributescroll' 129 self.attributeScroll.hiliteSorted = 0 130 self.attributeScroll.ShowHint(localization.GetByLabel('UI/Compare/NothingToCompare')) 131 132 def ConstructTypeScroll(self): 133 self.typeScroll = eveScroll.Scroll(name='typescroll', parent=self.mainCont, padTop=const.defaultPadding) 134 self.typeScroll.ShowHint(localization.GetByLabel('UI/Compare/CompareToolHint')) 135 self.typeScroll.sr.id = 'typecompare_typescroll' 136 self.typeScroll.sr.content.OnDropData = self.OnDropData 137 138 def SettingMenu(self, menuParent): 139 onlyShowDifferent = only_show_diffrentiators.is_enabled() 140 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Compare/OnlyShowDifferent'), checked=onlyShowDifferent, callback=only_show_diffrentiators.toggle) 141 142 def GetMenuMoreOptions(self): 143 menuData = super(TypeCompare, self).GetMenuMoreOptions() 144 menuData.AddCheckbox(text=GetByLabel('UI/Compare/OnlyShowDifferent'), setting=only_show_diffrentiators) 145 return menuData 146 147 def OnOnlyShowDiffrentiatorsSetting(self, value): 148 self.ReloadAttributeScroll() 149 self.ReloadTypeCompareScroll() 150 151 def RemoveAllEntries(self, *args): 152 self.types = [] 153 self.topLevelMarketGroup = None 154 self.SelectAll() 155 156 def SelectAll(self, onOff = 0): 157 if onOff: 158 return 159 self.attributeIDsCurrentlyChecked = [] 160 self.activeAttributesChecked.clear() 161 self.OnColumnChanged() 162 163 def AddTypeID(self, typeID, itemID = None): 164 currTypeIDs = [ node.typeID for node in self.types ] 165 if typeID in currTypeIDs: 166 return 167 if not self._IsValidTopLevelMarketGroupID(typeID, itemID): 168 prompt_player_fsd_dialog('CannotCompareNoneItem') 169 return 170 categoryID = evetypes.GetCategoryID(typeID) 171 if categoryID not in compareCategories: 172 message_player(localization.GetByLabel('UI/Compare/CannotCompareThisItem', typeID=typeID)) 173 return 174 typeData = TypeData(typeID, itemID) 175 if typeData not in self.types: 176 self.types.append(typeData) 177 self.OnColumnChanged() 178 if only_show_diffrentiators.is_enabled(): 179 self.ReloadAttributeScroll() 180 181 def AddVariantsOf(self, typeID): 182 typeIDs = evetypes.GetVariations(typeID) 183 for _typeID in typeIDs: 184 self.AddTypeID(_typeID) 185 186 def _IsValidTopLevelMarketGroupID(self, typeID, itemID): 187 dynamicItemSvc = sm.GetService('dynamicItemSvc') 188 if dynamicItemSvc.IsDynamicItem(typeID): 189 mutatedItem = sm.GetService('dynamicItemSvc').GetDynamicItem(itemID) 190 topLevelMarketGroupID = self.GetTopLevelMarketGroupID(mutatedItem.sourceTypeID) 191 else: 192 topLevelMarketGroupID = self.GetTopLevelMarketGroupID(typeID) 193 return topLevelMarketGroupID != -1 194 195 def RemoveEntry(self, node): 196 nodes = self.typeScroll.GetSelected() or [node] 197 toRemove = [ node.typeID for node in nodes ] 198 self.types = [ typeData for typeData in self.types if typeData.typeID not in toRemove ] 199 if not self.types: 200 self.attributeIDsCurrentlyChecked = [] 201 self.activeAttributesChecked.clear() 202 self.topLevelMarketGroup = None 203 self.OnColumnChanged() 204 205 def OnColumnChanged(self, force = 1, *args): 206 self.attributesCombined = self.GetCombinedDogmaAttributes() 207 if force: 208 self.ReloadAttributeScroll() 209 self.ReloadTypeCompareScroll() 210 211 def GetTopLevelMarketGroupID(self, typeID): 212 marketGroupIDFromType = None 213 marketGroupID = evetypes.GetMarketGroupID(typeID) 214 if marketGroupID is None: 215 parentID = evetypes.GetParentIDOfVariations(typeID) 216 if parentID is not None: 217 marketGroupIDFromType = evetypes.GetMarketGroupID(parentID) 218 topLevelMarketGroupID = self.GetTopLevelMarketGroupIDEx(marketGroupIDFromType) 219 else: 220 return -1 221 else: 222 topLevelMarketGroupID = self.GetTopLevelMarketGroupIDEx(marketGroupID) 223 if not self.topLevelMarketGroup: 224 if marketGroupIDFromType: 225 self.topLevelMarketGroup = self.GetTopLevelMarketGroupIDEx(marketGroupIDFromType) 226 else: 227 self.topLevelMarketGroup = self.GetTopLevelMarketGroupIDEx(marketGroupID) 228 return topLevelMarketGroupID 229 230 def GetTopLevelMarketGroupIDEx(self, marketGroupID): 231 mg = sm.GetService('marketutils').GetMarketGroup(marketGroupID) 232 if mg and hasattr(mg, 'parentGroupID'): 233 parentGroupID = mg.parentGroupID 234 while parentGroupID: 235 mg = sm.GetService('marketutils').GetMarketGroup(parentGroupID) 236 parentGroupID = mg.parentGroupID 237 238 return mg.marketGroupID 239 else: 240 return None 241 242 def GetCombinedDogmaAttributes(self): 243 attributeIDs = [] 244 attributes = [] 245 for typeData in self.types: 246 dynamicItemSvc = sm.GetService('dynamicItemSvc') 247 if dynamicItemSvc.IsDynamicItem(typeData.typeID): 248 item = dynamicItemSvc.GetDynamicItem(typeData.itemID) 249 attributeDict = sm.GetService('info').GetAttributeDictForType(item.sourceTypeID) 250 else: 251 attributeDict = sm.GetService('info').GetAttributeDictForType(typeData.typeID) 252 for attributeID, value in attributeDict.iteritems(): 253 if attributeID not in self.banAttrs and attributeID not in attributeIDs: 254 attributeIDs.append(attributeID) 255 dgmAttribs = dogma_data.get_attribute(attributeID) 256 if dgmAttribs.published or dgmAttribs.attributeID in (dogma_const.attributeHp, dogma_const.attributeBaseWarpSpeed): 257 attributes.append(dgmAttribs) 258 259 attributesToRemove = [] 260 for attribute in attributes: 261 removeIt = True 262 for typeData in self.types: 263 value = typeData.GetAttributeValue(attribute.attributeID) 264 if value: 265 removeIt = False 266 break 267 268 if removeIt: 269 attributesToRemove.append(attribute) 270 271 return attributes 272 273 def ReloadAttributeScroll(self): 274 scrolllist = self.GetAttributeScrollList() 275 self.attributeScroll.Load(contentList=scrolllist, noContentHint=localization.GetByLabel('UI/Compare/NothingToCompare')) 276 277 def GetAttributeScrollList(self): 278 attributes = self.GetAttributesToOffer() 279 attributeIDs = {x.attributeID for x in attributes} 280 self.attributeIDsUserSelectable = [] 281 categoryID = evetypes.GetCategoryID(self.types[0].typeID) if self.types else None 282 if categoryID in (const.categoryShip, const.categoryDrone): 283 scrolllist = self._GetScrollListShipOrDrone(attributes, attributeIDs, categoryID) 284 else: 285 scrolllist = [] 286 for attribute in attributes: 287 self._AppendScrollEntry(attribute, scrolllist) 288 289 if scrolllist and self.ShouldShowEstPriceCheckbox(): 290 estPriceEntry = self.GetEstPriceEntry() 291 scrolllist.insert(0, estPriceEntry) 292 return scrolllist 293 294 def _GetScrollListShipOrDrone(self, attributes, attributeIDs, categoryID): 295 scrolllist = [] 296 attrAndFittings = OrderedDict() 297 attrAndFittings.update(self.GetShipAndDroneAttributes()) 298 attrAndFittings.update(self.GetFittings()) 299 for caption, attrs in attrAndFittings.iteritems(): 300 normalAttributes = attrs['normalAttributes'] 301 groupedAttributes = [ x[1] for x in attrs.get('groupedAttributes', []) ] 302 allAttributes = list(normalAttributes) + list(groupedAttributes) 303 shipAttr = [ attribute for attribute in attributes if attribute.attributeID in allAttributes ] 304 if shipAttr: 305 scrolllist.append(GetFromClass(Header, {'label': caption})) 306 for attribute in shipAttr: 307 self._AppendScrollEntry(attribute, scrolllist) 308 309 if categoryID == const.categoryShip and caption == localization.GetByLabel('UI/Compare/Propulsion'): 310 if dogma_const.attributeBaseWarpSpeed in attributeIDs: 311 attribute = dogma_data.get_attribute(dogma_const.attributeBaseWarpSpeed) 312 self._AppendScrollEntry(attribute, scrolllist) 313 314 if categoryID == const.categoryDrone: 315 otherAttributes = [ x for x in attributes if x.attributeID not in self.attributeIDsUserSelectable ] 316 if otherAttributes: 317 scrolllist.append(GetFromClass(Header, {'label': localization.GetByLabel('UI/InfoWindow/Miscellaneous')})) 318 for attribute in otherAttributes: 319 self._AppendScrollEntry(attribute, scrolllist) 320 321 return scrolllist 322 323 def GetShipAndDroneAttributes(self): 324 shipAttributes = OrderedDict() 325 shipAttributes[GetByLabel('UI/Fitting/Structure')] = {'normalAttributes': [dogma_const.attributeHp, 326 dogma_const.attributeCapacity, 327 dogma_const.attributeStructureDamageLimit, 328 dogma_const.attributeDroneCapacity, 329 dogma_const.attributeFrigateEscapeBayCapacity, 330 dogma_const.attributeDroneBandwidth, 331 dogma_const.attributeMass, 332 dogma_const.attributeVolume, 333 dogma_const.attributeAgility, 334 dogma_const.attributeSpecialAmmoHoldCapacity, 335 dogma_const.attributeSpecialGasHoldCapacity, 336 dogma_const.attributeSpecialIceHoldCapacity, 337 dogma_const.attributeSpecialIndustrialShipHoldCapacity, 338 dogma_const.attributeSpecialLargeShipHoldCapacity, 339 dogma_const.attributeSpecialMediumShipHoldCapacity, 340 dogma_const.attributeSpecialMineralHoldCapacity, 341 dogma_const.attributeGeneralMiningHoldCapacity, 342 dogma_const.attributeSpecialAsteroidHoldCapacity, 343 dogma_const.attributeSpecialSalvageHoldCapacity, 344 dogma_const.attributeSpecialShipHoldCapacity, 345 dogma_const.attributeSpecialSmallShipHoldCapacity, 346 dogma_const.attributeSpecialCommandCenterHoldCapacity, 347 dogma_const.attributeSpecialPlanetaryCommoditiesHoldCapacity, 348 dogma_const.attributeSpecialSubsystemHoldCapacity, 349 dogma_const.attributeSpecialCorpseHoldCapacity, 350 dogma_const.attributeSpecialBoosterHoldCapacity, 351 dogma_const.attributeSpecialMobileDepotHoldCapacity, 352 dogma_const.attributeSpecialColonyResourcesHoldCapacity], 353 'groupedAttributes': [('em', dogma_const.attributeEmDamageResonance), 354 ('thermal', dogma_const.attributeThermalDamageResonance), 355 ('kinetic', dogma_const.attributeKineticDamageResonance), 356 ('explosive', dogma_const.attributeExplosiveDamageResonance)]} 357 shipAttributes[GetByLabel('UI/Common/Armor')] = {'normalAttributes': [dogma_const.attributeArmorHP, dogma_const.attributeArmorDamageLimit], 358 'groupedAttributes': [('em', dogma_const.attributeArmorEmDamageResonance), 359 ('thermal', dogma_const.attributeArmorThermalDamageResonance), 360 ('kinetic', dogma_const.attributeArmorKineticDamageResonance), 361 ('explosive', dogma_const.attributeArmorExplosiveDamageResonance)]} 362 shipAttributes[GetByLabel('UI/Common/Shield')] = {'normalAttributes': [dogma_const.attributeShieldCapacity, dogma_const.attributeShieldRechargeRate, dogma_const.attributeShieldDamageLimit], 363 'groupedAttributes': [('em', dogma_const.attributeShieldEmDamageResonance), 364 ('thermal', dogma_const.attributeShieldThermalDamageResonance), 365 ('kinetic', dogma_const.attributeShieldKineticDamageResonance), 366 ('explosive', dogma_const.attributeShieldExplosiveDamageResonance)]} 367 shipAttributes[GetByLabel('UI/Common/EWarResistances')] = {'normalAttributes': [dogma_const.attributeECMResistance, 368 dogma_const.attributeRemoteAssistanceImpedance, 369 dogma_const.attributeRemoteRepairImpedance, 370 dogma_const.attributeEnergyWarfareResistance, 371 dogma_const.attributeSensorDampenerResistance, 372 dogma_const.attributeStasisWebifierResistance, 373 dogma_const.attributeTargetPainterResistance, 374 dogma_const.attributeWeaponDisruptionResistance]} 375 shipAttributes[GetByLabel('UI/Fitting/FittingWindow/Capacitor')] = {'normalAttributes': [dogma_const.attributeCapacitorCapacity, dogma_const.attributeRechargeRate]} 376 shipAttributes[GetByLabel('UI/Fitting/FittingWindow/Targeting')] = {'normalAttributes': [dogma_const.attributeMaxTargetRange, 377 dogma_const.attributeMaxRange, 378 dogma_const.attributeMaxLockedTargets, 379 dogma_const.attributeSignatureRadius, 380 dogma_const.attributeOptimalSigRadius, 381 dogma_const.attributeScanResolution, 382 dogma_const.attributeScanLadarStrength, 383 dogma_const.attributeScanMagnetometricStrength, 384 dogma_const.attributeScanRadarStrength, 385 dogma_const.attributeScanGravimetricStrength, 386 dogma_const.attributeProximityRange, 387 dogma_const.attributeFalloff, 388 dogma_const.attributeTrackingSpeed]} 389 shipAttributes[GetByLabel('UI/InfoWindow/SharedFacilities')] = {'normalAttributes': [dogma_const.attributeFleetHangarCapacity, 390 dogma_const.attributeShipMaintenanceBayCapacity, 391 dogma_const.attributeMaxJumpClones, 392 dogma_const.attributeReclonerFuelType]} 393 shipAttributes[GetByLabel('UI/InfoWindow/FighterFacilities')] = {'normalAttributes': [dogma_const.attributeFighterCapacity, 394 dogma_const.attributeFighterTubes, 395 dogma_const.attributeFighterLightSlots, 396 dogma_const.attributeFighterSupportSlots, 397 dogma_const.attributeFighterHeavySlots, 398 dogma_const.attributeFighterStandupLightSlots, 399 dogma_const.attributeFighterStandupSupportSlots, 400 dogma_const.attributeFighterStandupHeavySlots]} 401 shipAttributes[GetByLabel('UI/InfoWindow/OnDeath')] = {'normalAttributes': [dogma_const.attributeOnDeathAOERadius, 402 dogma_const.attributeOnDeathSignatureRadius, 403 dogma_const.attributeOnDeathDamageEM, 404 dogma_const.attributeOnDeathDamageTherm, 405 dogma_const.attributeOnDeathDamageKin, 406 dogma_const.attributeOnDeathDamageExp]} 407 shipAttributes[GetByLabel('UI/InfoWindow/JumpDriveSystems')] = {'normalAttributes': [dogma_const.attributeJumpDriveCapacitorNeed, 408 dogma_const.attributeJumpDriveRange, 409 dogma_const.attributeJumpDriveConsumptionType, 410 dogma_const.attributeJumpDriveConsumptionAmount, 411 dogma_const.attributeJumpDriveDuration, 412 dogma_const.attributeJumpPortalCapacitorNeed, 413 dogma_const.attributeJumpPortalConsumptionMassFactor, 414 dogma_const.attributeJumpPortalDuration, 415 dogma_const.attributeSpecialFuelBayCapacity, 416 dogma_const.attributeGroupJumpDriveConsumptionAmount, 417 dogma_const.attributeConduitJumpPassengerCount]} 418 shipAttributes[GetByLabel('UI/Compare/Propulsion')] = {'normalAttributes': [dogma_const.attributeMaxVelocity]} 419 return shipAttributes 420 421 def _AppendScrollEntry(self, attribute, scrolllist): 422 displayName = dogma_data.get_attribute_display_name(attribute.attributeID) 423 if displayName: 424 scrolllist.append(self.GetScrollEntry(attribute)) 425 self.attributeIDsUserSelectable.append(attribute.attributeID) 426 427 @telemetry.ZONE_METHOD 428 def GetAttributesToOffer(self): 429 if not only_show_diffrentiators.is_enabled() or len(self.types) < 2: 430 return self.attributesCombined 431 else: 432 return self._GetAttributesThatDiffrentiate() 433 434 def _GetAttributesThatDiffrentiate(self): 435 allAvailableAttributesByID = OrderedDict() 436 for attribute in self.attributesCombined: 437 allAvailableAttributesByID[attribute.attributeID] = attribute 438 439 differentAttributesDict = OrderedDict() 440 for eachAttributeID, attribute in allAvailableAttributesByID.iteritems(): 441 attributeValues = [] 442 for typeData in self.types: 443 if eachAttributeID == dogma_const.attributeBaseWarpSpeed: 444 value = self.GetWarpValue(typeData) 445 else: 446 value = typeData.GetAttributeValue(attribute.attributeID) 447 if attributeValues and value not in attributeValues: 448 differentAttributesDict[eachAttributeID] = attribute 449 break 450 else: 451 attributeValues.append(value) 452 453 attributes = differentAttributesDict.values() 454 return attributes 455 456 def ShouldShowEstPriceCheckbox(self): 457 if not only_show_diffrentiators.is_enabled(): 458 return True 459 if len(self.types) < 2: 460 return True 461 estPriceSet = set() 462 for typeData in self.types: 463 estPriceSet.add(GetAveragePrice(typeData.typeID)) 464 465 return len(estPriceSet) > 1 466 467 def GetFittings(self): 468 fittingDict = {localization.GetByLabel('UI/Fitting/FittingWindow/Fitting'): {'normalAttributes': dogma_groups.fitting_attribute_ids}} 469 return fittingDict 470 471 def GetScrollEntry(self, entry): 472 displayName = dogma_data.get_attribute_display_name(entry.attributeID) 473 return GetFromClass(AttributeCheckbox, {'line': 1, 474 'info': entry, 475 'label': displayName, 476 'iconID': getattr(entry, 'iconID', None), 477 'item': entry, 478 'text': FormatUnit(getattr(entry, 'unitID', None)) or ' ', 479 'hint': displayName, 480 'checked': entry.attributeID in self.attributeIDsCurrentlyChecked, 481 'cfgname': entry.attributeID, 482 'OnChange': self.OnAttributeSelectedChanged}) 483 484 def OnAttributeSelectedChanged(self, checkbox, *args): 485 attributeID = checkbox.GetSettingsKey() 486 if checkbox.GetValue(): 487 if len(self.activeAttributesChecked) < self.attributeLimit: 488 if attributeID not in self.attributeIDsCurrentlyChecked: 489 self.attributeIDsCurrentlyChecked.append(attributeID) 490 self.OnColumnChanged(force=0) 491 else: 492 checkbox.SetValue(False) 493 message = localization.GetByLabel('UI/Compare/CanOnlyCompareAmountAttributes', amount=self.attributeLimit) 494 prompt_player_fsd_dialog('CustomInfo', {'info': message}) 495 else: 496 if attributeID in self.attributeIDsCurrentlyChecked: 497 self.attributeIDsCurrentlyChecked.remove(attributeID) 498 self.OnColumnChanged(force=0) 499 500 def GetEstPriceEntry(self): 501 return GetFromClass(SingleLineCheckbox, {'line': 1, 502 'label': localization.GetByLabel('UI/Contracts/ContractsWindow/EstPrice'), 503 'checked': settings.user.ui.Get(EST_PRICE_CONFIG, True), 504 'OnChange': self.OnEstPriceSelectedChanged}) 505 506 def OnEstPriceSelectedChanged(self, checkbox, *args): 507 settings.user.ui.Set(EST_PRICE_CONFIG, checkbox.GetValue()) 508 self.OnColumnChanged(force=0) 509 510 def ReloadTypeCompareScroll(self): 511 scrolllist, headers = self.GetCompareTypeInfoContentList() 512 self.leftCont.display = bool(scrolllist) 513 self.typeScroll.Load(contentList=scrolllist, headers=headers, noContentHint=localization.GetByLabel('UI/Compare/CompareToolHint')) 514 515 def GetCompareTypeInfoContentList(self): 516 scrolllist = [] 517 headers, uniqueHeaders, treatedHeaders, initialHeaders = ([], 518 [], 519 [], 520 []) 521 estPriceChecked = settings.user.ui.Get(EST_PRICE_CONFIG, True) 522 estPriceHeaderText = localization.GetByLabel('UI/Contracts/ContractsWindow/EstPrice') if estPriceChecked else '' 523 if self.types: 524 headers = [localization.GetByLabel('/Carbon/UI/Common/TypeName'), localization.GetByLabel('UI/Compare/MetaGroup')] 525 attrDictToUse = self.GetAttributesToOffer() 526 self.activeAttributesChecked.clear() 527 for typeData in self.types: 528 data = KeyVal(typeID=typeData.typeID, itemID=typeData.itemID, godmaAttributes=typeData.godmaAttributes) 529 typeName = evetypes.GetName(typeData.typeID) 530 metaGroupID = evetypes.GetMetaGroupIDOrNone(typeData.typeID) 531 text = '%s<t>%s' % (typeName, metaGroups.get_name(metaGroupID)) 532 data.Set('sort_%s' % headers[0], typeName) 533 data.Set('sort_%s' % headers[1], metaGroupID) 534 if estPriceChecked: 535 estPriceHeader = (estPriceHeaderText, -1) 536 if estPriceHeader not in uniqueHeaders: 537 uniqueHeaders.append(estPriceHeader) 538 estPrice = inventorycommon.typeHelpers.GetAveragePrice(typeData.typeID) 539 if estPrice is not None: 540 formattedIsk = eveFormat.FmtISK(estPrice, showFractionsAlways=1) 541 text += '<t><right>%s' % formattedIsk 542 data.Set('sort_%s' % estPriceHeaderText, estPrice) 543 else: 544 text += '<t>' 545 data.Set('sort_%s' % estPriceHeaderText, None) 546 attributeLoop = {} 547 for each in attrDictToUse: 548 if each.attributeID in self.attributeIDsCurrentlyChecked: 549 self.activeAttributesChecked.add(each.attributeID) 550 attributeLoop[each.attributeID] = each 551 552 for each in self.attributeIDsUserSelectable: 553 attribute = attributeLoop.get(each, None) 554 if not attribute: 555 continue 556 displayNameRaw = dogma_data.get_attribute_display_name(attribute.attributeID) 557 displayName = eveformat.replace_text_ignoring_tags(displayNameRaw, old=' ', new='<br>') 558 if (displayName, attribute.attributeID) not in uniqueHeaders: 559 uniqueHeaders.append((displayName, attribute.attributeID)) 560 if attribute.attributeID == dogma_const.attributeBaseWarpSpeed: 561 value = self.GetWarpValue(typeData) 562 else: 563 value = typeData.GetAttributeValue(attribute.attributeID) 564 data.Set('sort_%s' % displayName, value) 565 if value is None: 566 taa = localization.GetByLabel('UI/Generic/NotAvailableShort') 567 else: 568 taa = GetFormatAndValue(attribute, value) 569 text += '<t>%s' % taa 570 571 data.label = text 572 data.getIcon = 1 573 data.GetMenu = self.GetEntryMenu 574 data.viewMode = 'details' 575 data.ignoreRightClick = 1 576 data.OnDropData = self.OnDropData 577 scrolllist.append(GetFromClass(Item, data)) 578 579 for header, attributeID in uniqueHeaders: 580 if header in headers: 581 header = header + ' ' 582 headers.append(header) 583 584 initialHeaders = headers 585 treatedHeaders = [] 586 for each in initialHeaders: 587 treatedHeaders.append(each.replace(' ', '<br>')) 588 589 return (scrolllist, initialHeaders) 590 591 def GetWarpValue(self, typeData): 592 godma = sm.GetService('godma') 593 cmp = max(godma.GetTypeAttribute(typeData.typeID, dogma_const.attributeBaseWarpSpeed, defaultValue=1), 1.0) 594 cmp *= godma.GetTypeAttribute(typeData.typeID, dogma_const.attributeWarpSpeedMultiplier, defaultValue=1) 595 cmp *= const.AU 596 return cmp 597 598 def GetEntryMenu(self, item): 599 m = GetMenuService().GetMenuFromItemIDTypeID(None, item.typeID, includeMarketDetails=True).filter(['UI/Compare/CompareButton']) 600 item.DoSelectNode() 601 sel = self.typeScroll.GetSelected() 602 text = localization.GetByLabel('UI/Commands/Remove') 603 if len(sel) > 1: 604 text = localization.GetByLabel('UI/Commands/RemoveMultiple', itemcount=len(sel)) 605 m += [(text, self.RemoveEntry, (item,))] 606 return m 607 608 def OnDropData(self, dragObj, nodes): 609 for node in nodes: 610 if getattr(node, '__guid__', None) in allowedGuids: 611 typeID = self._GetNodeTypeID(node) 612 if typeID: 613 if not sm.GetService('info').GetAttributeDictForType(typeID): 614 message_player(localization.GetByLabel('UI/Compare/CannotCompareThisItem', typeID=typeID)) 615 return 616 if not hasattr(node, 'itemID'): 617 node.itemID = None 618 self.AddTypeID(typeID, node.itemID) 619 620 def _GetNodeTypeID(self, node): 621 invType = node.get('invtype') 622 if invType: 623 return invType 624 typeID = node.get('typeID') 625 if typeID: 626 return typeID 627 628 629 class SingleLineCheckbox(CheckboxEntry): 630 631 def Load(self, args): 632 CheckboxEntry.Load(self, args) 633 self.sr.checkbox.left = 4 634 635 636 class AttributeCheckbox(LabelTextTop): 637 __guid__ = 'listentry.AttributeCheckbox' 638 639 def Startup(self, *args): 640 LabelTextTop.Startup(self, args) 641 self.sr.checkbox = Checkbox(parent=self, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, callback=self.CheckBoxChange, pos=(4, 4, 0, 0)) 642 643 def Load(self, args): 644 LabelTextTop.Load(self, args) 645 data = self.sr.node 646 self.sr.checkbox.SetChecked(data.checked, 0) 647 self.sr.checkbox.SetSettingsKey(data.cfgname) 648 self.sr.icon.left = 20 649 if self.sr.icon.display: 650 self.sr.label.left = self.sr.icon.left + self.sr.icon.width + 2 651 self.sr.text.left = self.sr.icon.left + self.sr.icon.width + 2 652 else: 653 self.sr.label.left = 24 654 self.sr.text.left = 24 655 656 def CheckBoxChange(self, *args): 657 self.sr.node.checked = self.sr.checkbox.checked 658 self.sr.node.OnChange(*args) 659 660 def OnClick(self, *args): 661 self.sr.checkbox.OnClick(*args)