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

notifications.py (16937B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\notifications.py
      2 import eveformat
      3 import utillib
      4 from carbon.common.script.sys.serviceConst import ROLE_GML
      5 from carbon.common.script.util import timerstuff
      6 from carbon.common.script.util.commonutils import StripTags
      7 from carbon.common.script.util.format import FmtDate
      8 from carbonui.control.dragResizeCont import DragResizeCont
      9 from carbonui.primitives.container import Container
     10 from carbonui.util.various_unsorted import SortListOfTuples
     11 from eve.client.script.ui.control import eveScroll
     12 from carbonui.button.group import ButtonGroup
     13 from eve.client.script.ui.control.divider import Divider
     14 import blue
     15 import eve.common.script.util.notificationconst as notificationConst
     16 import uthread
     17 import carbonui.const as uiconst
     18 import eve.common.script.util.notificationUtil as notificationUtil
     19 import localization
     20 from carbonui.uicore import uicore
     21 from eve.client.script.ui.control.entries.space import Space
     22 from eve.client.script.ui.control.entries.util import GetFromClass
     23 from eve.client.script.ui.control.eveEditPlainText import EditPlainText
     24 from eve.client.script.ui.control.listgroup import ListGroup
     25 from eve.client.script.ui.shared.neocom.evemail import MailEntry
     26 from menu import MenuLabel
     27 from globalConfig.getFunctions import IsPlayerBountyHidden
     28 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     29 HINTCUTOFF = 100
     30 DELETE_INTERVAL = 0.3 * const.SEC
     31 
     32 class NotificationForm(Container):
     33     __guid__ = 'form.NotificationForm'
     34     __notifyevents__ = ['OnNotificationsRefresh', 'OnNewNotificationReceived', 'OnNotificationReadOutside']
     35 
     36     def Setup(self):
     37         sm.RegisterNotify(self)
     38         self.scrollHeight = 0
     39         self.DrawStuff()
     40         self.readTimer = 0
     41         self.viewing = None
     42         self.lastDeleted = 0
     43 
     44     def DrawStuff(self, *args):
     45         btns = ButtonGroup(btns=[[localization.GetByLabel('UI/Mail/Notifications/MarkAllAsRead'),
     46           self.MarkAllRead,
     47           None,
     48           81], [localization.GetByLabel('UI/Mail/Notifications/DeleteAll'),
     49           self.DeleteAll,
     50           None,
     51           81]], parent=self, idx=0)
     52         leftContWidth = settings.user.ui.Get('notifications_leftContWidth', 200)
     53         self.sr.leftCont = Container(name='leftCont', parent=self, align=uiconst.TOLEFT, width=leftContWidth)
     54         self.sr.leftScroll = eveScroll.Scroll(name='leftScroll', parent=self.sr.leftCont)
     55         self.sr.leftScroll.multiSelect = 0
     56         divider = Divider(name='divider', align=uiconst.TOLEFT, width=const.defaultPadding, parent=self, state=uiconst.UI_NORMAL)
     57         divider.Startup(self.sr.leftCont, 'width', 'x', 180, 250)
     58         self.sr.rightCont = Container(name='rightCont', parent=self, align=uiconst.TOALL, pos=(0,
     59          0,
     60          const.defaultPadding,
     61          const.defaultPadding))
     62         dividerCont = DragResizeCont(name='dividerCont', settingsID='notificationsSplitSize', parent=self.sr.rightCont, align=uiconst.TOTOP_PROP, minSize=0.1, maxSize=0.9, defaultSize=0.7, clipChildren=True)
     63         self.sr.readingPaneCont = Container(name='readingPaneCont', parent=self.sr.rightCont, align=uiconst.TOALL)
     64         self.sr.readingPane = EditPlainText(setvalue='', parent=self.sr.readingPaneCont, align=uiconst.TOALL, readonly=1)
     65         self.sr.msgCont = Container(name='msgCont', parent=dividerCont)
     66         self.sr.msgScroll = eveScroll.Scroll(name='msgScroll', parent=self.sr.msgCont)
     67         self.sr.msgScroll.sr.id = 'notifications_msgs'
     68         self.sr.msgScroll.sr.fixedColumns = {localization.GetByLabel('UI/Mail/Status'): 52}
     69         self.sr.msgScroll.OnSelectionChange = self.MsgScrollSelectionChange
     70         self.sr.msgScroll.OnDelete = self.DeleteFromKeyboard
     71         self.inited = True
     72 
     73     def LoadNotificationForm(self, *args):
     74         self.LoadLeftSide()
     75 
     76     def OnClose_(self, *args):
     77         settings.user.ui.Set('notifications_leftContWidth', self.sr.leftCont.width)
     78         settings.user.ui.Set('notifications_readingContHeight', self.sr.readingPaneCont.height)
     79         sm.GetService('mailSvc').SaveChangesToDisk()
     80         sm.UnregisterNotify(self)
     81 
     82     def SelectGroupById(self, groupID):
     83         for entry in self.sr.leftScroll.GetNodes():
     84             if entry.groupID == groupID:
     85                 panel = entry.panel
     86                 if panel is not None:
     87                     self.UpdateCounters()
     88                     panel.OnClick()
     89 
     90     def LoadLeftSide(self):
     91         scrolllist = self.GetStaticLabelsGroups()
     92         self.sr.leftScroll.Load(contentList=scrolllist)
     93         lastViewedID = settings.char.ui.Get('mail_lastnotification', None)
     94         for entry in self.sr.leftScroll.GetNodes():
     95             if entry.groupID is None:
     96                 continue
     97             if entry.groupID == lastViewedID:
     98                 panel = entry.panel
     99                 if panel is not None:
    100                     self.UpdateCounters()
    101                     panel.OnClick()
    102                     return
    103 
    104         self.UpdateCounters()
    105         if len(self.sr.leftScroll.GetNodes()) > 0:
    106             entry = self.sr.leftScroll.GetNodes()[0]
    107             panel = entry.panel
    108             if panel is not None:
    109                 panel.OnClick()
    110 
    111     def GetStaticLabelsGroups(self):
    112         scrolllist = []
    113         lastViewedID = settings.char.ui.Get('mail_lastnotification', None)
    114         for groupID, labelPath in notificationUtil.groupNamePaths.iteritems():
    115             if groupID == notificationUtil.groupBounties and IsPlayerBountyHidden(sm.GetService('machoNet')):
    116                 continue
    117             label = localization.GetByLabel(labelPath)
    118             entry = self.GetGroupEntry(groupID, label, groupID == lastViewedID)
    119             strippedLabel = StripTags(label, stripOnly=['localized'])
    120             scrolllist.append((strippedLabel.lower(), entry))
    121 
    122         scrolllist = SortListOfTuples(scrolllist)
    123         entry = self.GetGroupEntry(const.notificationGroupUnread, localization.GetByLabel('UI/Mail/Unread'), const.notificationGroupUnread == lastViewedID)
    124         scrolllist.insert(0, entry)
    125         scrolllist.insert(1, GetFromClass(Space, {'height': 12}))
    126         return scrolllist
    127 
    128     def GetGroupEntry(self, groupID, label, selected = 0):
    129         return GetFromClass(ListGroup, {'GetSubContent': self.GetLeftGroups,
    130          'label': label,
    131          'id': ('notification', id),
    132          'state': 'locked',
    133          'BlockOpenWindow': 1,
    134          'disableToggle': 1,
    135          'expandable': 0,
    136          'showicon': 'hide',
    137          'showlen': 0,
    138          'groupItems': [],
    139          'hideNoItem': 1,
    140          'hideExpander': 1,
    141          'hideExpanderLine': 1,
    142          'selectGroup': 1,
    143          'isSelected': selected,
    144          'groupID': groupID,
    145          'OnClick': self.LoadGroupFromEntry,
    146          'MenuFunction': self.StaticMenu})
    147 
    148     def GetLeftGroups(self, *args):
    149         return []
    150 
    151     def LoadGroupFromEntry(self, entry, *args):
    152         group = entry.sr.node
    153         self.LoadGroupFromNode(group)
    154 
    155     def LoadGroupFromNode(self, node, refreshing = 0, selectedIDs = [], *args):
    156         group = node
    157         settings.char.ui.Set('mail_lastnotification', group.groupID)
    158         notifications = []
    159         if group.groupID == const.notificationGroupUnread:
    160             notifications = sm.GetService('notificationSvc').GetFormattedUnreadNotifications()
    161             senders = [ value.senderID for value in sm.GetService('notificationSvc').GetUnreadNotifications() ]
    162         else:
    163             notifications = sm.GetService('notificationSvc').GetFormattedNotifications(group.groupID)
    164             senders = [ value.senderID for value in sm.GetService('notificationSvc').GetNotificationsByGroupID(group.groupID) ]
    165         sm.GetService('mailSvc').PrimeOwners(senders)
    166         if not self or self.destroyed:
    167             return
    168         pos = self.sr.msgScroll.GetScrollProportion()
    169         scrolllist = []
    170         for each in notifications:
    171             senderName = ''
    172             if each.senderID == -1:
    173                 senderName = cfg.eveowners.Get(const.ownerSystem).ownerName
    174             elif each.senderID is not None:
    175                 senderName = cfg.eveowners.Get(each.senderID).ownerName
    176             label = '<t>' + senderName + '<t>' + each.subject + '<t>' + FmtDate(each.created, 'ls')
    177             if group.groupID == const.notificationGroupUnread:
    178                 typeGroup = notificationConst.GetTypeGroup(each.typeID)
    179                 labelPath = notificationUtil.groupNamePaths.get(typeGroup, None)
    180                 if labelPath is None:
    181                     typeName = ''
    182                 else:
    183                     typeName = localization.GetByLabel(labelPath)
    184                 label += '<t>' + typeName
    185             hint = eveformat.truncate_text_ignoring_tags(string=each.body.replace('<br>', ' '), length=HINTCUTOFF, trail=localization.GetByLabel('UI/Common/MoreTrail'))
    186             scrolllist.append(GetFromClass(MailEntry, {'cleanLabel': label,
    187              'parentNode': node,
    188              'label': label,
    189              'hint': hint.strip(),
    190              'id': each.notificationID,
    191              'typeID': each.typeID,
    192              'senderID': each.senderID,
    193              'data': utillib.KeyVal(read=each.processed),
    194              'info': each,
    195              'OnClick': self.LoadReadingPaneFromEntry,
    196              'OnDblClick': self.DblClickNotificationEntry,
    197              'GetMenu': self.GetEntryMenu,
    198              'ignoreRightClick': 1,
    199              'isSelected': each.notificationID in selectedIDs,
    200              'Draggable_blockDrag': 1,
    201              'isNotification': True}))
    202 
    203         scrollHeaders = [localization.GetByLabel('UI/Mail/Status'),
    204          localization.GetByLabel('UI/Mail/Sender'),
    205          localization.GetByLabel('UI/Mail/Subject'),
    206          localization.GetByLabel('UI/Mail/Received')]
    207         if group.groupID == const.notificationGroupUnread:
    208             scrollHeaders.append(localization.GetByLabel('UI/Mail/Notifications/GroupName'))
    209         if not self or self.destroyed:
    210             return
    211         self.sr.msgScroll.Load(contentList=scrolllist, headers=scrollHeaders, noContentHint=localization.GetByLabel('UI/Mail/Notifications/NoNotifications'))
    212         if not refreshing:
    213             self.ClearReadingPane()
    214         else:
    215             self.sr.msgScroll.ScrollToProportion(pos)
    216         self.UpdateCounters()
    217 
    218     def StaticMenu(self, node, *args):
    219         m = []
    220         if node.groupID != const.notificationGroupUnread:
    221             m.append((MenuLabel('UI/Mail/Notifications/MarkAllAsRead'), self.MarkAllReadInGroup, (node.groupID,)))
    222             m.append(None)
    223             m.append((MenuLabel('UI/Mail/Notifications/DeleteAll'), self.DeleteAllFromGroup, (node.groupID,)))
    224         return m
    225 
    226     def DeleteAll(self, *args):
    227         if prompt_player_fsd_dialog('EvemailNotificationsDeleteAll', {}, uiconst.YESNO, suppress=uiconst.ID_YES) == uiconst.ID_YES:
    228             sm.GetService('notificationSvc').DeleteAll()
    229 
    230     def MarkAllRead(self, *args):
    231         if prompt_player_fsd_dialog('EvemailNotificationsMarkAllRead', {}, uiconst.YESNO, suppress=uiconst.ID_YES) == uiconst.ID_YES:
    232             sm.GetService('notificationSvc').MarkAllRead()
    233 
    234     def DeleteAllFromGroup(self, groupID, *args):
    235         if prompt_player_fsd_dialog('EvemailNotificationsDeleteGroup', {}, uiconst.YESNO, suppress=uiconst.ID_YES) == uiconst.ID_YES:
    236             sm.GetService('notificationSvc').DeleteAllFromGroup(groupID)
    237 
    238     def MarkAllReadInGroup(self, groupID, *args):
    239         sm.GetService('notificationSvc').MarkAllReadInGroup(groupID)
    240 
    241     def GetEntryMenu(self, entry, *args):
    242         m = []
    243         sel = self.sr.msgScroll.GetSelected()
    244         selIDs = [ x.id for x in sel ]
    245         msgID = entry.sr.node.id
    246         if msgID not in selIDs:
    247             selIDs = [msgID]
    248             sel = [entry.sr.node]
    249         unread = {}
    250         for each in sel:
    251             if not each.data.read:
    252                 unread[each.id] = each
    253 
    254         if len(unread) > 0:
    255             m.append((MenuLabel('UI/Mail/Notifications/MarkAsRead'), self.MarkAsRead, (unread.values(), unread.keys())))
    256         m.append(None)
    257         if len(selIDs) > 0:
    258             m.append((MenuLabel('UI/Mail/Notifications/Delete'), self.DeleteNotifications, (sel, selIDs)))
    259         if session.role & ROLE_GML:
    260             m.append(('GM: MessageID=%s' % msgID, blue.pyos.SetClipboardData, (str(msgID),)))
    261         return m
    262 
    263     def MarkAsRead(self, notifications, notificationIDs, *args):
    264         sm.GetService('notificationSvc').MarkAsRead(notificationIDs)
    265         self.UpdateCounters()
    266         self.SetMsgEntriesAsRead(notifications)
    267 
    268     def DblClickNotificationEntry(self, entry):
    269         messageID = entry.sr.node.id
    270         info = entry.sr.node.info
    271         sm.GetService('notificationSvc').OpenNotificationReadingWnd(info)
    272 
    273     def LoadReadingPaneFromEntry(self, entry):
    274         uthread.new(self.LoadReadingPaneFromNode, entry.sr.node)
    275 
    276     def LoadReadingPaneFromNode(self, node):
    277         shift = uicore.uilib.Key(uiconst.VK_SHIFT)
    278         if not shift:
    279             self.LoadReadingPane(node)
    280 
    281     def LoadReadingPane(self, node):
    282         self.readTimer = 0
    283         info = node.info
    284         txt = sm.GetService('notificationSvc').GetReadingText(node.senderID, info.subject, info.created, info.body)
    285         self.sr.readingPane.SetText(txt)
    286         self.viewing = node.id
    287         if not node.data.read:
    288             self.MarkAsRead([node], [node.id])
    289 
    290     def ClearReadingPane(self):
    291         self.sr.readingPane.SetText('')
    292         self.viewing = None
    293 
    294     def SetMsgEntriesAsRead(self, nodes):
    295         for node in nodes:
    296             self.TryReloadNode(node)
    297 
    298     def TryReloadNode(self, node):
    299         node.data.read = 1
    300         panel = node.Get('panel', None)
    301         if panel is None:
    302             return
    303         panel.LoadMailEntry(node)
    304 
    305     def MsgScrollSelectionChange(self, sel = [], *args):
    306         if len(sel) == 0:
    307             return
    308         node = sel[0]
    309         if self.viewing != node.id:
    310             self.readTimer = timerstuff.AutoTimer(1000, self.LoadReadingPane, node)
    311 
    312     def DeleteFromKeyboard(self, *args):
    313         if blue.os.GetWallclockTime() - self.lastDeleted < DELETE_INTERVAL:
    314             prompt_player_fsd_dialog('uiwarning03')
    315             return
    316         sel = self.sr.msgScroll.GetSelected()
    317         ids = [ each.id for each in sel ]
    318         self.DeleteNotifications(sel, ids)
    319         self.lastDeleted = blue.os.GetWallclockTime()
    320 
    321     def DeleteNotifications(self, notificationEntries, ids):
    322         if len(notificationEntries) < 1:
    323             return
    324         idx = notificationEntries[0].idx
    325         ids = []
    326         for entry in notificationEntries:
    327             ids.append(entry.id)
    328 
    329         sm.GetService('notificationSvc').DeleteNotifications(ids)
    330         sm.ScatterEvent('OnMessageChanged', const.mailTypeNotifications, ids, 'deleted')
    331         self.sr.msgScroll.RemoveEntries(notificationEntries)
    332         if self.viewing in ids:
    333             self.ClearReadingPane()
    334         self.UpdateCounters()
    335         if len(self.sr.msgScroll.GetNodes()) < 1:
    336             self.sr.msgScroll.Load(contentList=[], headers=[], noContentHint=localization.GetByLabel('UI/Mail/Notifications/NoNotifications'))
    337             return
    338         numChildren = len(self.sr.msgScroll.GetNodes())
    339         newIdx = min(idx, numChildren - 1)
    340         newSelectedNode = self.sr.msgScroll.GetNode(newIdx)
    341         if newSelectedNode is not None:
    342             self.sr.msgScroll.SelectNode(newSelectedNode)
    343 
    344     def SelectNodeByNotificationID(self, notificationID):
    345         nodes = self.sr.msgScroll.GetNodes()
    346         for node in nodes:
    347             if node.id == notificationID:
    348                 self.sr.msgScroll.SelectNode(node)
    349                 break
    350 
    351     def OnNotificationsRefresh(self):
    352         self.LoadLeftSide()
    353 
    354     def OnNewNotificationReceived(self, *args):
    355         self.UpdateCounters()
    356 
    357     def OnNotificationReadOutside(self, notificationID):
    358         self.UpdateCounters()
    359         for node in self.sr.msgScroll.GetNodes():
    360             if node.id == notificationID:
    361                 self.SetMsgEntriesAsRead([node])
    362                 return
    363 
    364     def UpdateCounters(self):
    365         unreadCounts = sm.GetService('notificationSvc').GetAllUnreadCount()
    366         for each in self.sr.leftScroll.GetNodes():
    367             if each.groupID is None:
    368                 continue
    369             count = unreadCounts.get(each.groupID, 0)
    370             self.TryChangePanelLabel(each, count)
    371 
    372     def TryChangePanelLabel(self, node, count):
    373         panel = node.Get('panel', None)
    374         if panel is None:
    375             return
    376         panelLabel = self.GetPanelLabel(node.cleanLabel, count)
    377         panel.sr.label.text = panelLabel
    378 
    379     def GetPanelLabel(self, label, count):
    380         if count > 0:
    381             return localization.GetByLabel('UI/Mail/Notifications/GroupUnreadLabel', groupName=label, unreadCount=count)
    382         else:
    383             return label