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

member_list_entry.py (16022B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\chat\client\member_list_entry.py
      2 import sys
      3 import carbonui.const as uiconst
      4 from carbon.common.script.util.commonutils import GetAttrs
      5 from carbonui.control.scrollentries import SE_BaseClassCore
      6 from carbonui.primitives.container import Container
      7 from carbonui.primitives.sprite import Sprite
      8 from eve.client.script.ui.control import eveIcon
      9 from eve.client.script.ui.control.eveLabel import EveLabelMedium
     10 from eve.client.script.ui.control.eveWindowUnderlay import ListEntryUnderlay
     11 from eve.client.script.ui.shared.neocom.addressBook.contactsConst import COLOR_ONLINE, COLOR_OFFLINE
     12 from eve.client.script.ui.shared.stateFlag import GetStateFlagFromData, AddAndSetFlagIcon, AddAndSetFlagIconFromData
     13 from eve.client.script.ui.util.linkUtil import GetCharIDFromTextLink
     14 from eve.common.script.sys import idCheckers
     15 from eveservices.menu import GetMenuService
     16 import evetypes
     17 from menu import MenuLabel
     18 import localization
     19 import telemetry
     20 import uthread
     21 import log
     22 from carbonui.uicore import uicore
     23 import threadutils
     24 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     25 ICON_ONLINESTATUS = 'res:/UI/Texture/Classes/Contacts/onlineIcon.png'
     26 ICON_BLOCKED = 'res:/UI/Texture/Classes/Contacts/blockedWhite.png'
     27 BUDDY_CONTAINER_PAD_LEFT = 3
     28 BUDDY_CONTAINER_PAD_TOP = 1
     29 STATUS_ICON_SIZE = 12
     30 STATUS_ICON_PAD_LEFT = 2
     31 
     32 class ChatMemberListEntryUnderlay(ListEntryUnderlay):
     33     default_padBottom = 0
     34 
     35 
     36 class ChatMemberListEntry(SE_BaseClassCore):
     37     __guid__ = 'listentry.ChatMemberListEntry'
     38     __notifyevents__ = ['OnContactLoggedOn',
     39      'OnContactLoggedOff',
     40      'OnClientContactChange',
     41      'OnContactNoLongerContact',
     42      'OnStateSetupChange',
     43      'OnMyFleetInited',
     44      'OnFleetJoin_Local',
     45      'OnFleetLeave_Local',
     46      'ProcessOnUIAllianceRelationshipChanged',
     47      'OnContactChange',
     48      'OnBlockContacts',
     49      'OnUnblockContacts',
     50      'OnCrimewatchEngagementUpdated',
     51      'OnSuspectsAndCriminalsUpdate',
     52      'OnDisapprovalUpdate']
     53     default_highlightClass = ChatMemberListEntryUnderlay
     54     isDragObject = True
     55     charid = None
     56     selected = 0
     57     id = None
     58     groupID = None
     59     picloaded = 0
     60     label = None
     61 
     62     def Startup(self, scroll, *args, **kwargs):
     63         self._CreatePicture()
     64         self._CreateName()
     65         self.flagCont = None
     66         self._CreateBuddyContainer()
     67         self._CreateBottomRightContainer()
     68         sm.RegisterNotify(self)
     69 
     70     def _CreatePicture(self):
     71         self.sr.picture = Container(name='picture', parent=self, pos=(0, 0, 32, 32), state=uiconst.UI_DISABLED, align=uiconst.RELATIVE)
     72 
     73     @telemetry.ZONE_METHOD
     74     def _CreateName(self):
     75         self.sr.namelabel = EveLabelMedium(name='nameLabel', parent=self, state=uiconst.UI_DISABLED, text='', idx=0)
     76 
     77     def _CreateBuddyContainer(self):
     78         self.sr.statusIconContainer = Container(name='statusIconContainer', parent=self, align=uiconst.TOPRIGHT, width=16, height=16, idx=0)
     79         self.sr.statusIcon = Sprite(name='statusIcon', parent=self.sr.statusIconContainer, align=uiconst.CENTER, width=STATUS_ICON_SIZE, height=STATUS_ICON_SIZE, texturePath=ICON_ONLINESTATUS)
     80 
     81     def _CreateBottomRightContainer(self):
     82         self.bottomRightCont = Container(name='bottomRightCont', parent=self, align=uiconst.BOTTOMRIGHT, width=16, height=16, idx=0)
     83 
     84     def PreLoad(node):
     85         data = node
     86         charinfo = data.Get('info', None) or cfg.eveowners.Get(data.charID)
     87         data.info = charinfo
     88         if data.GetLabel:
     89             data.label = data.GetLabel(data)
     90         elif not data.Get('label', None):
     91             label = charinfo.name
     92             data.label = label
     93         groupID = evetypes.GetGroupID(data.info.typeID)
     94         data.invtype = data.info.typeID
     95         data.IsCharacter = groupID == const.groupCharacter
     96 
     97     def Load(self, node):
     98         self.sr.node = node
     99         data = node
    100         self.channelID = data.Get('channelID', None)
    101         self.name = data.info.name
    102         self.sr.namelabel.text = data.label
    103         self.charid = self.id = data.itemID = data.charID
    104         self.picloaded = 0
    105         self.confirmOnDblClick = data.Get('dblconfirm', 1)
    106         self.data = {'Name': self.name,
    107          'charid': data.charID}
    108         self.inWatchlist = sm.GetService('addressbook').IsInWatchlist(data.charID)
    109         self.sr.namelabel.SetAlign(uiconst.CENTERLEFT)
    110         self.sr.namelabel.left = 40
    111         self.LoadPortrait()
    112         uthread.new(self.SetRelationship, data)
    113         self.sr.statusIconContainer.display = False
    114         if data.charID != session.charid and self.inWatchlist:
    115             try:
    116                 self.SetOnline(sm.GetService('onlineStatus').GetOnlineStatus(data.charID, fetch=False))
    117             except IndexError:
    118                 sys.exc_clear()
    119 
    120         if self.sr.node.Get('selected', 0):
    121             self.Select()
    122         else:
    123             self.Deselect()
    124         self.SetBlocked(1)
    125         if uicore.uilib.mouseOver is self:
    126             self.Select()
    127 
    128     def GetDynamicHeight(node, width):
    129         node.height = 32
    130         return node.height
    131 
    132     def OnContactLoggedOn(self, charID):
    133         self._OnContactsOnlineStateChanged(charID, isOnline=1)
    134 
    135     def OnContactLoggedOff(self, charID):
    136         self._OnContactsOnlineStateChanged(charID, isOnline=0)
    137 
    138     def _OnContactsOnlineStateChanged(self, charID, isOnline):
    139         if self._IsMeOrDestroyedEntry(charID):
    140             return
    141         if self.IsThisCharacter(charID):
    142             self.SetOnline(isOnline)
    143 
    144     def OnClientContactChange(self, charID, online):
    145         self._OnContactsOnlineStateChanged(charID, isOnline=bool(online))
    146 
    147     def OnContactNoLongerContact(self, charID):
    148         self._OnContactsOnlineStateChanged(charID, isOnline=None)
    149 
    150     def IsThisCharacter(self, charID):
    151         return charID == self.charid
    152 
    153     def _IsMeOrDestroyedEntry(self, charID):
    154         if not self:
    155             return True
    156         if self.destroyed:
    157             return True
    158         if charID == session.charid:
    159             return True
    160         if idCheckers.IsNPC(charID):
    161             return True
    162         return False
    163 
    164     def OnPortraitCreated(self, charID, _size):
    165         if self.destroyed:
    166             return
    167         if self.sr.node and charID == self.sr.node.charID and not self.picloaded:
    168             self.LoadPortrait(orderIfMissing=False)
    169 
    170     def OnContactChange(self, contactIDs, contactType = None):
    171         if self.destroyed:
    172             return
    173         self.SetRelationship(self.sr.node)
    174         if self.charid in contactIDs:
    175             addressbookSvc = sm.GetService('addressbook')
    176             self.inWatchlist = addressbookSvc.IsInWatchlist(self.charid)
    177             if self.inWatchlist:
    178                 self.sr.statusIconContainer.display = True
    179             else:
    180                 isBlocked = addressbookSvc.IsBlocked(self.charid)
    181                 if isBlocked:
    182                     self.sr.statusIconContainer.display = True
    183                     self.sr.statusIcon.SetRGB(1.0, 1.0, 1.0)
    184                 else:
    185                     self.sr.statusIconContainer.display = False
    186 
    187     def OnBlockContacts(self, contactIDs):
    188         if not self or self.destroyed:
    189             return
    190         if self.charid in contactIDs:
    191             self.SetBlocked(1)
    192 
    193     def OnUnblockContacts(self, contactIDs):
    194         if not self or self.destroyed:
    195             return
    196         if self.charid in contactIDs:
    197             self.SetBlocked(0)
    198 
    199     def OnStateSetupChange(self, what):
    200         if self.destroyed:
    201             return
    202         self.SetRelationship(self.sr.node)
    203 
    204     def ProcessOnUIAllianceRelationshipChanged(self, *args):
    205         if self.destroyed:
    206             return
    207         self.SetRelationship(self.sr.node)
    208 
    209     def OnFleetJoin_Local(self, memberInfo):
    210         thisCharID = self.GetCharIdFromNode()
    211         if thisCharID is None:
    212             return
    213         charID = memberInfo.charID
    214         if charID == thisCharID:
    215             uthread.new(self.SetRelationship, self.sr.node)
    216 
    217     def OnFleetLeave_Local(self, memberInfo):
    218         thisCharID = self.GetCharIdFromNode()
    219         if thisCharID is None:
    220             return
    221         charID = memberInfo.charID
    222         if charID == thisCharID or charID == session.charid:
    223             uthread.new(self.SetRelationship, self.sr.node)
    224 
    225     def OnMyFleetInited(self):
    226         if self.destroyed:
    227             return
    228         uthread.new(self.SetRelationship, self.sr.node)
    229 
    230     def SetOnline(self, online):
    231         if self.destroyed:
    232             return
    233         if online is None or not self.inWatchlist:
    234             if not sm.GetService('addressbook').IsBlocked(self.charid):
    235                 self.sr.statusIconContainer.display = False
    236         else:
    237             color = COLOR_ONLINE if online else COLOR_OFFLINE
    238             self.sr.statusIcon.SetRGBA(*color)
    239             if online:
    240                 hint = localization.GetByLabel('UI/Common/Online')
    241             else:
    242                 hint = localization.GetByLabel('UI/Common/Offline')
    243             self.sr.statusIcon.hint = hint
    244             self.sr.statusIconContainer.display = True
    245 
    246     def SetBlocked(self, blocked):
    247         isBlocked = sm.GetService('addressbook').IsBlocked(self.charid)
    248         if blocked and isBlocked:
    249             self.sr.statusIcon.SetTexturePath(ICON_BLOCKED)
    250             self.sr.statusIconContainer.display = True
    251         elif self.inWatchlist:
    252             self.sr.statusIcon.SetTexturePath(ICON_ONLINESTATUS)
    253         else:
    254             self.sr.statusIconContainer.display = False
    255 
    256     def SetRelationship(self, data):
    257         if self.destroyed or not data:
    258             return
    259         flag = GetStateFlagFromData(data)
    260         if self.flagCont is None:
    261             self.flagCont = self.bottomRightCont
    262         AddAndSetFlagIcon(self.flagCont, align=uiconst.CENTER, flag=flag, width=12, height=12)
    263         self.flagCont.display = bool(flag is not None)
    264 
    265     def LoadPortrait(self, orderIfMissing = True):
    266         self.sr.picture.Flush()
    267         if self.sr.node is None:
    268             return
    269         if eveIcon.GetOwnerLogo(self.sr.picture, self.id, size=32, callback=True, orderIfMissing=orderIfMissing):
    270             self.picloaded = 1
    271 
    272     def GetMenu(self):
    273         if self.destroyed:
    274             return
    275         else:
    276             selected = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    277             if len(selected) < 2:
    278                 m = GetMenuService().GetMenuFromItemIDTypeID(self.id, self.sr.node.invtype, channelID=self.channelID)
    279                 if self.charid != session.charid:
    280                     m += [None, (MenuLabel('UI/Chat/ReportIskSpammer'), self._ReportISKSpammer)]
    281                 return m
    282             charIDs = []
    283             for entry in selected:
    284                 if entry.charID:
    285                     charIDs.append(entry.charID)
    286 
    287             return GetMenuService().CharacterMenu(charIDs)
    288 
    289     def _ReportISKSpammer(self, *args):
    290         sm.GetService('chat').report_isk_spammer(self.charid, self.channelID)
    291 
    292     def ShowInfo(self, *args):
    293         if self.destroyed:
    294             return
    295         sm.GetService('info').ShowInfo(cfg.eveowners.Get(self.charid).typeID, self.charid)
    296 
    297     def OnClick(self, *args):
    298         if self.destroyed:
    299             return
    300         prompt_player_fsd_dialog('ListEntryClick')
    301         self.sr.node.scroll.SelectNode(self.sr.node)
    302         if self.sr.node.Get('OnClick', None):
    303             self.sr.node.OnClick(self)
    304 
    305     def OnDblClick(self, *args):
    306         if self.destroyed:
    307             return
    308         if self.sr.node.Get('OnDblClick', None):
    309             self.sr.node.OnDblClick(self)
    310             return
    311         onDblClick = settings.user.ui.Get('dblClickUser', 0)
    312         if onDblClick == 0:
    313             sm.GetService('info').ShowInfo(cfg.eveowners.Get(self.charid).typeID, self.charid)
    314         elif onDblClick == 1:
    315             sm.GetService('chat').invite_to_private_chat(self.charid)
    316 
    317     def GetDragData(self, *args):
    318         if self and not self.destroyed:
    319             return self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    320         else:
    321             return []
    322 
    323     def OnSuspectsAndCriminalsUpdate(self, criminalizedCharIDs, decriminalizedCharIDs):
    324         return self._UpdateOnSuspectCriminalAndDisapprovalChanges(criminalizedCharIDs, decriminalizedCharIDs)
    325 
    326     def OnDisapprovalUpdate(self, newCharIDs, removedCharIDs):
    327         return self._UpdateOnSuspectCriminalAndDisapprovalChanges(newCharIDs, removedCharIDs)
    328 
    329     def _UpdateOnSuspectCriminalAndDisapprovalChanges(self, newCharIDs, removedCharIDs):
    330         charID = self.GetCharIdFromNode()
    331         if charID is None:
    332             return
    333         if charID in newCharIDs or charID in removedCharIDs:
    334             uthread.new(self.SetRelationship, self.sr.node)
    335 
    336     def OnCrimewatchEngagementUpdated(self, otherCharId, timeout):
    337         charID = self.GetCharIdFromNode()
    338         if charID is None:
    339             return
    340         if charID == otherCharId:
    341             uthread.new(self.SetRelationship, self.sr.node)
    342 
    343     @threadutils.throttled(0.2)
    344     def UpdateRelationship(self, characterID):
    345         if self.destroyed:
    346             return
    347         charID = self.GetCharIdFromNode()
    348         if charID is None or charID != characterID:
    349             return
    350         currentData = self.sr.node
    351         self.SetRelationship(currentData)
    352 
    353     def GetCharIdFromNode(self):
    354         if self.destroyed:
    355             return None
    356         charID = GetAttrs(self, 'sr', 'node', 'charID')
    357         return charID
    358 
    359     def OnDropData(self, dragObj, nodes):
    360         nonCharNodes = []
    361         for eachNode in nodes:
    362             itemID = getattr(eachNode, 'itemID', None)
    363             if not itemID:
    364                 itemID = GetCharIDFromTextLink(eachNode)
    365             if idCheckers.IsCharacter(itemID):
    366                 continue
    367             nonCharNodes.append(eachNode)
    368 
    369         if nonCharNodes and self.charid:
    370             from eve.client.script.ui.station.pvptrade.tradeUtil import TryInitiateTrade
    371             TryInitiateTrade(self.charid, nonCharNodes)
    372         self.sr.node.scroll.GetContentContainer().OnDropData(dragObj, nodes)
    373 
    374     def _IsDisplayed(self, container):
    375         return container is not None and not container.destroyed and container.display
    376 
    377     def _OnResize(self, *args):
    378         self.UpdateComponentSizes()
    379 
    380     def UpdateComponentSizes(self):
    381         occupiedWidth = 4
    382         if self._IsDisplayed(self.sr.statusIconContainer):
    383             occupiedWidth += STATUS_ICON_SIZE + STATUS_ICON_PAD_LEFT
    384         if self._IsDisplayed(self.flagCont):
    385             occupiedWidth = max(occupiedWidth, self.flagCont.width + 5)
    386         spaceAvailableForNameLabel = self.width - self.sr.namelabel.left - occupiedWidth
    387         self.sr.namelabel.SetRightAlphaFade(fadeEnd=spaceAvailableForNameLabel, maxFadeWidth=3)
    388 
    389     @classmethod
    390     def GetCopyData(cls, node):
    391         return node.label
    392 
    393 
    394 class ChatMemberCompactListEntry(ChatMemberListEntry):
    395     __guid__ = 'listentry.ChatMemberCompactListEntry'
    396     ENTRYHEIGHT = 16
    397 
    398     def Startup(self, *args):
    399         ChatMemberListEntry.Startup(self, *args)
    400         self.iconCont = Container(name='iconCont', parent=self, align=uiconst.TOLEFT, width=12)
    401 
    402     def _CreatePicture(self):
    403         pass
    404 
    405     def _CreateBottomRightContainer(self):
    406         pass
    407 
    408     def Load(self, node):
    409         ChatMemberListEntry.Load(self, node)
    410         self.sr.namelabel.left = 16
    411 
    412     def SetRelationship(self, data):
    413         if self.destroyed or not data:
    414             return
    415         AddAndSetFlagIconFromData(parentCont=self.iconCont, data=data, align=uiconst.CENTER, top=-1, left=0, width=12, height=12)
    416 
    417     def LoadPortrait(self, orderIfMissing = True):
    418         pass
    419 
    420     def _CreateBuddyContainer(self):
    421         self.sr.statusIconContainer = Container(name='statusIconContainer', parent=self, align=uiconst.TORIGHT, width=16, height=16)
    422         self.sr.statusIcon = Sprite(name='statusIcon', parent=self.sr.statusIconContainer, align=uiconst.CENTERRIGHT, width=STATUS_ICON_SIZE, height=STATUS_ICON_SIZE, texturePath=ICON_ONLINESTATUS)