userentry.py (41277B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\userentry.py 2 import sys 3 from carbon.common.script.util.commonutils import GetAttrs 4 from carbon.common.script.util.timerstuff import AutoTimer 5 from carbonui import TextColor, uiconst 6 from carbonui.control.scrollentries import SE_BaseClassCore 7 from carbonui.primitives.base import ReverseScaleDpi 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.containerAutoSize import ContainerAutoSize 10 from carbonui.primitives.sprite import Sprite 11 from carbonui.uicore import uicore 12 from eve.client.script.ui.control import eveIcon 13 from eve.client.script.ui.control.eveLabel import EveLabelMedium, EveLabelLarge 14 from eve.client.script.ui.eveColor import SUCCESS_GREEN_HEX 15 from eve.client.script.ui.shared.neocom.addressBook.buddyOnlineIndicator import BuddyOnlineIndicator 16 from eve.client.script.ui.shared.stateFlag import GetStateFlagFromData, AddAndSetFlagIcon, GetFlagFromRelationShip, AddAndSetFlagIconFromData 17 from eve.client.script.ui.station.agents.agentConversationIcon import AgentConversationIcon 18 from eve.client.script.ui.station.agents.agentDialogueUtil import GetAgentNameAndLevel 19 from eve.client.script.ui.station.agents.agentUtil import GetAgentLocationText 20 from eve.client.script.ui.util.uix import GetTextHeight 21 from eve.common.script.sys import idCheckers 22 from eve.common.script.util.eveFormat import FmtISK 23 from eveservices.menu import GetMenuService 24 from eveservices.xmppchat import GetChatService 25 import evetypes 26 from gametime import GetWallclockTimeNow, HOUR, MIN 27 import localization 28 import telemetry 29 import uthread 30 from menu import MenuLabel 31 from npcs.divisions import get_division_name 32 from player_messaging.client.ui_message import prompt_player_fsd_dialog 33 HEIGHT = 40 34 BUDDY_CONTAINER_PAD_LEFT = 4 35 STATUS_ICON_SIZE = 12 36 STATUS_ICON_PAD_LEFT = 2 37 38 class User(SE_BaseClassCore): 39 __guid__ = 'listentry.User' 40 __params__ = ['charID'] 41 __notifyevents__ = ['OnContactLoggedOn', 42 'OnContactLoggedOff', 43 'OnClientContactChange', 44 'OnPortraitCreated', 45 'OnContactNoLongerContact', 46 'OnStateSetupChange', 47 'OnMyFleetInited', 48 'OnFleetJoin_Local', 49 'OnFleetLeave_Local', 50 'ProcessOnUIAllianceRelationshipChanged', 51 'OnContactChange', 52 'OnBlockContacts', 53 'OnUnblockContacts', 54 'OnCrimewatchEngagementUpdated', 55 'OnSuspectsAndCriminalsUpdate', 56 'OnDisapprovalUpdate'] 57 isDragObject = True 58 charid = None 59 selected = 0 60 big = 0 61 id = None 62 groupID = None 63 picloaded = 0 64 fleetCandidate = 0 65 label = None 66 slimuser = False 67 68 def Startup(self, *args): 69 self._CreatePicture() 70 self._CreateName() 71 self.sr.voiceIcon = None 72 self.sr.eveGateIcon = None 73 self.contactLabel = None 74 self.rightCont = ContainerAutoSize(parent=self, align=uiconst.CENTERRIGHT, height=16, left=4) 75 self.flagCont = None 76 self._CreateOnlineStatusIcon() 77 self._CreateStandingLabel() 78 self._CreateCorpApplicationLabel() 79 sm.RegisterNotify(self) 80 81 def _CreatePicture(self): 82 self.sr.picture = Container(parent=self, name='picture', state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, pos=(2, 0, 32, 32)) 83 self.sr.extraIconCont = Container(name='extraIconCont', parent=self, idx=0, pos=(0, 0, 16, 16), align=uiconst.BOTTOMLEFT, state=uiconst.UI_HIDDEN) 84 85 @telemetry.ZONE_METHOD 86 def _CreateName(self): 87 self.sr.namelabel = EveLabelLarge(name='nameLabel', parent=self, align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, idx=0) 88 89 def _CreateContactLabels(self): 90 self.contactLabel = EveLabelMedium(text='', name='contactLabels', parent=self, state=uiconst.UI_DISABLED, idx=0, align=uiconst.BOTTOMLEFT, left=40, top=4, color=TextColor.SECONDARY) 91 92 @telemetry.ZONE_METHOD 93 def _CreateStandingLabel(self): 94 self.sr.standingLabel = EveLabelMedium(text='', name='standingLabel', parent=self.rightCont, state=uiconst.UI_DISABLED, align=uiconst.TORIGHT) 95 96 def _CreateOnlineStatusIcon(self): 97 self.onlineStatusIcon = BuddyOnlineIndicator(parent=self.rightCont, align=uiconst.TORIGHT, width=16) 98 99 @telemetry.ZONE_METHOD 100 def _CreateCorpApplicationLabel(self): 101 self.sr.corpApplicationLabel = EveLabelMedium(text='corpApplicationLabel', name='corpApplicationLabel', parent=self, state=uiconst.UI_DISABLED, idx=0, align=uiconst.CENTERRIGHT) 102 self.sr.corpApplicationLabel.left = 16 103 104 def PreLoad(node): 105 data = node 106 charinfo = data.Get('info', None) or cfg.eveowners.Get(data.charID) 107 data.info = charinfo 108 if data.GetLabel: 109 data.label = data.GetLabel(data) 110 elif not data.Get('label', None): 111 label = charinfo.name 112 if data.bounty: 113 label += '<br>' 114 label += localization.GetByLabel('UI/Common/BountyAmount', bountyAmount=FmtISK(data.bounty.bounty, 0)) 115 elif data.killTime: 116 label += '<br>' + localization.GetByLabel('UI/PeopleAndPlaces/ExpiresTime', expires=data.killTime) 117 data.label = label 118 groupID = evetypes.GetGroupID(data.info.typeID) 119 data.invtype = data.info.typeID 120 data.IsCharacter = groupID == const.groupCharacter 121 data.IsCorporation = groupID == const.groupCorporation 122 data.IsFaction = groupID == const.groupFaction 123 data.IsAlliance = groupID == const.groupAlliance 124 if data.IsCorporation and not idCheckers.IsNPC(data.charID): 125 logoData = cfg.corptickernames.Get(data.charID) 126 127 def Load(self, node): 128 self.sr.node = node 129 data = node 130 self.name = data.info.name 131 self.sr.namelabel.text = data.label 132 self.charid = self.id = data.itemID = data.charID 133 self.picloaded = 0 134 self.sr.parwnd = data.Get('dad', None) 135 self.fleetCandidate = data.Get('fleetster', 1) and not data.info.IsNPC() 136 self.confirmOnDblClick = data.Get('dblconfirm', 1) 137 self.leaveDadAlone = data.Get('leavedad', 0) 138 self.slimuser = data.Get('slimuser', False) 139 self.data = {'Name': self.name, 140 'charid': data.charID} 141 self.inWatchlist = sm.GetService('addressbook').IsInWatchlist(data.charID) 142 self.isContactList = data.Get('contactType', None) 143 self.applicationDate = data.Get('applicationDate', None) 144 self.contactLevel = None 145 if self.isContactList: 146 self.contactLevel = data.contactLevel 147 self.SetLabelText() 148 self.isCorpOrAllianceContact = data.contactType and data.contactType != 'contact' 149 data.listvalue = [data.info.name, data.charID] 150 level = self.sr.node.Get('sublevel', 0) 151 subLevelOffset = 16 152 self.sr.picture.left = 2 + max(0, subLevelOffset * level) 153 self.LoadPortrait() 154 if data.IsCharacter: 155 uthread.new(self.SetRelationship, data) 156 self.onlineStatusIcon.Hide() 157 if data.charID != session.charid: 158 if not idCheckers.IsNPC(data.charID) and not self.isCorpOrAllianceContact and self.inWatchlist: 159 try: 160 self.SetOnline(sm.GetService('onlineStatus').GetOnlineStatus(data.charID, fetch=False)) 161 except IndexError: 162 sys.exc_clear() 163 164 else: 165 self.onlineStatusIcon.Hide() 166 if data.charID != session.charid: 167 uthread.new(self.SetRelationship, data) 168 self.sr.namelabel.left = 40 + max(0, subLevelOffset * level) 169 if self.sr.node.Get('selected', 0): 170 self.Select() 171 else: 172 self.Deselect() 173 if not self.isCorpOrAllianceContact: 174 self.contactLevel = sm.GetService('addressbook').GetStandingsLevel(self.charid, 'contact') 175 self.SetBlocked(1) 176 else: 177 self.SetBlocked(0) 178 if self.isCorpOrAllianceContact: 179 self.SetStandingText(self.contactLevel) 180 if self.applicationDate: 181 self.sr.corpApplicationLabel.SetText(localization.GetByLabel('UI/Corporations/Applied', applydate=self.applicationDate)) 182 self.sr.corpApplicationLabel.Show() 183 data.Set('sort_' + localization.GetByLabel('UI/Common/Date'), self.applicationDate) 184 data.Set('sort_' + localization.GetByLabel('UI/Common/Name'), data.info.name) 185 else: 186 self.sr.corpApplicationLabel.SetText('') 187 self.sr.corpApplicationLabel.Hide() 188 189 def GetValue(self): 190 return [self.name, self.id] 191 192 def GetDynamicHeight(node, width): 193 if '<br>' in node.label: 194 node.height = max(HEIGHT, GetTextHeight(node.label, linespace=11)) 195 else: 196 node.height = HEIGHT 197 return node.height 198 199 def OnContactLoggedOn(self, charID): 200 if self and not self.destroyed and charID == self.charid and charID != session.charid and not idCheckers.IsNPC(charID): 201 self.SetOnline(1) 202 203 def OnContactLoggedOff(self, charID): 204 if self and not self.destroyed and charID == self.charid and charID != session.charid and not idCheckers.IsNPC(charID): 205 self.SetOnline(0) 206 207 def OnClientContactChange(self, charID, online): 208 if online: 209 self.OnContactLoggedOn(charID) 210 else: 211 self.OnContactLoggedOff(charID) 212 213 def OnContactNoLongerContact(self, charID): 214 if self and not self.destroyed and charID == self.charid and charID != session.charid: 215 self.SetOnline(None) 216 217 def OnPortraitCreated(self, charID, _size): 218 if self.destroyed: 219 return 220 if self.sr.node and charID == self.sr.node.charID and not self.picloaded: 221 self.LoadPortrait(orderIfMissing=False) 222 223 def OnContactChange(self, contactIDs, contactType = None): 224 if self.destroyed: 225 return 226 self.SetRelationship(self.sr.node) 227 if self.charid in contactIDs: 228 if sm.GetService('addressbook').IsInAddressBook(self.charid, contactType): 229 if not self.isContactList: 230 self.isContactList = contactType 231 else: 232 self.isContactList = None 233 self.inWatchlist = sm.GetService('addressbook').IsInWatchlist(self.charid) 234 if not self.inWatchlist: 235 isBlocked = sm.GetService('addressbook').IsBlocked(self.charid) 236 if isBlocked: 237 self.onlineStatusIcon.SetBlocked() 238 else: 239 self.onlineStatusIcon.Hide() 240 241 def OnBlockContacts(self, contactIDs): 242 if not self or self.destroyed: 243 return 244 if self.charid in contactIDs: 245 self.SetBlocked(1) 246 self.UpdateComponentSizes() 247 248 def OnUnblockContacts(self, contactIDs): 249 if not self or self.destroyed: 250 return 251 if self.charid in contactIDs: 252 self.SetBlocked(0) 253 self.UpdateComponentSizes() 254 255 def OnStateSetupChange(self, what): 256 if self.destroyed: 257 return 258 self.SetRelationship(self.sr.node) 259 260 def ProcessOnUIAllianceRelationshipChanged(self, *args): 261 if self.destroyed: 262 return 263 self.SetRelationship(self.sr.node) 264 265 def OnFleetJoin_Local(self, memberInfo, state = 'Active'): 266 if self.destroyed: 267 return 268 myID = GetAttrs(self, 'sr', 'node', 'charID') 269 charID = memberInfo.charID 270 if myID is not None and charID == myID: 271 uthread.new(self.SetRelationship, self.sr.node) 272 273 def OnFleetLeave_Local(self, memberInfo): 274 if self.destroyed: 275 return 276 myID = GetAttrs(self, 'sr', 'node', 'charID') 277 charID = memberInfo.charID 278 if myID is not None and charID == myID or charID == session.charid: 279 uthread.new(self.SetRelationship, self.sr.node) 280 281 def OnMyFleetInited(self): 282 if self.destroyed: 283 return 284 uthread.new(self.SetRelationship, self.sr.node) 285 286 def SetOnline(self, online): 287 if self.destroyed: 288 return 289 if self.slimuser: 290 return 291 if online is None or not self.inWatchlist or self.isCorpOrAllianceContact: 292 self.onlineStatusIcon.Hide() 293 elif online: 294 self.onlineStatusIcon.SetOnline() 295 else: 296 self.onlineStatusIcon.SetOffline() 297 298 def SetBlocked(self, blocked): 299 isBlocked = sm.GetService('addressbook').IsBlocked(self.charid) 300 if blocked and isBlocked and not self.isCorpOrAllianceContact: 301 self.onlineStatusIcon.SetBlocked() 302 elif self.inWatchlist: 303 self.onlineStatusIcon.SetNotBlocked() 304 else: 305 self.onlineStatusIcon.Hide() 306 307 @telemetry.ZONE_METHOD 308 def SetLabelText(self): 309 labelMask = sm.GetService('addressbook').GetLabelMask(self.charid) 310 self.sr.node.labelMask = labelMask 311 labeltext = sm.GetService('addressbook').GetLabelText(labelMask, self.isContactList) 312 if labeltext: 313 self.SetContactLabelText(labeltext) 314 315 def SetContactLabelText(self, labeltext): 316 if not self.contactLabel: 317 self._CreateContactLabels() 318 self.sr.namelabel.SetAlign(uiconst.TOPLEFT) 319 self.sr.namelabel.top = 3 320 self.contactLabel.text = labeltext 321 322 def SetStandingText(self, standing): 323 self.sr.standingLabel.text = standing 324 325 def SetRelationship(self, data, debugFlag = None): 326 if self.destroyed: 327 return 328 if self.slimuser: 329 return 330 if not data: 331 return 332 flag = None 333 if data.Get('contactType', None): 334 if self.contactLevel is None: 335 return 336 flag = GetFlagFromRelationShip(self.contactLevel) 337 else: 338 flag = GetStateFlagFromData(data) 339 if flag: 340 self._ConstructFlagCont(flag) 341 342 def _ConstructFlagCont(self, flag): 343 if self.flagCont is None: 344 self.flagCont = Container(name='flagCont', parent=self.rightCont, pos=(0, 0, 16, 16), align=uiconst.TORIGHT, idx=0) 345 AddAndSetFlagIcon(self.flagCont, flag=flag, top=0, left=0, width=12, height=12, align=uiconst.CENTER) 346 347 def LoadPortrait(self, orderIfMissing = True): 348 self.sr.picture.Flush() 349 if self.sr.node is None: 350 return 351 if eveIcon.GetOwnerLogo(self.sr.picture, self.id, size=32, callback=True, orderIfMissing=orderIfMissing): 352 self.picloaded = 1 353 354 def RemoveFromListGroup(self, listGroupIDs, charIDs, listname): 355 if self.destroyed: 356 return 357 if listGroupIDs: 358 for listGroupID, charID in listGroupIDs: 359 uicore.registry.RemoveFromListGroup(listGroupID, charID) 360 361 sm.GetService('addressbook').RefreshWindow() 362 if charIDs and listname: 363 name = [localization.GetByLabel('UI/AddressBook/RemoveAddressBook1'), cfg.eveowners.Get(charIDs[0]).name][len(charIDs) == 1] 364 if prompt_player_fsd_dialog('WarnDeleteFromAddressbook', {'name': name, 365 'type': listname}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 366 return 367 sm.GetService('addressbook').DeleteEntryMulti(charIDs, None) 368 369 def GetMenu(self): 370 if self.destroyed: 371 return 372 m = [] 373 selected = self.sr.node.scroll.GetSelectedNodes(self.sr.node) 374 multi = len(selected) > 1 375 if multi: 376 return self._GetMultiMenu(selected) 377 channelID = self.sr.node.Get('channelID', None) 378 m = GetMenuService().GetMenuFromItemIDTypeID(self.id, self.sr.node.invtype, channelID=channelID) 379 if self.sr.node.Get('GetMenu', None) is not None: 380 m += self.sr.node.GetMenu(self.sr.node) 381 listGroupID = self.sr.node.Get('listGroupID', None) 382 if listGroupID is not None: 383 group = uicore.registry.GetListGroup(listGroupID) 384 if group: 385 if listGroupID not in [('buddygroups', 'all'), ('buddygroups', 'allcorps')]: 386 m.append(None) 387 m.append((MenuLabel('UI/Common/RemoveFromGroup', {'groupname': group['label']}), self.RemoveFromListGroup, ([(listGroupID, self.charid)], [], ''))) 388 if self.sr.node.Get('MenuFunction', None): 389 cm = [None] 390 cm += self.sr.node.MenuFunction([self.sr.node]) 391 m += cm 392 if self.isContactList is not None: 393 if sm.GetService('addressbook').ShowLabelMenuAndManageBtn(self.isContactList): 394 m.append(None) 395 assignLabelMenu = sm.StartService('addressbook').GetAssignLabelMenu(selected, [self.charid], self.isContactList) 396 if len(assignLabelMenu) > 0: 397 m.append((MenuLabel('UI/Mail/AssignLabel'), assignLabelMenu)) 398 removeLabelMenu = sm.StartService('addressbook').GetRemoveLabelMenu(selected, [self.charid], self.isContactList) 399 if len(removeLabelMenu) > 0: 400 m.append((MenuLabel('UI/Mail/LabelRemove'), removeLabelMenu)) 401 return m 402 403 def _GetMultiMenu(self, selected): 404 m = [] 405 charIDs = [] 406 multiCharIDs = [] 407 multiEveCharIDs = [] 408 listGroupIDs = {} 409 listGroupID_charIDs = [] 410 onlyCharacters = True 411 for entry in selected: 412 listGroupID = entry.listGroupID 413 if listGroupID: 414 listGroupIDs[listGroupID] = 0 415 listGroupID_charIDs.append((listGroupID, entry.charID)) 416 if entry.charID: 417 charIDs.append(entry.charID) 418 multiCharIDs.append(entry.charID) 419 if not idCheckers.IsCharacter(entry.charID): 420 onlyCharacters = False 421 422 if self.isContactList is None: 423 if onlyCharacters: 424 m += GetMenuService().CharacterMenu(charIDs) 425 if listGroupIDs: 426 listname = '' 427 delCharIDs = [] 428 rem = [] 429 for listGroupID, charID in listGroupID_charIDs: 430 if listGroupID in [('buddygroups', 'all'), ('buddygroups', 'allcorps')]: 431 if onlyCharacters: 432 return m 433 uicore.registry.GetListGroup(listGroupID) 434 listname = [localization.GetByLabel('UI/Generic/BuddyList')][listGroupID == ('buddygroups', 'all')] 435 delCharIDs.append(charID) 436 rem.append((listGroupID, charID)) 437 438 for each in rem: 439 listGroupID_charIDs.remove(each) 440 441 foldername = 'folders' 442 if len(listGroupIDs) == 1: 443 group = uicore.registry.GetListGroup(listGroupIDs.keys()[0]) 444 if group: 445 foldername = group['label'] 446 label = '' 447 if delCharIDs and listname: 448 label = localization.GetByLabel('UI/PeopleAndPlaces/RemoveMultipleFromAddressbook', removecount=len(delCharIDs)) 449 if listGroupID_charIDs: 450 label += [', '] 451 if listGroupID_charIDs: 452 label += localization.GetByLabel('UI/PeopleAndPlaces/RemoveFromFolder', foldername=foldername, removecount=len(listGroupID_charIDs)) 453 m.append((label, self.RemoveFromListGroup, (listGroupID_charIDs, delCharIDs, listname))) 454 else: 455 addressBookSvc = sm.GetService('addressbook') 456 counter = len(selected) 457 blocked = 0 458 if self.isContactList == 'contact': 459 editLabel = localization.GetByLabel('UI/PeopleAndPlaces/EditContacts', contactcount=counter) 460 m.append((editLabel, addressBookSvc.EditContacts, [multiCharIDs, 'contact'])) 461 deleteLabel = localization.GetByLabel('UI/PeopleAndPlaces/RemoveContacts', contactcount=counter) 462 m.append((deleteLabel, addressBookSvc.DeleteEntryMulti, [multiCharIDs, 'contact'])) 463 for charid in multiCharIDs: 464 if sm.GetService('addressbook').IsBlocked(charid): 465 blocked += 1 466 467 if blocked == counter: 468 unblockLabel = localization.GetByLabel('UI/PeopleAndPlaces/UnblockContacts', contactcount=blocked) 469 m.append((unblockLabel, addressBookSvc.UnblockOwner, [multiCharIDs])) 470 elif self.isContactList == 'corpcontact': 471 editLabel = localization.GetByLabel('UI/PeopleAndPlaces/EditCorpContacts', contactcount=counter) 472 m.append((editLabel, addressBookSvc.EditContacts, [multiCharIDs, 'corpcontact'])) 473 deleteLabel = localization.GetByLabel('UI/PeopleAndPlaces/RemoveCorpContacts', contactcount=counter) 474 m.append((deleteLabel, addressBookSvc.DeleteEntryMulti, [multiCharIDs, 'corpcontact'])) 475 elif self.isContactList == 'alliancecontact': 476 editLabel = localization.GetByLabel('UI/PeopleAndPlaces/EditAllianceContacts', contactcount=counter) 477 m.append((editLabel, addressBookSvc.EditContacts, [multiCharIDs, 'alliancecontact'])) 478 deleteLabel = localization.GetByLabel('UI/PeopleAndPlaces/RemoveAllianceContacts', contactcount=counter) 479 m.append((deleteLabel, addressBookSvc.DeleteEntryMulti, [multiCharIDs, 'alliancecontact'])) 480 m.append(None) 481 assignLabelMenu = sm.StartService('addressbook').GetAssignLabelMenu(selected, multiCharIDs, self.isContactList) 482 if len(assignLabelMenu) > 0: 483 m.append((MenuLabel('UI/PeopleAndPlaces/AddContactLabel'), assignLabelMenu)) 484 removeLabelMenu = sm.StartService('addressbook').GetRemoveLabelMenu(selected, multiCharIDs, self.isContactList) 485 if len(removeLabelMenu) > 0: 486 m.append((MenuLabel('UI/PeopleAndPlaces/RemoveContactLabel'), removeLabelMenu)) 487 m.append(None) 488 m.append((MenuLabel('UI/Commands/CapturePortrait'), sm.StartService('photo').SavePortraits, [multiEveCharIDs])) 489 if self.sr.node.Get('MenuFunction', None): 490 cm = [None] 491 cm += self.sr.node.MenuFunction(selected) 492 m += cm 493 return m 494 495 def ShowInfo(self, *args): 496 if self.destroyed: 497 return 498 sm.GetService('info').ShowInfo(cfg.eveowners.Get(self.charid).typeID, self.charid) 499 500 def OnClick(self, *args): 501 if self.destroyed: 502 return 503 prompt_player_fsd_dialog('ListEntryClick') 504 self.sr.node.scroll.SelectNode(self.sr.node) 505 if self.sr.node.Get('OnClick', None): 506 self.sr.node.OnClick(self) 507 508 def OnDblClick(self, *args): 509 if self.destroyed: 510 return 511 if self.sr.node.Get('OnDblClick', None): 512 self.sr.node.OnDblClick(self) 513 return 514 if self.sr.parwnd and hasattr(self.sr.parwnd, 'Select') and self.confirmOnDblClick: 515 self.sr.parwnd.Select(self) 516 self.sr.parwnd.Confirm() 517 return 518 if not self.leaveDadAlone and self.sr.parwnd and uicore.registry.GetModalWindow() == self.sr.parwnd: 519 self.sr.parwnd.SetModalResult(uiconst.ID_OK) 520 return 521 onDblClick = settings.user.ui.Get('dblClickUser', 0) 522 if onDblClick == 0: 523 sm.GetService('info').ShowInfo(cfg.eveowners.Get(self.charid).typeID, self.charid) 524 elif onDblClick == 1: 525 GetChatService().Invite(self.charid) 526 527 def GetDragData(self, *args): 528 if self and not self.destroyed and not self.slimuser: 529 return self.sr.node.scroll.GetSelectedNodes(self.sr.node) 530 else: 531 return [] 532 533 @classmethod 534 def GetCopyData(cls, node): 535 return node.label 536 537 def OnSuspectsAndCriminalsUpdate(self, criminalizedCharIDs, decriminalizedCharIDs): 538 return self._UpdateOnSuspectCriminalAndDisapprovalChanges(criminalizedCharIDs, decriminalizedCharIDs) 539 540 def OnDisapprovalUpdate(self, newCharIDs, removedCharIDs): 541 return self._UpdateOnSuspectCriminalAndDisapprovalChanges(newCharIDs, removedCharIDs) 542 543 def _UpdateOnSuspectCriminalAndDisapprovalChanges(self, newCharIDs, removedCharIDs): 544 if self.destroyed: 545 return 546 charID = GetAttrs(self, 'sr', 'node', 'charID') 547 if charID is not None and (charID in newCharIDs or charID in removedCharIDs): 548 uthread.new(self.SetRelationship, self.sr.node) 549 550 def OnCrimewatchEngagementUpdated(self, otherCharId, timeout): 551 if self.destroyed: 552 return 553 charID = GetAttrs(self, 'sr', 'node', 'charID') 554 if charID is not None and charID == otherCharId: 555 uthread.new(self.SetRelationship, self.sr.node) 556 557 def OnDropData(self, dragObj, nodes): 558 nonCharNodes = [] 559 for eachNode in nodes: 560 itemID = getattr(eachNode, 'itemID', None) 561 if idCheckers.IsCharacter(itemID): 562 continue 563 nonCharNodes.append(eachNode) 564 565 if not nonCharNodes or not self.charid or not idCheckers.IsCharacter(self.charid): 566 return 567 from eve.client.script.ui.station.pvptrade.tradeUtil import TryInitiateTrade 568 TryInitiateTrade(self.charid, nonCharNodes) 569 570 def _IsDisplayed(self, container): 571 return container is not None and not container.destroyed and container.display 572 573 def _OnResize(self, *args): 574 super(User, self)._OnResize(args) 575 self.UpdateComponentSizes() 576 577 def UpdateComponentSizes(self): 578 occupiedWidth = BUDDY_CONTAINER_PAD_LEFT 579 if self._IsDisplayed(self.onlineStatusIcon): 580 occupiedWidth += STATUS_ICON_SIZE + STATUS_ICON_PAD_LEFT 581 if self._IsDisplayed(self.flagCont): 582 occupiedWidth += self.flagCont.width + 1 583 spaceAvailableForNameLabel = self.width - self.sr.namelabel.left - occupiedWidth 584 self.sr.namelabel.SetRightAlphaFade(fadeEnd=spaceAvailableForNameLabel, maxFadeWidth=3) 585 586 def LoadTooltipPanel(self, panel, *args): 587 char_id = GetAttrs(self, 'sr', 'node', 'charID') 588 if char_id is None: 589 return 590 from character.client.identifier import CharacterIdentifier 591 from cosmetics.client.character.title.api.repository import get_repository 592 equipped_state = get_repository().get_equipped_title(CharacterIdentifier(char_id)) 593 if equipped_state is None or equipped_state.equipped_title is None: 594 return 595 from achievement_system.client.ui.chip.character_title import CharacterTitleChip 596 title_chip = CharacterTitleChip(name='character_title_chip', character_id=char_id) 597 panel.LoadStandardSpacing() 598 panel.AddCell(title_chip, cellPadding=(-4, -4, -4, -4)) 599 600 601 class UserSimple(User): 602 __guid__ = 'listentry.UserSimple' 603 ENTRYHEIGHT = 18 604 605 def Startup(self, *args): 606 User.Startup(self, *args) 607 self.iconCont = Container(parent=self, align=uiconst.TOLEFT, width=16) 608 609 def Load(self, node, *args): 610 User.Load(self, node, *args) 611 self.sr.namelabel.left = 16 612 self.sr.label = self.sr.namelabel 613 self.sr.label.maxLines = 1 614 615 def SetRelationship(self, data, *args, **kwargs): 616 if self.destroyed: 617 return 618 if not data: 619 return 620 AddAndSetFlagIconFromData(parentCont=self.iconCont, data=data, top=4, left=4) 621 622 def LoadPortrait(self, orderIfMissing = True): 623 pass 624 625 def GetDynamicHeight(node, width): 626 node.height = UserSimple.ENTRYHEIGHT 627 return node.height 628 629 630 class AgentEntry(SE_BaseClassCore): 631 __guid__ = 'listentry.AgentEntry' 632 default_name = 'AgentEntry' 633 isDragObject = True 634 635 def Startup(self, *args): 636 self.divisionName = '' 637 self.agentName = '' 638 self.levelName = '' 639 self.agentType = '' 640 self.agentLocation = '' 641 self.missionState = '' 642 self.locationLabel = None 643 self.agentChatBtn = None 644 self.timer = None 645 self._timerUpdatesThread = None 646 picCont = Container(parent=self, pos=(1, 0, 50, 0), name='pictureContainer', state=uiconst.UI_PICKCHILDREN, align=uiconst.TOLEFT) 647 self.sr.pic = Sprite(parent=picCont, name='picture', align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN) 648 textCont = Container(parent=self, name='textCont', state=uiconst.UI_PICKCHILDREN, align=uiconst.TOALL, padLeft=6, padTop=2, padRight=6) 649 self.textCont = Container(parent=textCont, name='text', state=uiconst.UI_PICKCHILDREN, align=uiconst.TOALL, clipChildren=True, padTop=2) 650 self.sr.namelabel = EveLabelMedium(name='nameLabel', text='', parent=self.textCont) 651 self.sr.timerLabel = EveLabelMedium(name='timerLabel', text='', align=uiconst.TOPLEFT, parent=self.textCont, top=14) 652 self.sr.levelLabel = EveLabelMedium(name='levelLabel', text='', align=uiconst.TOPLEFT, parent=self.textCont, top=14) 653 self.sr.missionLabel = EveLabelMedium(name='missionLabel', text='', parent=self.textCont, align=uiconst.TOPRIGHT) 654 self.agentChatBtn = AgentConversationIcon(name='agentChatBtn', parent=self, align=uiconst.BOTTOMRIGHT, left=0, top=0) 655 buttonIconOnMouseEnter = self.agentChatBtn.OnMouseEnter 656 self.agentChatBtn.OnMouseEnter = (self.OnChatButtonMouseEnter, self.agentChatBtn, buttonIconOnMouseEnter) 657 658 def PreLoad(node): 659 data = node 660 charinfo = data.Get('info', None) or cfg.eveowners.Get(data.charID) 661 data.info = charinfo 662 data.itemID = data.charID 663 data.invtype = data.info.typeID 664 665 def GetAgentInfo(self, data): 666 charID = data.charID 667 self.UpdateMissionStateText(charID) 668 agentInfo = sm.GetService('agents').GetAgentByID(charID) 669 self.agentName = GetAgentNameAndLevel(charID, agentInfo.level) 670 if agentInfo: 671 self.agentChatBtn.SetAgentID(charID) 672 agentDivision = get_division_name(agentInfo.divisionID).replace('&', '&') 673 if charID in const.rookieAgentList: 674 self.agentType = localization.GetByLabel('UI/AgentFinder/TutorialAgentDivision', divisionName=agentDivision) 675 elif agentInfo.agentTypeID == const.agentTypeEpicArcAgent: 676 self.agentType = localization.GetByLabel('UI/AgentFinder/EpicArcAgentDivision', divisionName=agentDivision) 677 elif agentInfo.agentTypeID in (const.agentTypeGenericStorylineMissionAgent, const.agentTypeStorylineMissionAgent): 678 self.agentType = localization.GetByLabel('UI/AgentFinder/StorylineAgentDivision', divisionName=agentDivision) 679 elif agentInfo.agentTypeID == const.agentTypeEventMissionAgent: 680 self.agentType = localization.GetByLabel('UI/AgentFinder/EventAgentDivision', divisionName=agentDivision) 681 elif agentInfo.agentTypeID == const.agentTypeCareerAgent: 682 self.agentType = localization.GetByLabel('UI/AgentFinder/CareerAgentDivision', divisionName=agentDivision) 683 elif agentInfo.agentTypeID == const.agentTypeHeraldry: 684 self.agentType = localization.GetByLabel('UI/AgentFinder/HeraldryAgent') 685 elif agentInfo.agentTypeID == const.agentTypeAura: 686 self.agentType = '' 687 else: 688 self.agentType = agentDivision 689 if agentInfo.stationID and session.stationid != agentInfo.stationID: 690 agentInfo = sm.GetService('agents').GetAgentByID(data.charID) 691 solarSystemID = sm.GetService('contracts').GetSolarSystemIDForStationOrStructure(agentInfo.stationID) 692 pathfinder = sm.GetService('clientPathfinderService') 693 numJumps = pathfinder.GetAutopilotJumpCount(session.solarsystemid2, solarSystemID) 694 self.agentLocation = GetAgentLocationText(solarSystemID) 695 else: 696 self.agentChatBtn.display = False 697 698 def UpdateMissionStateText(self, charID): 699 activeMission = sm.GetService('journal').GetActiveMissionForAgent(charID) 700 if activeMission: 701 self.missionState = activeMission.GetMissionStateTextColored() 702 703 def Load(self, node): 704 self.sr.node = node 705 data = node 706 if self.sr.node.Get('selected', 0): 707 self.Select() 708 else: 709 self.Deselect() 710 self.timer = getattr(data, 'timer', None) 711 self.GetAgentInfo(data) 712 extraTop = 0 713 if self.agentLocation != '': 714 if not self.locationLabel: 715 self.locationLabel = EveLabelMedium(name='locationLabel', parent=self.textCont, text=self.agentLocation, top=14) 716 extraTop = 14 717 self.name = data.info.name 718 self.sr.namelabel.text = self.agentName 719 self.sr.missionLabel.text = self.missionState 720 if self.timer: 721 extraTop += 14 722 self._StartTimerUpdates() 723 self.sr.timerLabel.top = extraTop 724 else: 725 self._StopTimerUpdates() 726 self.sr.timerLabel.top = extraTop 727 extraTop += 14 728 if self.levelName == '': 729 levelText = self.agentType 730 else: 731 levelText = self.levelName 732 self.sr.levelLabel.text = levelText 733 self.sr.levelLabel.top = extraTop 734 self.charID = data.charID 735 sm.GetService('photo').GetPortrait(self.charID, 64, self.sr.pic) 736 737 def _StartTimerUpdates(self): 738 self._UpdateTimer() 739 if not self._timerUpdatesThread: 740 self._timerUpdatesThread = AutoTimer(interval=500, method=self._UpdateTimer) 741 742 def _GetTimerText(self, timeLeft): 743 if timeLeft >= 12 * HOUR: 744 showTo = 'hour' 745 elif timeLeft >= HOUR: 746 showTo = 'minute' 747 elif timeLeft >= 10 * MIN: 748 showTo = 'minute' 749 else: 750 showTo = 'second' 751 formatter = localization.formatters.FormatTimeIntervalShortWritten 752 formattedTime = formatter(timeLeft, showFrom='hour', showTo=showTo) 753 text = localization.GetByLabel('UI/Agents/AgentEntry/Timer', timeLeft=formattedTime, color=SUCCESS_GREEN_HEX) 754 return text 755 756 def _UpdateTimer(self): 757 if self.destroyed or not self.sr.timerLabel or not self.timer: 758 self._StopTimerUpdates() 759 return 760 now = GetWallclockTimeNow() 761 timeLeft = max(self.timer - now, 0) 762 text = self._GetTimerText(timeLeft) 763 self.sr.timerLabel.SetText(text) 764 if timeLeft == 0: 765 self._StopTimerUpdates() 766 767 def _StopTimerUpdates(self): 768 if self._timerUpdatesThread: 769 self._timerUpdatesThread.KillTimer() 770 if not self.destroyed and self.sr.timerLabel: 771 self.sr.timerLabel.text = '' 772 self.sr.levelLabel.top = self.sr.timerLabel.top 773 774 def GetMenu(self): 775 if self.destroyed: 776 return 777 m = [] 778 selected = self.sr.node.scroll.GetSelectedNodes(self.sr.node) 779 multi = len(selected) > 1 780 if multi: 781 return self._GetMultiMenu(selected) 782 m = GetMenuService().GetMenuFromItemIDTypeID(self.charID, self.sr.node.invtype) 783 if self.sr.node.Get('GetMenu', None) is not None: 784 m += self.sr.node.GetMenu(self.sr.node) 785 listGroupID = self.sr.node.Get('listGroupID', None) 786 if listGroupID is not None: 787 group = uicore.registry.GetListGroup(listGroupID) 788 if group: 789 if not listGroupID == ('agentgroups', 'all'): 790 m.append(None) 791 m.append((MenuLabel('UI/Common/RemoveFromGroup', {'groupname': group['label']}), self.RemoveFromListGroup, ([(listGroupID, self.charID)], [], ''))) 792 if self.sr.node.Get('MenuFunction', None): 793 cm = [None] 794 cm += self.sr.node.MenuFunction([self.sr.node]) 795 m += cm 796 return m 797 798 def _GetMultiMenu(self, selected): 799 m = [] 800 charIDs = [] 801 multiCharIDs = [] 802 listGroupIDs = {} 803 listGroupID_charIDs = [] 804 onlyCharacters = True 805 for entry in selected: 806 listGroupID = entry.listGroupID 807 if listGroupID: 808 listGroupIDs[listGroupID] = 0 809 listGroupID_charIDs.append((listGroupID, entry.charID)) 810 if entry.charID: 811 charIDs.append(entry.charID) 812 multiCharIDs.append(entry.charID) 813 if not idCheckers.IsCharacter(entry.charID): 814 onlyCharacters = False 815 816 if onlyCharacters: 817 m += GetMenuService().CharacterMenu(charIDs) 818 if listGroupIDs: 819 listname = '' 820 delCharIDs = [] 821 rem = [] 822 for listGroupID, charID in listGroupID_charIDs: 823 if listGroupID == ('agentgroups', 'all'): 824 if onlyCharacters: 825 return m 826 group = uicore.registry.GetListGroup(listGroupID) 827 listname = [localization.GetByLabel('UI/Agents/AgentList'), localization.GetByLabel('UI/Generic/BuddyList')][listGroupID == ('buddygroups', 'all')] 828 delCharIDs.append(charID) 829 rem.append((listGroupID, charID)) 830 831 for each in rem: 832 listGroupID_charIDs.remove(each) 833 834 foldername = 'folders' 835 if len(listGroupIDs) == 1: 836 group = uicore.registry.GetListGroup(listGroupIDs.keys()[0]) 837 if group: 838 foldername = group['label'] 839 label = '' 840 if delCharIDs and listname: 841 label = localization.GetByLabel('UI/PeopleAndPlaces/RemoveMultipleFromAddressbook', removecount=len(delCharIDs)) 842 if listGroupID_charIDs: 843 label += [', '] 844 if listGroupID_charIDs: 845 label += localization.GetByLabel('UI/PeopleAndPlaces/RemoveFromFolder', foldername=foldername, removecount=len(listGroupID_charIDs)) 846 m.append((label, self.RemoveFromListGroup, (listGroupID_charIDs, delCharIDs, listname))) 847 if self.sr.node.Get('MenuFunction', None): 848 cm = [None] 849 cm += self.sr.node.MenuFunction(selected) 850 m += cm 851 return m 852 853 def ShowInfo(self, *args): 854 if self.destroyed: 855 return 856 sm.GetService('info').ShowInfo(cfg.eveowners.Get(self.charID).typeID, self.charID) 857 858 def GetDragData(self, *args): 859 if self and not self.destroyed: 860 return self.sr.node.scroll.GetSelectedNodes(self.sr.node) 861 else: 862 return [] 863 864 def OnClick(self, *args): 865 if self.destroyed: 866 return 867 prompt_player_fsd_dialog('ListEntryClick') 868 self.sr.node.scroll.SelectNode(self.sr.node) 869 if self.sr.node.Get('OnClick', None): 870 self.sr.node.OnClick(self) 871 872 @telemetry.ZONE_METHOD 873 def OnDblClick(self, *args): 874 if self.destroyed: 875 return 876 if self.sr.node.Get('OnDblClick', None): 877 self.sr.node.OnDblClick(self) 878 return 879 agentInfo = sm.GetService('agents').GetAgentByID(self.charID) 880 if session.stationid and agentInfo: 881 sm.GetService('agents').OpenDialogueWindow(self.charID) 882 return 883 self.ShowInfo() 884 885 def GetHeight(self, *args): 886 node, width = args 887 node.height = 51 888 return node.height 889 890 def RemoveFromListGroup(self, listGroupIDs, charIDs, listname): 891 if self.destroyed: 892 return 893 if listGroupIDs: 894 for listGroupID, charID in listGroupIDs: 895 uicore.registry.RemoveFromListGroup(listGroupID, charID) 896 897 sm.GetService('addressbook').RefreshWindow() 898 if charIDs and listname: 899 name = [localization.GetByLabel('UI/AddressBook/RemoveAddressBook1'), cfg.eveowners.Get(charIDs[0]).name][len(charIDs) == 1] 900 if prompt_player_fsd_dialog('WarnDeleteFromAddressbook', {'name': name, 901 'type': listname}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 902 return 903 sm.GetService('addressbook').DeleteEntryMulti(charIDs, None) 904 905 def OnChatButtonMouseEnter(self, btn, buttonIconOnMouseEnter, *args): 906 self.OnMouseEnter() 907 buttonIconOnMouseEnter() 908 909 def UpdateAlignment(self, *args, **kwargs): 910 alignment = super(AgentEntry, self).UpdateAlignment(*args, **kwargs) 911 self.UpdateLabelRightFade() 912 return alignment 913 914 def UpdateLabelRightFade(self): 915 availableWidth = ReverseScaleDpi(self.displayWidth) - 64 - ReverseScaleDpi(self.sr.missionLabel.displayWidth) 916 self.sr.namelabel.SetRightAlphaFade(fadeEnd=availableWidth, maxFadeWidth=20) 917 if self.agentChatBtn and self.agentChatBtn.display: 918 availableWidth = ReverseScaleDpi(self.displayWidth) - 64 - self.agentChatBtn.width 919 self.sr.levelLabel.SetRightAlphaFade(fadeEnd=availableWidth, maxFadeWidth=20) 920 else: 921 self.sr.levelLabel.SetRightAlphaFade(fadeEnd=0, maxFadeWidth=0)