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

eveCalendarsvc.py (31251B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\services\eveCalendarsvc.py
      2 import time
      3 import utillib
      4 from carbon.common.script.sys.service import Service
      5 from carbon.common.script.sys.serviceConst import SERVICE_RUNNING, SERVICE_START_PENDING
      6 from carbon.common.script.util.format import GetTimeParts, GetYearMonthFromTime
      7 from carbon.common.script.util.timerstuff import AutoTimer
      8 from carbonui import uiconst
      9 from carbonui.primitives.container import Container
     10 from eve.client.script.ui.shared.eveCalendar import CalendarNewEventWnd, CalendarSingleDayWnd, CalendarWnd
     11 from eve.client.script.ui.shared.stateFlag import AddAndSetFlagIcon, FlagIcon
     12 import blue
     13 from eve.client.script.parklife import states as state
     14 import localization
     15 import eveLocalization
     16 from carbonui.uicore import uicore
     17 from eve.client.script.util import eveMisc
     18 from eveexceptions import UserError
     19 from menu import MenuLabel
     20 from eveexceptions.exceptionEater import ExceptionEater
     21 from localization import GetByLabel
     22 from notifications.client.notificationSettings.notificationSettingHandler import NotificationSettingData
     23 from notifications.common.formatters.calendar import CalendarNotificationFormatter
     24 import eve.common.script.util.notificationconst as notificationConst
     25 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     26 from timeDateHelpers.const import MONTHANDYEAR_NAME_TEXT
     27 import eve.common.lib.appConst as const
     28 RESPONSETYPES = {const.eventResponseAccepted: 'UI/Calendar/ResponseTypes/Accepted',
     29  const.eventResponseDeclined: 'UI/Calendar/ResponseTypes/Declined',
     30  const.eventResponseDeleted: 'UI/Calendar/ResponseTypes/Canceled',
     31  const.eventResponseUninvited: 'UI/Calendar/ResponseTypes/Uninvited',
     32  const.eventResponseUndecided: 'UI/Calendar/ResponseTypes/NotResponded',
     33  const.eventResponseMaybe: 'UI/Calendar/ResponseTypes/MaybeReply'}
     34 EVENTTYPES = {const.calendarTagPersonal: 'UI/Calendar/CalendarWindow/GroupPersonal',
     35  const.calendarTagCorp: 'UI/Calendar/CalendarWindow/GroupCorp',
     36  const.calendarTagAlliance: 'UI/Calendar/CalendarWindow/GroupAlliance',
     37  const.calendarTagCCP: 'UI/Calendar/CalendarWindow/GroupCcp',
     38  const.calendarTagAutomated: 'UI/Calendar/CalendarWindow/GroupAutomated'}
     39 TAGLIST = [const.calendarTagPersonal,
     40  const.calendarTagCorp,
     41  const.calendarTagAlliance,
     42  const.calendarTagCCP,
     43  const.calendarTagAutomated]
     44 
     45 class CalendarSvc(Service):
     46     __guid__ = 'svc.calendar'
     47     __displayname__ = 'Calendar service'
     48     __notifyevents__ = ['OnNewCalendarEvent',
     49      'OnEditCalendarEvent',
     50      'OnRemoveCalendarEvent',
     51      'OnSessionChanged',
     52      'OnEventResponseByExternal']
     53     __startupdependencies__ = ['settings', 'objectCaching']
     54 
     55     def Run(self, *etc):
     56         self.state = SERVICE_START_PENDING
     57         self.events = {}
     58         self.eventDetails = {}
     59         self.eventsNotified = set()
     60         self.nextEvents = {}
     61         self.eventResponses = None
     62         self.calendarMgr = sm.RemoteSvc('calendarMgr')
     63         self.state = SERVICE_RUNNING
     64         self._calendarProxy = None
     65         self.notificationThread = AutoTimer(60000, self.CheckForNewEvents_thread)
     66 
     67     def GetCalendarProxy(self):
     68         if self._calendarProxy is None:
     69             self._calendarProxy = sm.ProxySvc('calendarProxy')
     70         return self._calendarProxy
     71 
     72     def IsInPast(self, year, month, monthday, hour = 0, min = 0, allowToday = 0, *args):
     73         now = blue.os.GetWallclockTime()
     74         if allowToday:
     75             cyear, cmonth, cwd, cday, chour, cmin, csec, cms = GetTimeParts(now)
     76             now = blue.os.GetTimeFromParts(cyear, cmonth, cday, 0, 0, 0, 0)
     77         thisDay = blue.os.GetTimeFromParts(year, month, monthday, hour, min, 0, 0)
     78         return self.IsInPastFromBlueTime(thisDay, now)
     79 
     80     def IsInPastFromBlueTime(self, then, now = None, *args):
     81         if now is None:
     82             now = blue.os.GetWallclockTime() + eveLocalization.GetTimeDelta() * const.SEC
     83         inPast = now > then
     84         return inPast
     85 
     86     def IsTooFarInFuture(self, year, month):
     87         now = blue.os.GetWallclockTime()
     88         rlYear, rlMonth, wd, day, hour, min, sec, ms = GetTimeParts(now)
     89         nowNumMonths = rlYear * 12 + rlMonth
     90         thenNumMonths = year * 12 + month
     91         difference = thenNumMonths - nowNumMonths
     92         if difference > const.calendarViewRangeInMonths:
     93             return True
     94         return False
     95 
     96     def FlushCache(self):
     97         self.events = {}
     98         self.nextEvents = {}
     99 
    100     def GetMonthText(self, year, month, *args):
    101         return localization.GetByLabel(MONTHANDYEAR_NAME_TEXT[month - 1], year=year)
    102 
    103     def GetBrowsedMonth(self, direction, year, month):
    104         if direction == 1:
    105             if month == const.calendarDecember:
    106                 year += 1
    107                 month = const.calendarJanuary
    108             else:
    109                 month += 1
    110         elif direction == -1:
    111             if month == const.calendarJanuary:
    112                 year -= 1
    113                 month = const.calendarDecember
    114             else:
    115                 month -= 1
    116         return (year, month)
    117 
    118     def GetEventMenu(self, eventInfo, myResponse = None, getJumpOption = True, *args):
    119         m = []
    120         m.append((MenuLabel('/Carbon/UI/Calendar/ViewEvent'), self.OpenEventWnd, (eventInfo,)))
    121         if getattr(eventInfo, 'isDeleted', None):
    122             return m
    123         canDelete = 0
    124         if not self.IsInPastFromBlueTime(then=eventInfo.eventDateTime):
    125             if eventInfo.ownerID != session.charid:
    126                 if eventInfo.flag in [const.calendarTagCorp, const.calendarTagAlliance]:
    127                     if eventInfo.ownerID in [session.corpid, session.allianceid] and session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
    128                         canDelete = 1
    129                         m.append((MenuLabel('/Carbon/UI/Calendar/EditEvent'), self.OpenEditEventWnd, (eventInfo,)))
    130                 if myResponse is None:
    131                     iconPath, myResponse = self.GetMyResponseIconFromID(eventInfo.eventID)
    132                 m.append(None)
    133                 if eventInfo.flag is not const.calendarTagCCP:
    134                     if myResponse != const.eventResponseAccepted:
    135                         m.append((MenuLabel('/Carbon/UI/Calendar/Accept'), self.RespondToEvent, (eventInfo.eventID, eventInfo, const.eventResponseAccepted)))
    136                     if myResponse != const.eventResponseMaybe:
    137                         m.append((MenuLabel('/Carbon/UI/Calendar/MaybeReply'), self.RespondToEvent, (eventInfo.eventID, eventInfo, const.eventResponseMaybe)))
    138                     if myResponse != const.eventResponseDeclined:
    139                         m.append((MenuLabel('/Carbon/UI/Calendar/Decline'), self.RespondToEvent, (eventInfo.eventID, eventInfo, const.eventResponseDeclined)))
    140             elif eventInfo.flag == const.calendarTagPersonal:
    141                 canDelete = 1
    142                 m.append((MenuLabel('/Carbon/UI/Calendar/EditEvent'), self.OpenEditEventWnd, (eventInfo,)))
    143         if getJumpOption:
    144             m.append(None)
    145             m.append((MenuLabel('/Carbon/UI/Calendar/GotoDay'), self.JumpToDay, (eventInfo,)))
    146         if canDelete:
    147             m.append(None)
    148             m.append((MenuLabel('/Carbon/UI/Calendar/DeleteEvent'), self.DeleteEvent, (eventInfo.eventID, eventInfo.ownerID)))
    149         return m
    150 
    151     def JumpToDay(self, eventInfo):
    152         calendar = self.FindCalendar()
    153         if calendar:
    154             year, month, wd, monthday, hour, minute, sec, ms = blue.os.GetTimeParts(eventInfo.eventDateTime)
    155             calendar.SetMonth(year, month, updateInView=1)
    156             blue.synchro.Yield()
    157             if calendar and not calendar.destroyed:
    158                 calendar.CrawlForAndSetMonthday(monthday)
    159 
    160     def OpenNewEventWnd(self, year, month, monthday, *args):
    161         configname = 'calendarNewEventWnd_%s_%s_%s' % (year, month, monthday)
    162         CalendarNewEventWnd.Open(windowID=configname, year=year, month=month, monthday=monthday)
    163 
    164     def CreateNewEvent(self, dateTime, duration, title, description, eventTag, important = 0, invitees = []):
    165         if not title.strip():
    166             raise UserError('CalendarEventMustSpecifyTitle')
    167         year, month, wd, day, hour, min, sec, ms = blue.os.GetTimeParts(dateTime)
    168         if self.IsTooFarInFuture(year, month):
    169             raise UserError('CalendarTooFarIntoFuture', {'numMonths': const.calendarViewRangeInMonths})
    170         if len(title) > const.calendarMaxTitleSize:
    171             raise UserError('CalendarTitleTooLong')
    172         newEventID = None
    173         if eventTag == const.calendarTagPersonal:
    174             if invitees:
    175                 newEventID = eveMisc.CSPAChargedAction('CSPACalendarCheck', self.calendarMgr, 'CreatePersonalEvent', dateTime, duration, title, description, important, invitees)
    176             else:
    177                 newEventID = self.calendarMgr.CreatePersonalEvent(dateTime, duration, title, description, important, invitees)
    178             if newEventID is not None:
    179                 self.OnNewCalendarEvent(eventID=newEventID, ownerID=session.charid, eventDateTime=dateTime, eventDuration=duration, eventTitle=title, importance=important)
    180                 if self.eventResponses is not None:
    181                     self.eventResponses[newEventID] = const.eventResponseAccepted
    182         elif eventTag == const.calendarTagCorp:
    183             newEventID = self.calendarMgr.CreateCorporationEvent(dateTime, duration, title, description, important)
    184         elif eventTag == const.calendarTagAlliance:
    185             newEventID = self.calendarMgr.CreateAllianceEvent(dateTime, duration, title, description, important)
    186 
    187     def UpdateEventParticipants(self, eventID, charsToAdd, charsToRemove):
    188         if eventID is not None:
    189             if len(charsToAdd) > 0:
    190                 eveMisc.CSPAChargedAction('CSPACalendarCheck', self.calendarMgr, 'UpdateEventParticipants', eventID, charsToAdd, charsToRemove)
    191             elif len(charsToRemove) > 0:
    192                 self.calendarMgr.UpdateEventParticipants(eventID, charsToAdd, charsToRemove)
    193             self.objectCaching.InvalidateCachedMethodCall('calendarMgr', 'GetResponsesToEvent', eventID, session.charid)
    194 
    195     def EditEvent(self, eventID, oldDateTime, dateTime, duration, title, description, eventTag, important = 0):
    196         year, month, wd, day, hour, min, sec, ms = blue.os.GetTimeParts(dateTime)
    197         if self.IsTooFarInFuture(year, month):
    198             raise UserError('CalendarTooFarIntoFuture', {'numMonths': const.calendarViewRangeInMonths})
    199         if oldDateTime != dateTime:
    200             if prompt_player_fsd_dialog('CalendarEventEditDate', {}, uiconst.YESNO) != uiconst.ID_YES:
    201                 return False
    202         if eventTag == const.calendarTagPersonal:
    203             self.calendarMgr.EditPersonalEvent(eventID, oldDateTime, dateTime, duration, title, description, important)
    204         elif eventTag == const.calendarTagCorp:
    205             self.calendarMgr.EditCorporationEvent(eventID, oldDateTime, dateTime, duration, title, description, important)
    206         elif eventTag == const.calendarTagAlliance:
    207             self.calendarMgr.EditAllianceEvent(eventID, oldDateTime, dateTime, duration, title, description, important)
    208         return True
    209 
    210     def GetEventFlag(self, ownerID, autoEventType = None):
    211         if ownerID == session.corpid:
    212             if autoEventType is None:
    213                 return const.calendarTagCorp
    214             return const.calendarTagAutomated
    215         elif ownerID == session.allianceid:
    216             return const.calendarTagAlliance
    217         elif ownerID == const.ownerSystem:
    218             return const.calendarTagCCP
    219         else:
    220             return const.calendarTagPersonal
    221 
    222     def GetEventsByMonthYear(self, month, year):
    223         eventList = self.events.get((month, year))
    224         if eventList is None:
    225             eventList = []
    226             dbRowList = self.GetCalendarProxy().GetEventList(month, year)
    227             for dbRows in dbRowList:
    228                 if dbRows is not None:
    229                     eventList.extend([ utillib.KeyVal(x) for x in dbRows ])
    230 
    231             for x in eventList:
    232                 x.flag = self.GetEventFlag(x.ownerID, x.Get('autoEventType', None))
    233 
    234             self.events[month, year] = eventList
    235         return eventList
    236 
    237     def GetEventResponses(self):
    238         if self.eventResponses is None:
    239             dbRows = self.calendarMgr.GetResponsesForCharacter()
    240             self.eventResponses = {}
    241             for dbRow in dbRows:
    242                 self.eventResponses[dbRow.eventID] = dbRow.status
    243 
    244         return self.eventResponses
    245 
    246     def GetEventDetails(self, eventID, ownerID):
    247         if eventID not in self.eventDetails:
    248             self.eventDetails[eventID] = self.GetCalendarProxy().GetEventDetails(eventID, ownerID)
    249         return self.eventDetails[eventID]
    250 
    251     def OpenSingleDayWnd(self, header, year, month, monthday, events, isADay = 1, wndType = 'singleWndDay', *args):
    252         windowInstanceID = '%s_%s_%s_%s' % (wndType,
    253          year,
    254          month,
    255          monthday)
    256         wnd = CalendarSingleDayWnd.GetIfOpen(windowID=wndType, windowInstanceID=windowInstanceID)
    257         if wnd:
    258             wnd.Maximize()
    259             return
    260         shift = uicore.uilib.Key(uiconst.VK_SHIFT)
    261         if not shift:
    262             for someWnd in uicore.registry.GetWindows()[:]:
    263                 if isinstance(someWnd, CalendarSingleDayWnd):
    264                     someWnd.CloseByUser()
    265 
    266         wnd = CalendarSingleDayWnd.Open(windowID=wndType, windowInstanceID=windowInstanceID, header=header, wndType=wndType, year=year, month=month, monthday=monthday, events=events, isADay=isADay)
    267 
    268     def OpenEditEventWnd(self, eventInfo, *args):
    269         self.OpenEventWnd(eventInfo, edit=1)
    270 
    271     def OpenEventWnd(self, eventInfo, edit = 0, *args):
    272         year, month, wd, monthday, hour, min, sec, ms = blue.os.GetTimeParts(eventInfo.eventDateTime)
    273         windowInstanceID = 'calendarEventWnd_%s' % eventInfo.eventID
    274         if edit:
    275             wnd = CalendarNewEventWnd.GetIfOpen(windowID='calendarEventWnd', windowInstanceID=windowInstanceID)
    276             if wnd and not wnd.inEditMode:
    277                 wnd.CloseByUser()
    278         wnd = CalendarNewEventWnd.Open(windowID='calendarEventWnd', windowInstanceID=windowInstanceID, year=year, month=month, monthday=monthday, eventInfo=eventInfo, edit=edit)
    279         if wnd:
    280             wnd.Maximize()
    281 
    282     def RespondToEvent(self, eventID, eventKV, response):
    283         self.calendarMgr.SendEventResponse(eventID, eventKV.ownerID, response)
    284         self._RespondToEvent(eventID, eventKV, response)
    285 
    286     def _RespondToEvent(self, eventID, eventKV, response):
    287         if self.eventResponses is not None:
    288             self.eventResponses[eventID] = response
    289         if response != const.eventResponseDeclined:
    290             if eventKV.eventDateTime > blue.os.GetWallclockTime():
    291                 year, month = GetYearMonthFromTime(eventKV.eventDateTime)
    292                 if self.IsInNextEventsWindow(year, month):
    293                     self.nextEvents[eventID] = eventKV
    294         elif eventID in self.nextEvents:
    295             self.nextEvents.pop(eventID, None)
    296         self.objectCaching.InvalidateCachedMethodCall('calendarMgr', 'GetResponsesToEvent', eventID, eventKV.ownerID)
    297         sm.ScatterEvent('OnReloadToDo')
    298         sm.ScatterEvent('OnRespondToEvent')
    299         sm.ScatterEvent('OnReloadCalendar')
    300 
    301     def DeleteEvent(self, eventID, ownerID):
    302         if prompt_player_fsd_dialog('CalendarDeleteEvent', {}, uiconst.YESNO) != uiconst.ID_YES:
    303             return False
    304         self.calendarMgr.DeleteEvent(eventID, ownerID)
    305         name = 'calendarEventWnd_%s' % eventID
    306         CalendarNewEventWnd.CloseIfOpen(windowID=name)
    307         return True
    308 
    309     def IsInNextEventsWindow(self, eventYear, eventMonth):
    310         now = blue.os.GetWallclockTime() + eveLocalization.GetTimeDelta() * const.SEC
    311         nowYear, nowMonth = GetYearMonthFromTime(now)
    312         if eventYear == nowYear:
    313             return eventMonth in (nowMonth, nowMonth + 1)
    314         if eventYear == nowYear + 1:
    315             return nowMonth == const.calendarDecember and eventMonth == const.calendarJanuary
    316         return False
    317 
    318     def OnNewCalendarEvent(self, eventID, ownerID, eventDateTime, eventDuration, eventTitle, importance, autoEventType = None, doBlink = True):
    319         year, month = GetYearMonthFromTime(eventDateTime)
    320         now = blue.os.GetWallclockTime()
    321         eventList = self.events.get((month, year))
    322         if eventList is not None:
    323             if eventID not in [ x.eventID for x in eventList ]:
    324                 eventKV = utillib.KeyVal(eventID=eventID, ownerID=ownerID, eventDateTime=eventDateTime, eventDuration=eventDuration, eventTitle=eventTitle, importance=importance, flag=self.GetEventFlag(ownerID, autoEventType))
    325                 eventKV.isDeleted = False
    326                 eventKV.dateModified = blue.os.GetWallclockTime()
    327                 eventList.append(eventKV)
    328                 self.events[month, year] = eventList
    329                 if eventDateTime > now and self.IsInNextEventsWindow(year, month):
    330                     self.nextEvents[eventID] = eventKV
    331         if doBlink and ownerID != session.charid and eventDateTime > now and self.IsInNextEventsWindow(year, month):
    332             sm.GetService('neocom').Blink('calendar', GetByLabel('UI/Neocom/Blink/NewCalendarEvent'))
    333         sm.ScatterEvent('OnReloadCalendar')
    334         sm.ScatterEvent('OnReloadToDo')
    335 
    336     def OnEditCalendarEvent(self, eventID, ownerID, oldEventDateTime, eventDateTime, eventDuration, eventTitle, importance, autoEventType = None):
    337         oldYear, oldMonth = GetYearMonthFromTime(oldEventDateTime)
    338         if eventID in self.nextEvents:
    339             self.nextEvents.pop(eventID)
    340         if eventID in self.eventDetails:
    341             self.eventDetails.pop(eventID)
    342         if oldEventDateTime != eventDateTime:
    343             if self.eventResponses is None:
    344                 self.GetEventResponses()
    345             if ownerID != session.charid:
    346                 oldReply = self.eventResponses.get(eventID, const.eventResponseUndecided)
    347                 if oldReply in (const.eventResponseUndecided, const.eventResponseAccepted, const.eventResponseMaybe):
    348                     self.eventResponses[eventID] = const.eventResponseUndecided
    349                     year, month = GetYearMonthFromTime(eventDateTime)
    350                     if eventDateTime > blue.os.GetWallclockTime() and self.IsInNextEventsWindow(year, month):
    351                         sm.GetService('neocom').Blink('calendar', GetByLabel('UI/Neocom/Blink/CalendarEventModified'))
    352             self.objectCaching.InvalidateCachedMethodCall('calendarMgr', 'GetResponsesToEvent', eventID, ownerID)
    353         eventList = self.events.get((oldMonth, oldYear))
    354         if eventList is not None:
    355             for evt in eventList:
    356                 if eventID == evt.eventID:
    357                     eventList.remove(evt)
    358 
    359             self.events[oldMonth, oldYear] = eventList
    360         self.OnNewCalendarEvent(eventID, ownerID, eventDateTime, eventDuration, eventTitle, importance, autoEventType, doBlink=False)
    361 
    362     def OnRemoveCalendarEvent(self, eventID, eventDateTime, isDeleted):
    363         year, month, wd, monthday, hour, min, sec, ms = blue.os.GetTimeParts(eventDateTime)
    364         eventList = self.events.get((month, year))
    365         if eventList is not None:
    366             for x in eventList:
    367                 if x.eventID == eventID:
    368                     if isDeleted:
    369                         x.isDeleted = True
    370                         x.dateModified = blue.os.GetWallclockTime()
    371                     else:
    372                         eventList.remove(x)
    373                     break
    374 
    375             self.events[month, year] = eventList
    376             if self.eventResponses and eventID in self.eventResponses and self.eventResponses.get(eventID, None) != const.eventResponseDeclined:
    377                 self.eventResponses.pop(eventID)
    378         self.nextEventsFetched = False
    379         sm.ScatterEvent('OnReloadToDo')
    380         sm.ScatterEvent('OnReloadCalendar')
    381 
    382     def OnSessionChanged(self, isRemote, session, change):
    383         if 'corpid' in change or 'allianceid' in change:
    384             self.events = {}
    385             self.nextEvents = {}
    386             self.nextEventsFetched = False
    387             sm.ScatterEvent('OnReloadToDo')
    388             sm.ScatterEvent('OnReloadCalendar')
    389 
    390     def OnEventResponseByExternal(self, eventID, eventKV, response):
    391         eventKV.flag = self.GetEventFlag(eventKV.flag)
    392         self._RespondToEvent(eventID, eventKV, response)
    393 
    394     def GetResponsesToEvent(self, eventID, ownerID):
    395         dbRows = self.calendarMgr.GetResponsesToEvent(eventID, ownerID)
    396         responseDict = {}
    397         for row in dbRows:
    398             if row.status != const.eventResponseUninvited:
    399                 responseDict[row.characterID] = row.status
    400 
    401         return responseDict
    402 
    403     def GetResponsesToEventInStatusDict(self, eventID, responseDict):
    404         statusDict = {}
    405         accepted = []
    406         rejected = []
    407         noreply = []
    408         maybe = []
    409         for charID, response in responseDict.iteritems():
    410             if response == const.eventResponseUndecided:
    411                 noreply.append(charID)
    412             elif response == const.eventResponseDeclined:
    413                 rejected.append(charID)
    414             elif response == const.eventResponseAccepted:
    415                 accepted.append(charID)
    416             elif response == const.eventResponseMaybe:
    417                 maybe.append(charID)
    418 
    419         statusDict[const.eventResponseUndecided] = noreply
    420         statusDict[const.eventResponseDeclined] = rejected
    421         statusDict[const.eventResponseAccepted] = accepted
    422         statusDict[const.eventResponseMaybe] = maybe
    423         return statusDict
    424 
    425     def GetResponseIconNum(self, response):
    426         if response == const.eventResponseAccepted:
    427             return 'ui_38_16_193'
    428         if response in [const.eventResponseDeclined, const.eventResponseDeleted]:
    429             return 'ui_38_16_194'
    430         if response == const.eventResponseUndecided:
    431             return 'ui_38_16_177'
    432         if response == const.eventResponseMaybe:
    433             return 'ui_38_16_195'
    434         return 'ui_38_16_192'
    435 
    436     def GetLongResponseIconPath(self, response):
    437         return self.GetResponseIconNum(response)
    438 
    439     def GetMyResponseIconFromID(self, eventID, long = 0, getDeleted = 0):
    440         if getDeleted:
    441             myResponse = const.eventResponseDeleted
    442         else:
    443             myResponse = self.GetMyResponse(eventID)
    444         if long:
    445             icon = self.GetLongResponseIconPath(myResponse)
    446         else:
    447             icon = self.GetResponseIconNum(myResponse)
    448         return (icon, myResponse)
    449 
    450     def GetActiveTags(self, *args):
    451         showTags = 0
    452         for tag in TAGLIST:
    453             checked = settings.user.ui.Get('calendarTagCheked_%s' % tag, 1)
    454             if checked:
    455                 showTags += tag
    456 
    457         return showTags
    458 
    459     def LoadTagIcon(self, tag):
    460         if tag not in [const.calendarTagCorp,
    461          const.calendarTagAlliance,
    462          const.calendarTagCCP,
    463          const.calendarTagAutomated]:
    464             return
    465         else:
    466             tagIconCont = Container(name='tagIconCont', parent=None, align=uiconst.TOPLEFT, pos=(0, 0, 14, 14))
    467             self.LoadTagIconInContainer(tag, tagIconCont, left=0, top=0)
    468             return tagIconCont
    469 
    470     def LoadTagIconInContainer(self, tag, cont, left = 2, top = 4, *args):
    471         cont.Flush()
    472         if tag == const.calendarTagCorp:
    473             AddAndSetFlagIcon(parentCont=cont, flag=state.flagSamePlayerCorp, top=top, left=left)
    474         elif tag == const.calendarTagAlliance:
    475             AddAndSetFlagIcon(parentCont=cont, flag=state.flagSameAlliance, top=top, left=left)
    476         elif tag == const.calendarTagCCP:
    477             self.LoadCCPIcon(cont, top, left)
    478         elif tag == const.calendarTagAutomated:
    479             self.LoadAutomatedIcon(cont, top, left)
    480 
    481     def LoadCCPIcon(self, container, top, left, *args):
    482         if getattr(container.sr, 'flag', None) is None or container.sr.flag.destroyed:
    483             container.sr.flag = FlagIcon(parent=container, left=left, top=top, state=uiconst.UI_DISABLED, align=uiconst.TOPRIGHT)
    484         container.sr.flag.SetBackgroundColor((0.7, 0.7, 0.7))
    485         container.sr.flag.SetIconTexturePath(iconIdx=2)
    486 
    487     def LoadAutomatedIcon(self, container, top, left, *args):
    488         if getattr(container.sr, 'flag', None) is None or container.sr.flag.destroyed:
    489             container.sr.flag = FlagIcon(parent=container, pos=(left,
    490              top,
    491              11,
    492              11), state=uiconst.UI_DISABLED, align=uiconst.TOPRIGHT)
    493         container.sr.flag.flagIcon.texturePath = 'res:/UI/Texture/Icons/AutomatedEntry_Icon_Alpha.png'
    494         color = sm.GetService('stateSvc').GetStateFlagColor(state.flagSamePlayerCorp)
    495         container.sr.flag.SetBackgroundColor(color, opacity=0.75)
    496 
    497     def GetMyChangedEvents(self, monthsAhead = 1):
    498         events = self.GetEventsNextXMonths(monthsAhead)
    499         showTag = self.GetActiveTags()
    500         changedEvents = {}
    501         now = blue.os.GetWallclockTime() + eveLocalization.GetTimeDelta() * const.SEC
    502         for eventID, eventKV in events.iteritems():
    503             if self.IsInUpdateEventsList(now, eventKV) and (showTag is None or showTag & eventKV.flag != 0):
    504                 changedEvents[eventID] = eventKV
    505 
    506         return changedEvents
    507 
    508     def GetMyNextEvents(self, monthsAhead = 1):
    509         events = self.GetEventsNextXMonths(monthsAhead)
    510         showTag = self.GetActiveTags()
    511         myNextEvents = {}
    512         now = blue.os.GetWallclockTime() + eveLocalization.GetTimeDelta() * const.SEC
    513         for eventID, eventKV in events.iteritems():
    514             if self.IsOnToDoList(now, eventKV) and (showTag is None or showTag & eventKV.flag != 0):
    515                 myNextEvents[eventID] = eventKV
    516 
    517         return myNextEvents
    518 
    519     def GetEventsNextXMonths(self, monthsAhead = 1, force = 0):
    520         if getattr(self, 'nextEventsFetched', False) and not force:
    521             return self.nextEvents
    522         self.nextEvents = self.FetchNextEvents(monthsAhead=monthsAhead)
    523         self.nextEventsFetched = True
    524         return self.nextEvents
    525 
    526     def FetchNextEvents(self, monthsAhead = 1):
    527         now = blue.os.GetWallclockTime() + eveLocalization.GetTimeDelta() * const.SEC
    528         year, month, wd, day, hour, minute, sec, ms = blue.os.GetTimeParts(now)
    529         nextEvents = self.FetchNextEventsDict(month, year, now)
    530         for i in xrange(monthsAhead):
    531             monthsFromNow = i + 1
    532             y, m = self.GetBrowsedMonth(monthsFromNow, year, month)
    533             nextMonthEvents = self.FetchNextEventsDict(m, y, now)
    534             nextEvents.update(nextMonthEvents)
    535 
    536         return nextEvents
    537 
    538     def FetchNextEventsDict(self, month, year, now):
    539         dict = {}
    540         events = self.GetEventsByMonthYear(month, year)
    541         for eventKV in events:
    542             dict[eventKV.eventID] = eventKV
    543 
    544         return dict
    545 
    546     def IsOnToDoList(self, now, eventKV):
    547         if eventKV.eventDateTime < now:
    548             return False
    549         if eventKV.isDeleted:
    550             return False
    551         if self.GetMyResponse(eventKV.eventID) in [const.eventResponseDeclined]:
    552             return False
    553         return True
    554 
    555     def IsInUpdateEventsList(self, now, eventKV):
    556         if now > eventKV.eventDateTime:
    557             return False
    558         myResponse = self.GetMyResponse(eventKV.eventID)
    559         if eventKV.isDeleted and myResponse != const.eventResponseDeclined:
    560             return True
    561         if myResponse == const.eventResponseUndecided:
    562             return True
    563         return False
    564 
    565     def GetMyResponse(self, eventID):
    566         if self.eventResponses is None:
    567             self.GetEventResponses()
    568         myResponse = self.eventResponses.get(eventID, const.eventResponseUndecided)
    569         return myResponse
    570 
    571     def GetEventHint(self, eventInfo, myResponse):
    572         if eventInfo is None:
    573             return ''
    574         if eventInfo.eventDuration is None:
    575             durationLabel = localization.GetByLabel('UI/Calendar/EventWindow/DateNotSpecified')
    576         else:
    577             hours = eventInfo.eventDuration / 60
    578             durationLabel = localization.GetByLabel('UI/Calendar/EventWindow/DateSpecified', hours=hours)
    579         responseLabel = localization.GetByLabel(self.GetResponseType().get(myResponse, 'UI/Generic/Unknown'))
    580         if getattr(eventInfo, 'eventTimeStamp', None) is None:
    581             year, month, wd, day, hour, min, sec, ms = blue.os.GetTimeParts(eventInfo.eventDateTime)
    582             ts = time.struct_time((year,
    583              month,
    584              day,
    585              hour,
    586              min,
    587              sec,
    588              0,
    589              1,
    590              0))
    591             eventInfo.eventTimeStamp = localization.formatters.FormatDateTime(value=ts, dateFormat='none', timeFormat='short')
    592         et = self.GetEventTypes().get(eventInfo.flag, '-')
    593         if et != '-':
    594             et = localization.GetByLabel(et)
    595         hint = localization.GetByLabel('UI/Calendar/Hints/Event', time=eventInfo.eventTimeStamp, title=eventInfo.eventTitle, eventType=et, response=responseLabel, duration=durationLabel, owner=cfg.eveowners.Get(eventInfo.ownerID).name)
    596         if eventInfo.importance > 0:
    597             hint += localization.GetByLabel('UI/Calendar/Hints/EventImportant')
    598         return hint
    599 
    600     def GetResponseType(self, *args):
    601         return RESPONSETYPES
    602 
    603     def GetEventTypes(self, *args):
    604         return EVENTTYPES
    605 
    606     def ShowCharacterInfo(self, itemID):
    607         return sm.GetService('info').ShowInfo(const.typeCharacter, itemID)
    608 
    609     def FindCalendar(self, *args):
    610         calendar = None
    611         wnd = CalendarWnd.GetIfOpen()
    612         if wnd:
    613             calendar = wnd.sr.calendarForm
    614         return calendar
    615 
    616     def CheckForNewEvents_thread(self):
    617         if not session.charid:
    618             return
    619         showTagMask = self.GetActiveTags()
    620         if not showTagMask:
    621             return
    622         if not AreNotificationActiveForCalendarEvents():
    623             return
    624         events = self.GetEventsNextXMonths()
    625         now = blue.os.GetWallclockTime()
    626         newEnoughTime = now - 5 * const.MIN
    627         notificationSvc = sm.GetService('notificationSvc')
    628         for each in events.itervalues():
    629             if each.isDeleted:
    630                 continue
    631             if each.eventID in self.eventsNotified:
    632                 continue
    633             if showTagMask & each.flag == 0:
    634                 continue
    635             if newEnoughTime < each.eventDateTime <= now:
    636                 with ExceptionEater('NotificationSvc: CheckForNewEvents_thread'):
    637                     notificationData = CalendarNotificationFormatter.MakeData(each)
    638                     notificationSvc.MakeAndScatterNotification(type=notificationConst.notificationTypeCalendarEvent, data=notificationData)
    639                 self.eventsNotified.add(each.eventID)
    640 
    641 
    642 def AreNotificationActiveForCalendarEvents():
    643     notificationSetting = settings.char.notifications.Get('notificationSettingsData', {}).get(notificationConst.notificationTypeCalendarEvent)
    644     if not notificationSetting:
    645         return True
    646     settingData = NotificationSettingData.fromTuple(notificationSetting)
    647     if settingData.showPopup or settingData.showAtAll:
    648         return True
    649     return False