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

eveCalendar.py (87535B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\eveCalendar.py
      2 import calendar
      3 import time
      4 import blue
      5 import eveLocalization
      6 import eveicon
      7 import uthread
      8 import utillib
      9 from bannedwords.client import bannedwords
     10 from carbon.client.script.util.misc import GetAttrs
     11 from carbon.common.script.util.format import FmtDate, GetTimeParts
     12 from carbonui import TextColor, uiconst
     13 from carbonui.control.combo import Combo
     14 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     15 from carbonui.control.window import Window
     16 from carbonui.decorative.panelUnderlay import PanelUnderlay
     17 from carbonui.primitives.container import Container
     18 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     19 from carbonui.primitives.frame import Frame
     20 from carbonui.primitives.layoutGrid import LayoutGrid
     21 from carbonui.util.various_unsorted import NiceFilter, SortListOfTuples
     22 from carbonui.button.group import ButtonGroup
     23 from carbonui.control.button import Button
     24 from eve.client.script.ui.control.datepicker import DatePicker
     25 from carbonui.control.checkbox import Checkbox
     26 from carbonui.control.radioButton import RadioButton
     27 from eve.client.script.ui.control.entries.generic import Generic
     28 from eve.client.script.ui.control.entries.user import SearchedUser
     29 from eve.client.script.ui.control.entries.util import GetFromClass
     30 from eve.client.script.ui.control.eveIcon import Icon
     31 from eve.client.script.ui.control.eveLabel import EveLabelSmall
     32 from eve.client.script.ui.control.listgroup import ListGroup
     33 from carbonui.control.tabGroup import TabGroup
     34 from eve.client.script.ui.control.themeColored import FrameThemeColored, FillThemeColored
     35 import evetypes
     36 from eve.client.script.ui.quickFilter import QuickFilterEdit
     37 from eve.client.script.ui.shared.neocom.ownerSearch import OwnerSearchWindow
     38 from eve.client.script.ui.control import eveEditPlainText, eveIcon, eveLabel, eveScroll
     39 from eve.client.script.ui.control.divider import Divider
     40 import localization
     41 from eve.client.script.ui.shared.userentry import User
     42 from eve.common.lib import appConst
     43 from eveexceptions import UserError
     44 from globalConfig.getFunctions import IsContentComplianceControlSystemActive
     45 from inventorycommon.util import IsNPC
     46 from menu import MenuLabel
     47 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     48 NUM_DAYROWS = 6
     49 DAY_NAME_SHORT_TEXT = ['UI/Moonmining/MondayShort',
     50  'UI/Moonmining/TuesdayShort',
     51  'UI/Moonmining/WednesdayShort',
     52  'UI/Moonmining/ThursdayShort',
     53  'UI/Moonmining/FridayShort',
     54  'UI/Moonmining/SaturdayShort',
     55  'UI/Moonmining/SundayShort']
     56 DAY_NAME_TEXT = ['/Carbon/UI/Common/Days/Monday',
     57  '/Carbon/UI/Common/Days/Tuesday',
     58  '/Carbon/UI/Common/Days/Wednesday',
     59  '/Carbon/UI/Common/Days/Thursday',
     60  '/Carbon/UI/Common/Days/Friday',
     61  '/Carbon/UI/Common/Days/Saturday',
     62  '/Carbon/UI/Common/Days/Sunday']
     63 
     64 class CalendarWnd(Window):
     65     __guid__ = 'form.eveCalendarWnd'
     66     __notifyevents__ = []
     67     default_windowID = 'calendar'
     68     default_captionLabelPath = 'UI/Calendar/CalendarWindow/Caption'
     69     default_iconNum = 'res:/ui/Texture/WindowIcons/calendar.png'
     70     default_minSize = (580, 400)
     71 
     72     def ApplyAttributes(self, attributes):
     73         super(CalendarWnd, self).ApplyAttributes(attributes)
     74         sm.RegisterNotify(self)
     75         sm.GetService('neocom').BlinkOff('calendar')
     76         self.sr.leftSide = Container(name='leftSide', parent=self.sr.main, align=uiconst.TOLEFT, pos=(0, 0, 150, 0), padding=(6,
     77          const.defaultPadding,
     78          0,
     79          const.defaultPadding))
     80         self.sr.xDivider = Divider(name='xDivider', parent=self.sr.main, align=uiconst.TOLEFT, pos=(0,
     81          0,
     82          const.defaultPadding,
     83          0), state=uiconst.UI_NORMAL)
     84         self.sr.xDivider.Startup(self.sr.leftSide, 'width', 'x', 75, 200)
     85         self.sr.calendarForm = Calendar(pos=(0, 0, 0, 0), parent=self.sr.main, padding=(const.defaultPadding,
     86          1,
     87          2 * const.defaultPadding,
     88          const.defaultPadding))
     89         self.sr.leftSideTop = Container(name='leftSideTop', parent=self.sr.leftSide, align=uiconst.TOTOP, pos=(0, 0, 0, 40))
     90         self.sr.cbCont = ContainerAutoSize(name='cbCont', parent=self.sr.leftSide, align=uiconst.TOBOTTOM, pos=(0, 6, 0, 125), clipChildren=True)
     91         self.sr.leftSideBottom = Container(name='leftSideBottom', parent=self.sr.leftSide, align=uiconst.TOALL, pos=(0, 0, 0, 0))
     92         self.sr.leftSideBottom.OnResize = self.OnResizeLeftSideBottom
     93         self.sr.updatedCont = Container(name='updatedCont', parent=self.sr.leftSideBottom, align=uiconst.TOBOTTOM, pos=(0, 0, 0, 60))
     94         self.sr.yDivider = Divider(name='yDivider', parent=self.sr.leftSideBottom, align=uiconst.TOBOTTOM, pos=(0,
     95          0,
     96          0,
     97          const.defaultPadding), state=uiconst.UI_NORMAL)
     98         self.sr.yDivider.Startup(self.sr.updatedCont, 'height', 'y', 50, 205)
     99         self.sr.yDivider.OnSizeChanged = self.OnListsSizeChanged
    100         self.sr.todoCont = Container(name='todoCont', parent=self.sr.leftSideBottom, align=uiconst.TOALL, padTop=4)
    101         hdrText = localization.GetByLabel('UI/Calendar/CalendarWindow/UpcomingEvents')
    102         eveLabel.EveLabelMedium(text=hdrText, parent=self.sr.todoCont, align=uiconst.TOTOP, bold=True, height=18)
    103         self.sr.toDoForm = EventList(pos=(0, 0, 0, 0), parent=self.sr.todoCont, name='toDoForm', listentryClass=CalendarListEntry, getEventsFunc=sm.GetService('calendar').GetMyNextEvents, header=hdrText, listType='upcomingEvents')
    104         hdrText = localization.GetByLabel('UI/Calendar/CalendarWindow/LatestUpdates')
    105         eveLabel.EveLabelMedium(text=hdrText, parent=self.sr.updatedCont, align=uiconst.TOTOP, bold=True, height=18)
    106         self.sr.changesForm = UpdateEventsList(pos=(0, 0, 0, 0), parent=self.sr.updatedCont, name='changesForm', listentryClass=CalendarUpdatedEntry, getEventsFunc=sm.GetService('calendar').GetMyChangedEvents, header=hdrText, listType='latestUpdates')
    107         self.AddCheckBoxes()
    108         self.sr.cbCont.height = sum([ each.height for each in self.sr.cbCont.children ])
    109         Button(parent=self.sr.leftSideTop, label=localization.GetByLabel('UI/Calendar/CalendarWindow/NewEvent'), func=self.CreateNewEvent, pos=(0, 7, 0, 0), fixedheight=20)
    110 
    111     def AddCheckBoxes(self, *args):
    112         self.sr.cbCont.Flush()
    113         eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Calendar/CalendarWindow/Filters'), parent=self.sr.cbCont, align=uiconst.TOTOP, bold=True, height=18, padTop=3)
    114         checkboxInfo = [(localization.GetByLabel('UI/Calendar/CalendarWindow/GroupPersonal'), 'calendarTagCheked_%s' % appConst.calendarTagPersonal, True)]
    115         if session.corpid and not IsNPC(session.corpid):
    116             checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/GroupCorp'), 'calendarTagCheked_%s' % appConst.calendarTagCorp, True))
    117         if session.allianceid:
    118             checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/GroupAlliance'), 'calendarTagCheked_%s' % appConst.calendarTagAlliance, True))
    119         checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/GroupCcp'), 'calendarTagCheked_%s' % appConst.calendarTagCCP, True))
    120         checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/GroupAutomated'), 'calendarTagCheked_%s' % appConst.calendarTagAutomated, True))
    121         checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/DeclinedEvents'), 'showDeclined', True))
    122         checkboxInfo.append((localization.GetByLabel('UI/Calendar/CalendarWindow/ShowTimestamp'), 'showTimestamp', True))
    123         self.sr.checkboxes = []
    124         for label, settingsKey, defaultValue in checkboxInfo:
    125             is_checked = 'calendar_%s' % settingsKey
    126             cb = Checkbox(text=label, parent=self.sr.cbCont, settingsKey=settingsKey, defaultValue=defaultValue, align=uiconst.TOTOP, padLeft=6, callback=self.DisplayCheckboxesChecked, checked=settings.user.ui.Get(is_checked, 1))
    127             self.sr.checkboxes.append(cb)
    128 
    129     def DisplayCheckboxesChecked(self, cb):
    130         config = 'calendar_%s' % cb.name
    131         settings.user.ui.Set(config, cb.checked)
    132         sm.ScatterEvent('OnCalendarFilterChange')
    133 
    134     def CreateNewEvent(self, *args):
    135         day = self.sr.calendarForm.selectedDay
    136         if day and not sm.GetService('calendar').IsInPast(day.year, day.month, day.monthday, allowToday=1):
    137             year = day.year
    138             month = day.month
    139             monthday = day.monthday
    140         else:
    141             prompt_player_fsd_dialog('CalendarCannotPlanThePast2')
    142             now = blue.os.GetWallclockTime()
    143             year, month, wd, monthday, hour, min, sec, ms = GetTimeParts(now)
    144         if not sm.GetService('calendar').IsInPast(year, month, monthday, allowToday=1):
    145             sm.GetService('calendar').OpenNewEventWnd(year, month, monthday)
    146 
    147     def OnListsSizeChanged(self, *args):
    148         h = self.sr.updatedCont.height
    149         l, t, w, absHeight = self.sr.leftSideBottom.GetAbsolute()
    150         if h > absHeight:
    151             h = absHeight
    152             ratio = float(h) / absHeight
    153             settings.user.ui.Set('calendar_listRatio', ratio)
    154             self._OnResize()
    155             return
    156         ratio = float(h) / absHeight
    157         settings.user.ui.Set('calendar_listRatio', ratio)
    158 
    159     def OnResizeLeftSideBottom(self, *args):
    160         if self and not self.destroyed and GetAttrs(self, 'sr', 'updatedCont'):
    161             l, t, w, absHeight = self.sr.leftSideBottom.GetAbsolute()
    162             scrollHeight = absHeight - 64
    163             ratio = settings.user.ui.Get('calendar_listRatio', 0.5)
    164             h = int(ratio * absHeight)
    165             if h > scrollHeight:
    166                 h = scrollHeight
    167             self.sr.updatedCont.height = max(64, h)
    168             self.sr.yDivider.max = scrollHeight
    169         uthread.new(self.UpdateIndicators)
    170 
    171     def UpdateIndicators(self, *args):
    172         blue.pyos.synchro.Yield()
    173         self.sr.changesForm.UpdateMoreIndicators()
    174         self.sr.toDoForm.UpdateMoreIndicators()
    175 
    176     def _OnResize(self, *args):
    177         Window._OnResize(self)
    178         self.sr.calendarForm._OnResize()
    179         self.sr.changesForm.OnResize()
    180         self.sr.toDoForm.OnResize()
    181 
    182     def OnExpanded(self, *args):
    183         super(CalendarWnd, self).OnExpanded(*args)
    184         uthread.new(self.OnExpanded_thread)
    185 
    186     def OnExpanded_thread(self, *args):
    187         blue.pyos.synchro.SleepWallclock(50)
    188         if self and not self.destroyed:
    189             self.UpdateIndicators()
    190 
    191 
    192 class Calendar(Container):
    193     __guid__ = 'form.eveCalendar'
    194     __notifyevents__ = ['OnReloadCalendar', 'OnReloadEvents', 'OnCalendarFilterChange']
    195     default_left = 0
    196     default_top = 0
    197     default_width = 256
    198     default_height = 256
    199 
    200     def ApplyAttributes(self, attributes):
    201         Container.ApplyAttributes(self, attributes)
    202         sm.GetService('calendar').GetEventResponses()
    203         self.monthInView = None
    204         self.allDayBoxes = []
    205         self.allDayBoxesByRows = {}
    206         self.allHeaderBoxes = []
    207         self.allDayRows = {}
    208         self.dayBoxesByDates = {}
    209         self.headerHeight = 24
    210         self.dayPadding = 1
    211         self.isTabStop = 1
    212         self.selectedDay = None
    213         self.disbleForward = False
    214         self.disbleBack = False
    215         self.Setup()
    216         self.InsertData()
    217 
    218     def Setup(self):
    219         sm.RegisterNotify(self)
    220         now = blue.os.GetWallclockTime()
    221         year, month, wd, day, hour, min, sec, ms = GetTimeParts(now)
    222         self.today = (year, month, day)
    223         self.calendar = calendar.Calendar()
    224         self.monthTextCont = Container(name='monthTextCont', parent=self, align=uiconst.TOTOP, pos=(0, 10, 0, 32))
    225         self.sr.gridCont = Container(name='gridCont', parent=self, align=uiconst.TOALL, pos=(0,
    226          0,
    227          0,
    228          const.defaultPadding))
    229         self.InsertBrowseControls()
    230         boxWidth = boxHeight = 30
    231         self.allHeaderBoxes = []
    232         self.allDayBoxes = []
    233         self.allDayBoxesByRows = {}
    234         row = Container(name='row', parent=self.sr.gridCont, align=uiconst.TOTOP, pos=(0,
    235          0,
    236          0,
    237          self.headerHeight))
    238         for j in xrange(0, const.calendarNumDaysInWeek):
    239             box = CalendarHeader(name='box', parent=row, align=uiconst.TOLEFT, pos=(0,
    240              0,
    241              boxWidth,
    242              0), padding=(self.dayPadding,
    243              self.dayPadding,
    244              self.dayPadding,
    245              self.dayPadding))
    246             self.allHeaderBoxes.append(box)
    247             setattr(self.sr, '%s_%s' % (0, j), box)
    248 
    249         row = None
    250         for i in xrange(1, NUM_DAYROWS + 1):
    251             row = Container(name='row', parent=self.sr.gridCont, align=uiconst.TOTOP, pos=(0,
    252              0,
    253              0,
    254              boxHeight))
    255             self.allDayRows[i] = row
    256             daysInRow = []
    257             box = None
    258             for j in xrange(0, const.calendarNumDaysInWeek):
    259                 configname = '%s_%s' % (i, j)
    260                 box = self.GetDay(row, boxWidth, configname)
    261                 self.allDayBoxes.append(box)
    262                 daysInRow.append(box)
    263                 setattr(self.sr, configname, box)
    264 
    265             if box is not None:
    266                 box.align = uiconst.TOALL
    267                 box.width = 0
    268             self.allDayBoxesByRows[i] = daysInRow
    269 
    270         if row is not None:
    271             row.align = uiconst.TOALL
    272             row.height = 0
    273         self.SetSizes()
    274         self.sr.gridCont._OnSizeChange_NoBlock = self.OnGridContainerSize
    275 
    276     def InsertBrowseControls(self, *args):
    277         self.sr.backBtn = Button(name='BackBtn', align=uiconst.TOLEFT, parent=self.monthTextCont, texturePath=eveicon.navigate_back, iconSize=24, iconPadding=-4, func=self.OnBackBtn, hint=localization.GetByLabel('UI/Calendar/Hints/Previous'))
    278         self.sr.fwdBtn = Button(name='FwdBtn', parent=self.monthTextCont, align=uiconst.TOLEFT, padLeft=4, texturePath=eveicon.navigate_forward, iconSize=24, iconPadding=-4, func=self.OnFwdBtn, hint=localization.GetByLabel('UI/Calendar/Hints/Next'))
    279         self.sr.todayBtn = Button(parent=self.monthTextCont, label=localization.GetByLabel('UI/Calendar/CalendarWindow/Today'), func=self.GetToday, align=uiconst.TOPRIGHT, fixedheight=20)
    280 
    281     def ChangeBrowseDisplay(self, btn, disable = 0):
    282         if disable:
    283             btn.opacity = 0.3
    284             btn.state = uiconst.UI_DISABLED
    285         else:
    286             btn.opacity = 1.0
    287             btn.state = uiconst.UI_NORMAL
    288 
    289     def GetDay(self, parent, width, configname):
    290         box = CalendarDay(name='box', parent=parent, align=uiconst.TOLEFT, pos=(0,
    291          0,
    292          width,
    293          0), padding=(self.dayPadding,
    294          self.dayPadding,
    295          self.dayPadding,
    296          self.dayPadding), configname=configname)
    297         box.DoClickDay = self.DoClickDay
    298         box.DoDblClickDay = self.DoDblClickDay
    299         return box
    300 
    301     def GetDayNameText(self, dayNumber):
    302         dayName = localization.GetByLabel(DAY_NAME_SHORT_TEXT[dayNumber])
    303         return dayName
    304 
    305     def GetToday(self, *args):
    306         self.ResetBrowse()
    307         self.InsertData()
    308 
    309     def ResetBrowse(self, *args):
    310         self.disbleBack = False
    311         self.disbleForward = False
    312         self.ChangeBrowseDisplay(self.sr.backBtn, disable=self.disbleBack)
    313         self.ChangeBrowseDisplay(self.sr.fwdBtn, disable=self.disbleForward)
    314 
    315     def SetMonth(self, year, month, updateInView = 0, *args):
    316         if updateInView:
    317             self.yearMonthInView = (year, month)
    318         i = 1
    319         j = 0
    320         self.dayBoxesByDates = {}
    321         self.lastNextMonthDay = 0
    322         daysInMonth = self.calendar.monthdayscalendar(year, month)
    323         firstRow = daysInMonth[0]
    324         numEmptyDaysBefore = firstRow.count(0)
    325         emptyDaysBefore = []
    326         if emptyDaysBefore > 0:
    327             newYear, newMonth = sm.GetService('calendar').GetBrowsedMonth(-1, year, month)
    328             monthRange = calendar.monthrange(newYear, newMonth)
    329             emptyDaysBefore = [ d for d in xrange(monthRange[1], monthRange[1] - numEmptyDaysBefore, -1) ]
    330         for weekNumber, week in enumerate(daysInMonth):
    331             for monthday in week:
    332                 notInMonth = 0
    333                 if monthday == 0:
    334                     if weekNumber == 0:
    335                         monthday = emptyDaysBefore.pop(-1)
    336                         notInMonth = -1
    337                     else:
    338                         self.lastNextMonthDay += 1
    339                         monthday = self.lastNextMonthDay
    340                         notInMonth = 1
    341                 self.ChangeDayBox(i, j, year, month, monthday, notInMonth)
    342                 j += 1
    343 
    344             j = 0
    345             i += 1
    346 
    347         for i in xrange(i, NUM_DAYROWS + 1):
    348             for j in xrange(0, const.calendarNumDaysInWeek):
    349                 self.lastNextMonthDay += 1
    350                 monthday = self.lastNextMonthDay
    351                 self.ChangeDayBox(i, j, year, month, monthday, notInMonth=1)
    352 
    353         self.SetMonthText(year, month)
    354         self.LoadEvents()
    355 
    356     def ChangeMonth(self, direction = 1, selectDay = 1, *args):
    357         year, month = self.yearMonthInView
    358         if direction == -1 and self.disbleBack or direction == 1 and self.disbleForward:
    359             return False
    360         year, month = sm.GetService('calendar').GetBrowsedMonth(direction, year, month)
    361         self.yearMonthInView = (year, month)
    362         self.SetMonth(year, month)
    363         now = blue.os.GetWallclockTime()
    364         rlYear, rlMonth, wd, day, hour, min, sec, ms = GetTimeParts(now)
    365         nowNumMonths = rlYear * 12 + rlMonth
    366         thenNumMonths = year * 12 + month
    367         difference = thenNumMonths - nowNumMonths
    368         self.disbleForward = 0
    369         self.disbleBack = 0
    370         if direction == 1 and difference >= const.calendarViewRangeInMonths:
    371             self.disbleForward = 1
    372         elif direction == -1 and -difference >= const.calendarViewRangeInMonths:
    373             self.disbleBack = 1
    374         self.ChangeBrowseDisplay(self.sr.backBtn, disable=self.disbleBack)
    375         self.ChangeBrowseDisplay(self.sr.fwdBtn, disable=self.disbleForward)
    376         self.selectedDay = self.CrawlForValidDay(self.selectedDay, direction, 'day')
    377         if selectDay:
    378             self.SelectDay()
    379         return True
    380 
    381     def SetCurrentRLMonth(self, selectToday = True, *args):
    382         now = blue.os.GetWallclockTime()
    383         year, month, wd, monthday, hour, min, sec, ms = GetTimeParts(now)
    384         self.yearMonthInView = (year, month)
    385         self.SetMonth(year, month)
    386         if selectToday:
    387             self.CrawlForAndSetMonthday(monthday)
    388 
    389     def ChangeDayBox(self, i, j, year, month, monthday = 0, notInMonth = 0):
    390         day = self.sr.get('%s_%s' % (i, j), None)
    391         if day:
    392             today = False
    393             if notInMonth == 0:
    394                 self.dayBoxesByDates[monthday] = day
    395                 if self.today == (year, month, monthday):
    396                     today = True
    397             day.SetDay(year, month, monthday=monthday, notInMonth=notInMonth, today=today)
    398 
    399     def SelectDay(self, *args):
    400         if self.selectedDay is None:
    401             self.selectedDay = self.sr.get('1_0', None)
    402         if self.selectedDay:
    403             for dayBox in self.allDayBoxes:
    404                 if dayBox != self.selectedDay:
    405                     dayBox.SetSelectedFrameState(on=0)
    406 
    407             self.selectedDay.SetSelectedFrameState(on=1)
    408 
    409     def SelectNextDay(self, direction = 1, weekOrDay = 'day', *args):
    410         currentlySelected = self.selectedDay
    411         if currentlySelected is None:
    412             newSelected = self.sr.get('1_0', None)
    413         else:
    414             newSelected = self.FindAnotherDay(currentlySelected, direction, weekOrDay)
    415         if newSelected:
    416             if newSelected.disabled:
    417                 wasChanged = self.ChangeMonth(direction, selectDay=0)
    418                 if wasChanged == False:
    419                     return
    420                 validDay = self.CrawlForValidDay(newSelected, direction, weekOrDay)
    421                 newSelected = validDay
    422             self.selectedDay = newSelected
    423         self.SelectDay()
    424 
    425     def CrawlForValidDay(self, newSelected, direction, weekOrDay, *args):
    426         configname = newSelected.configname
    427         row, col = configname.split('_')
    428         if direction == -1:
    429             row = NUM_DAYROWS
    430         elif direction == 1:
    431             row = 1
    432         configname = '%s_%s' % (row, col)
    433         newSelected = self.sr.get(configname, None)
    434         while newSelected.disabled:
    435             newSelected = self.FindAnotherDay(newSelected, direction, weekOrDay)
    436 
    437         return newSelected
    438 
    439     def CrawlForMonthday(self, monthday, *args):
    440         for day in self.allDayBoxes:
    441             if day.monthday == monthday and not day.disabled:
    442                 return day
    443 
    444     def CrawlForAndSetMonthday(self, monthday, *args):
    445         day = self.CrawlForMonthday(monthday)
    446         if day:
    447             self.selectedDay = day
    448             self.SelectDay()
    449 
    450     def OpenDay(self, *args):
    451         if self.selectedDay is not None:
    452             self.selectedDay.OnDblClickDay()
    453 
    454     def DoClickDay(self, day, *args):
    455         uthread.new(self.DoClickDay_thread, day)
    456 
    457     def DoClickDay_thread(self, day):
    458         if day.disabled:
    459             return
    460         self.selectedDay = day
    461         self.SelectDay()
    462 
    463     def DoDblClickDay(self, day, *args):
    464         if GetAttrs(day, 'disabled'):
    465             monthday = day.monthday
    466             self.ChangeMonth(day.disabled, selectDay=0)
    467             self.CrawlForAndSetMonthday(monthday)
    468         else:
    469             day.OpenSingleDayWnd()
    470 
    471     def FindAnotherDay(self, selectedDay, direction, weekOrDay = 'day'):
    472         newSelected = selectedDay
    473         index = self.allDayBoxes.index(selectedDay)
    474         if weekOrDay == 'day':
    475             if direction == -1:
    476                 if index == 0:
    477                     newSelected = self.allDayBoxes[-1]
    478                 else:
    479                     newSelected = self.allDayBoxes[index - 1]
    480             elif direction == 1:
    481                 if len(self.allDayBoxes) > index + 1:
    482                     newSelected = self.allDayBoxes[index + 1]
    483                 else:
    484                     newSelected = self.allDayBoxes[0]
    485         elif weekOrDay == 'week':
    486             configname = selectedDay.configname
    487             row, col = configname.split('_')
    488             row = int(row)
    489             col = int(col)
    490             if direction == -1:
    491                 previousRow = row - 1
    492                 newRow = self.allDayBoxesByRows.get(previousRow, None)
    493                 if newRow is None:
    494                     newRow = self.allDayBoxesByRows.get(len(self.allDayBoxesByRows), None)
    495                     if newRow is None:
    496                         newRow = self.allDayBoxesByRows.get(1)
    497                 newSelected = newRow[col]
    498             elif direction == 1:
    499                 nextRow = row + 1
    500                 newRow = self.allDayBoxesByRows.get(nextRow, None)
    501                 if newRow is None:
    502                     newRow = self.allDayBoxesByRows.get(1)
    503                 newSelected = newRow[col]
    504         return newSelected
    505 
    506     def AddMonthText(self, text = '', *args):
    507         if self.sr.Get('monthText', None) is None:
    508             self.sr.monthText = eveLabel.EveCaptionMedium(text=text, parent=self.monthTextCont, state=uiconst.UI_NORMAL, align=uiconst.CENTERTOP)
    509         return self.sr.monthText
    510 
    511     def SetMonthText(self, year, month, *args):
    512         self.AddMonthText()
    513         text = sm.GetService('calendar').GetMonthText(year, month)
    514         self.sr.monthText.text = text
    515 
    516     def SetHeader(self, *args):
    517         j = 0
    518         i = 0
    519         for j in xrange(0, const.calendarNumDaysInWeek):
    520             dayName = self.GetDayNameText(j)
    521             day = self.sr.get('%s_%s' % (i, j), None)
    522             if day:
    523                 day.SetDayName(dayName)
    524             j += 1
    525 
    526     def SetSizes(self, size = None):
    527         if size is None:
    528             w, h = self.sr.gridCont.GetAbsoluteSize()
    529         else:
    530             w, h = size
    531         newBoxWidth = w / const.calendarNumDaysInWeek
    532         newBoxHeight = (h - self.headerHeight) / NUM_DAYROWS
    533         newBoxWidth -= 2 * self.dayPadding
    534         newBoxHeight -= 2 * self.dayPadding
    535         for box in self.allHeaderBoxes:
    536             box.width = newBoxWidth
    537 
    538         row = None
    539         for row in self.allDayRows.values():
    540             row.height = newBoxHeight
    541 
    542         if row is not None:
    543             row.height = 0
    544         counter = 0
    545         for box in self.allDayBoxes:
    546             counter += 1
    547             if counter >= const.calendarNumDaysInWeek:
    548                 counter = 0
    549             else:
    550                 box.width = newBoxWidth
    551             box.CheckEventsClipped()
    552 
    553         return (newBoxWidth, newBoxHeight)
    554 
    555     def InsertData(self, *args):
    556         self.SetCurrentRLMonth()
    557         self.SetHeader()
    558 
    559     def LoadEventsToADay(self, date, eventsThisDay):
    560         dayBox = self.dayBoxesByDates.get(date, None)
    561         if dayBox is None:
    562             return
    563         dayBox.LoadEvents(eventsThisDay)
    564 
    565     def LoadEvents(self, *args):
    566         yearInView, monthInView = self.yearMonthInView
    567         events = sm.GetService('calendar').GetEventsByMonthYear(monthInView, yearInView)
    568         showTag = sm.GetService('calendar').GetActiveTags()
    569         eventsByDates = {}
    570         for eventKV in events:
    571             if eventKV.isDeleted:
    572                 continue
    573             year, month, wd, day, hour, minute, sec, ms = blue.os.GetTimeParts(eventKV.eventDateTime)
    574             ts = eventKV.eventDateTime - eveLocalization.GetTimeDelta() * const.SEC
    575             timeStr = localization.formatters.FormatDateTime(value=ts, dateFormat='none', timeFormat='short')
    576             eventKV.eventTimeStamp = timeStr
    577             if showTag is None or showTag & eventKV.flag != 0:
    578                 eventsThisDay = eventsByDates.get(day, {})
    579                 eventsThisDay[eventKV.eventID] = eventKV
    580                 eventsByDates[day] = eventsThisDay
    581 
    582         for date, eventsThisDay in eventsByDates.iteritems():
    583             self.LoadEventsToADay(date, eventsThisDay)
    584 
    585     def OnKeyDown(self, vkey, flag, *args):
    586         if vkey == uiconst.VK_RIGHT:
    587             self.SelectNextDay(1)
    588         elif vkey == uiconst.VK_LEFT:
    589             self.SelectNextDay(-1)
    590         elif vkey == uiconst.VK_UP:
    591             self.SelectNextDay(-1, weekOrDay='week')
    592         elif vkey == uiconst.VK_DOWN:
    593             self.SelectNextDay(1, weekOrDay='week')
    594         elif vkey == uiconst.VK_RETURN:
    595             self.OpenDay()
    596 
    597     def OnSetFocus(self, *args):
    598         self.SelectDay()
    599 
    600     def OnBackBtn(self, *args):
    601         self.ChangeMonth(-1)
    602 
    603     def OnFwdBtn(self, *args):
    604         self.ChangeMonth()
    605 
    606     def OnCalendarFilterChange(self, *args):
    607         self.OnReloadCalendar()
    608 
    609     def OnGridContainerSize(self, displayWidth, displayHeight):
    610         self.SetSizes((displayWidth, displayHeight))
    611 
    612     def OnReloadCalendar(self, *args):
    613         year, month = self.yearMonthInView
    614         self.SetMonth(year, month)
    615 
    616     def OnReloadEvents(self, *args):
    617         self.LoadEvents()
    618 
    619 
    620 class CalendarDay(Container):
    621     default_left = 0
    622     default_top = 0
    623     default_width = 256
    624     default_height = 256
    625     default_name = 'CalendarDay'
    626 
    627     def ApplyAttributes(self, attributes):
    628         Container.ApplyAttributes(self, attributes)
    629         self.year = None
    630         self.month = None
    631         self.monthday = 0
    632         self.events = {}
    633         self.eventHeight = 14
    634         self.disabled = 0
    635         self.configname = attributes.get('configname', None)
    636         self.Prepare_()
    637 
    638     def Prepare_(self, *args):
    639         self.sr.day = Container(name='dayNumberCont', parent=self, align=uiconst.TOALL, pos=(1, 1, 1, 1))
    640         self.sr.dayNumberCont = Container(name='dayNumberCont', parent=self.sr.day, align=uiconst.TOTOP, pos=(0, 0, 0, 12), state=uiconst.UI_NORMAL)
    641         self.sr.moreCont = Container(name='moreCont', parent=self.sr.day, align=uiconst.TOBOTTOM, pos=(0, 0, 0, 10), state=uiconst.UI_HIDDEN, padding=(0, 0, 0, 0))
    642         self.AddMoreContFill()
    643         self.AddFill()
    644         self.AddFrame()
    645         self.sr.emptyDay = Container(name='emptyDay', parent=self.sr.day, align=uiconst.TOALL, pos=(0, 0, 0, 0), clipChildren=1)
    646         self.sr.emptyDay.state = uiconst.UI_NORMAL
    647         self.sr.dayNumberCont.OnDblClick = self.OnDblClickDay
    648         self.sr.dayNumberCont.OnMouseDown = self.OnMouseClickDay
    649         self.sr.dayNumberCont.GetMenu = self.GetMenu
    650         self.sr.emptyDay.OnDblClick = self.OnDblClickDay
    651         self.sr.emptyDay.OnMouseDown = self.OnMouseClickDay
    652         self.sr.emptyDay.GetMenu = self.GetMenu
    653         self.sr.fill.SetOrder(-1)
    654         self.sr.todayFill.SetOrder(-1)
    655 
    656     def AddMoreContFill(self, *args):
    657         icon = eveIcon.Icon(icon='ui_38_16_229', parent=self.sr.moreCont, pos=(0, -3, 16, 16), align=uiconst.CENTERTOP, idx=0, ignoreSize=True)
    658         icon.OnClick = self.OnMoreClick
    659 
    660     def AddFill(self, *args):
    661         self.sr.fill = FillThemeColored(parent=self, padding=1, colorType=uiconst.COLORTYPE_UIHILIGHT, opacity=0.5)
    662 
    663     def AddFrame(self, *args):
    664         self.sr.frame = FrameThemeColored(parent=self, name='frame', frameConst=uiconst.FRAME_BORDER1_CORNER0, colorType=uiconst.COLORTYPE_UIHILIGHT, opacity=0.1)
    665         self.sr.todayFill = Frame(parent=self, name='todayFill', frameConst=uiconst.FRAME_FILLED_CORNER0, padding=(1, 1, 1, 1), color=(0.5, 0.5, 0.5, 0.75))
    666         self.sr.selectedFrame = Frame(parent=self, name='frame', frameConst=uiconst.FRAME_BORDER1_CORNER0, color=(0.5, 0.5, 0.5, 0.1), padding=(1, 1, 1, 1), state=uiconst.UI_HIDDEN)
    667 
    668     def AddDayNumber(self, text = '', *args):
    669         if self.sr.Get('dayNumberText', None) is None:
    670             self.sr.dayNumberText = eveLabel.EveLabelMedium(text=text, parent=self.sr.dayNumberCont, state=uiconst.UI_DISABLED, left=1, align=uiconst.TOPRIGHT)
    671         return self.sr.dayNumberText
    672 
    673     def SetDayNumber(self, text = None, *args):
    674         self.AddDayNumber()
    675         if text is not None:
    676             text = localization.formatters.FormatNumeric(text, decimalPlaces=0)
    677             self.sr.dayNumberText.text = text
    678 
    679     def SetDayInfo(self, year, month, monthday = 0, *args):
    680         self.year = year
    681         self.month = month
    682         self.monthday = monthday
    683 
    684     def SetDay(self, year, month, monthday = 0, notInMonth = 0, today = False):
    685         self.SetDayNumber(text=monthday)
    686         self.ChangeDayVisibility(disabled=notInMonth)
    687         self.ClearDay()
    688         self.SetDayInfo(year, month, monthday=monthday)
    689         self.SetTodayMarker(today=today)
    690 
    691     def ChangeDayVisibility(self, disabled = 1, *args):
    692         self.disabled = disabled
    693         self.SetFillState(visible=not disabled)
    694         self.SetFrameState(visible=disabled)
    695         self.SetDayVisibility(visible=not disabled)
    696 
    697     def SetFrameState(self, visible = 1):
    698         self.sr.frame.SetAlpha([0.0, 0.4][bool(visible)])
    699 
    700     def SetFillState(self, visible = 1):
    701         self.sr.fill.state = [uiconst.UI_HIDDEN, uiconst.UI_DISABLED][bool(visible)]
    702 
    703     def SetDayVisibility(self, visible = 1):
    704         self.sr.day.opacity = [0.4, 1.0][bool(visible)]
    705 
    706     def SetTodayMarker(self, today = False, *args):
    707         self.sr.todayFill.state = [uiconst.UI_HIDDEN, uiconst.UI_DISABLED][today == True]
    708 
    709     def GetMenu(self, *args):
    710         return self.GetMenuFunction(*args)
    711 
    712     def GetMenuFunction(self, *args):
    713         m = []
    714         if self.disabled:
    715             return m
    716         if not sm.GetService('calendar').IsInPast(self.year, self.month, self.monthday, allowToday=1):
    717             m += [(MenuLabel('/Carbon/UI/Calendar/CreateNewEvent'), self.OpenNewEventWnd)]
    718         if not self.disabled:
    719             m += [(MenuLabel('/Carbon/UI/Calendar/ViewDay'), self.OpenSingleDayWnd)]
    720         return m
    721 
    722     def SetSelectedFrameState(self, on = 0):
    723         self.sr.selectedFrame.state = [uiconst.UI_HIDDEN, uiconst.UI_DISABLED][on]
    724 
    725     def OnMouseClickDay(self, *args):
    726         self.DoClickDay(self)
    727 
    728     def DoClickDay(self, object):
    729         self.SetSelectedFrameState(on=1)
    730 
    731     def OnDblClickDay(self, *args):
    732         self.DoDblClickDay(self)
    733 
    734     def DoDblClickDay(self, day, *args):
    735         self.OpenSingleDayWnd()
    736 
    737     def OpenNewEventWnd(self, *args):
    738         sm.GetService('calendar').OpenNewEventWnd(self.year, self.month, self.monthday)
    739 
    740     def OpenSingleDayWnd(self, *args):
    741         sm.GetService('calendar').OpenSingleDayWnd('day', self.year, self.month, self.monthday, self.events)
    742 
    743     def ClearDay(self, *args):
    744         self.events = {}
    745         self.CheckEventsClipped()
    746         self.sr.emptyDay.Flush()
    747 
    748     def LoadEvents(self, eventsThisDay, *args):
    749         self.sr.emptyDay.Flush()
    750         self.events = {}
    751         toSort = [ ((eventKV.eventTimeStamp, eventKV.eventTitle), eventKV) for eventKV in eventsThisDay.values() ]
    752         eventsKVs = SortListOfTuples(toSort)
    753         for eventInfo in eventsKVs:
    754             onDblClick = (self.OpenEvent, eventInfo)
    755             iconPath, response = sm.GetService('calendar').GetMyResponseIconFromID(eventInfo.eventID, long=1)
    756             if response == const.eventResponseDeleted or response == const.eventResponseDeclined and not settings.user.ui.Get('calendar_showDeclined', 1):
    757                 continue
    758             tagIcon = self.GetTagIcon(eventInfo.flag)
    759             entry = CalendarEventEntry(name='calendarEventEntry', parent=self.sr.emptyDay, align=uiconst.TOTOP, pos=(0,
    760              0,
    761              0,
    762              self.eventHeight), padding=(1, 1, 1, 0), state=uiconst.UI_NORMAL, eventInfo=eventInfo, onDblClick=onDblClick, responseIconPath=iconPath, tagIcon=tagIcon, response=response)
    763             entry.MenuFunction = self.GetEventMenu
    764             self.events[eventInfo.eventID] = eventInfo
    765 
    766         self.CheckEventsClipped()
    767 
    768     def GetTagIcon(self, tag):
    769         tagIcon = sm.GetService('calendar').LoadTagIcon(tag)
    770         return tagIcon
    771 
    772     def GetEventMenu(self, entry, *args):
    773         eventInfo = entry.eventInfo
    774         m = sm.GetService('calendar').GetEventMenu(eventInfo, entry.response, getJumpOption=False)
    775         return m
    776 
    777     def OpenEvent(self, eventInfo, *args):
    778         sm.GetService('calendar').OpenEventWnd(eventInfo)
    779 
    780     def CheckEventsClipped(self, *args):
    781         numEvents = len(self.events)
    782         if numEvents < 1:
    783             self.sr.moreCont.state = uiconst.UI_HIDDEN
    784             return
    785         totalEntryHeight = numEvents * (self.eventHeight + 1)
    786         l, t, w, h = self.sr.emptyDay.GetAbsolute()
    787         moreHeight = 0
    788         if self.sr.moreCont.state != uiconst.UI_HIDDEN:
    789             moreHeight = self.sr.moreCont.height
    790         if totalEntryHeight > h + moreHeight:
    791             self.sr.moreCont.state = uiconst.UI_PICKCHILDREN
    792         else:
    793             self.sr.moreCont.state = uiconst.UI_HIDDEN
    794 
    795     def OnMoreClick(self, *args):
    796         sm.GetService('calendar').OpenSingleDayWnd('day', self.year, self.month, self.monthday, self.events)
    797 
    798 
    799 class CalendarHeader(Container):
    800     default_left = 0
    801     default_top = 0
    802     default_width = 256
    803     default_height = 256
    804     default_name = 'CalendarHeader'
    805     default_charID = None
    806 
    807     def ApplyAttributes(self, attributes):
    808         Container.ApplyAttributes(self, attributes)
    809         self.Prepare_()
    810 
    811     def Prepare_(self, *args):
    812         self.sr.dayNameCont = Container(name='dayNameCont', parent=self, align=uiconst.TOALL, pos=(0, 0, 0, 0))
    813         self.AddDayNameText()
    814 
    815     def AddDayNameText(self, text = '', *args):
    816         if self.sr.Get('dayNameText', None) is None:
    817             self.sr.dayNameText = EveLabelSmall(text=text, parent=self.sr.dayNameCont, state=uiconst.UI_NORMAL, align=uiconst.CENTERBOTTOM)
    818         return self.sr.dayNameText
    819 
    820     def SetDayName(self, text = None, *args):
    821         self.AddDayNameText()
    822         if text is not None:
    823             self.sr.dayNameText.text = text
    824 
    825 
    826 class CalendarEventEntry(Container):
    827 
    828     def ApplyAttributes(self, attributes):
    829         Container.ApplyAttributes(self, attributes)
    830         self.eventInfo = getattr(attributes, 'eventInfo', None)
    831         self.response = getattr(attributes, 'response', None)
    832         if self.eventInfo is not None:
    833             tagIcon = attributes.get('tagIcon', None)
    834             myResponse = attributes.get('response', None)
    835             time = self.eventInfo.eventTimeStamp
    836             title = self.eventInfo.eventTitle
    837             if settings.user.ui.Get('calendar_showTimestamp', 1):
    838                 if getattr(self.eventInfo, 'importance', None) > 0:
    839                     text = localization.GetByLabel('/Carbon/UI/Calendar/EventTitleWithTimeImportant', timeStamp=time, eventTitle=title)
    840                 else:
    841                     text = localization.GetByLabel('/Carbon/UI/Calendar/EventTitleWithTime', timeStamp=time, eventTitle=title)
    842             elif getattr(self.eventInfo, 'importance', None) > 0:
    843                 text = localization.GetByLabel('/Carbon/UI/Calendar/EventTitleImportant', eventTitle=title)
    844             else:
    845                 text = localization.GetByLabel('/Carbon/UI/Calendar/EventTitle', eventTitle=title)
    846             hint = sm.GetService('calendar').GetEventHint(self.eventInfo, myResponse)
    847             responseIconPath = attributes.get('responseIconPath', None)
    848         else:
    849             text = ''
    850             tagIcon = None
    851             responseIconPath = None
    852         onDblClick = getattr(attributes, 'onDblClick', None)
    853         if onDblClick is not None:
    854             self.OnDblClick = onDblClick
    855         self.Prepare_(text, tagIcon, responseIconPath, hint)
    856 
    857     def Prepare_(self, text = '', tagIcon = None, responseIconPath = None, hint = '', *args):
    858         self.clipChildren = 1
    859         self.AddLabel(text)
    860         self.height = 14
    861         self.AddIconCont(responsePath=responseIconPath, tagIcon=tagIcon)
    862         self.AddFill()
    863         self.hint = hint
    864 
    865     def AddLabel(self, text, *args):
    866         self.sr.label = eveLabel.EveLabelSmall(text=text, parent=self, left=14, top=0, state=uiconst.UI_DISABLED, color=None, align=uiconst.CENTERLEFT, maxLines=1)
    867 
    868     def AddFill(self, *args):
    869         self.sr.fill = Frame(parent=self, name='fill', frameConst=uiconst.FRAME_FILLED_SHADOW_CORNER0, color=(1.0, 1.0, 1.0, 0.05))
    870         self.sr.hilite = Frame(parent=self, name='hilite', frameConst=uiconst.FRAME_FILLED_SHADOW_CORNER0, pos=(1, 1, 0, 0), color=(1.0, 1.0, 1.0, 0.25), state=uiconst.UI_HIDDEN)
    871 
    872     def AddIconCont(self, responsePath = None, tagIcon = None, *args):
    873         self.sr.tagCont = Container(name='statusCont', parent=self, align=uiconst.TOPRIGHT, pos=(0, 2, 14, 14), state=uiconst.UI_DISABLED, idx=0)
    874         self.sr.tagCont.autoPos = uiconst.AUTOPOSYCENTER
    875         self.sr.responseCont = Container(name='responseCont', parent=self, align=uiconst.TOPLEFT, pos=(1, 0, 10, 14), state=uiconst.UI_DISABLED)
    876         if tagIcon is not None:
    877             self.SetTag(tagIcon)
    878         self.SetStatus(self.sr.responseCont, responsePath)
    879 
    880     def SetStatus(self, cont, iconPath = None):
    881         cont.Flush()
    882         if iconPath:
    883             Icon(icon=iconPath, parent=cont, align=uiconst.CENTER, pos=(0, 0, 16, 16))
    884 
    885     def SetTag(self, tagIcon):
    886         self.sr.tagCont.Flush()
    887         self.sr.tagCont.children.append(tagIcon)
    888 
    889     def GetMenu(self):
    890         return self.MenuFunction(self)
    891 
    892     def MenuFunction(self, entry, *args):
    893         return []
    894 
    895     def OnMouseEnter(self, *args):
    896         if GetAttrs(self, 'sr', 'hilite'):
    897             self.sr.hilite.state = uiconst.UI_DISABLED
    898 
    899     def OnMouseExit(self, *args):
    900         if GetAttrs(self, 'sr', 'hilite'):
    901             self.sr.hilite.state = uiconst.UI_HIDDEN
    902 
    903 
    904 class CalendarNewEventWnd(Window):
    905     __guid__ = 'form.CalendarNewEventWnd'
    906     __notifyevents__ = ['OnRespondToEvent', 'OnRemoveCalendarEvent']
    907     default_iconNum = 'res:/ui/Texture/WindowIcons/calendar.png'
    908     default_minSize = (530, 370)
    909     default_height = 460
    910 
    911     def ApplyAttributes(self, attributes):
    912         super(CalendarNewEventWnd, self).ApplyAttributes(attributes)
    913         sm.RegisterNotify(self)
    914         year = attributes.year
    915         month = attributes.month
    916         monthday = attributes.monthday
    917         eventInfo = attributes.eventInfo
    918         edit = attributes.edit or False
    919         self.buttonGroup = None
    920         now = blue.os.GetWallclockTime()
    921         cyear, cmonth, cwd, cday, chour, cmin, csec, cms = GetTimeParts(now)
    922         if year is None or month is None:
    923             year = cyear
    924             month = cmonth
    925         if (year, month, monthday) == (cyear, cmonth, cday):
    926             year, month, monthday, hour = self.FindTimeToUse(year, month, monthday, chour)
    927         else:
    928             hour = 12
    929         self.year = year
    930         self.month = month
    931         self.monthday = monthday
    932         self.hour = hour
    933         self.min = 0
    934         self.configname = '%s_%s_%s' % (year, month, monthday)
    935         self.invitees = None
    936         self.oldInvitees = None
    937         self.inEditMode = False
    938         self.sr.infoCont = ContainerAutoSize(name='infoCont', parent=self.sr.main, align=uiconst.TOTOP, alignMode=uiconst.TOTOP)
    939         self.sr.tabCont = Container(name='tabCont', parent=self.sr.main, align=uiconst.TOALL, pos=(0, 0, 0, 0))
    940         self.sr.eventDescrCont = Container(name='invitedScroll', parent=self.sr.tabCont, align=uiconst.TOALL, pos=(0, 0, 0, 0))
    941         self.sr.invitedCont = Container(name='invitedScroll', parent=self.sr.tabCont, align=uiconst.TOALL, pos=(0, 0, 0, 0))
    942         subtabs = [[localization.GetByLabel('UI/Calendar/EventWindow/TabDescription'),
    943           self.sr.eventDescrCont,
    944           self,
    945           'descr']]
    946         flag = GetAttrs(eventInfo, 'flag')
    947         if flag is None or flag == const.calendarTagPersonal:
    948             subtabs.append([localization.GetByLabel('UI/Calendar/EventWindow/TabInvitations'),
    949              self.sr.invitedCont,
    950              self,
    951              'invitations'])
    952         elif flag in [const.calendarTagCorp, const.calendarTagAlliance] and session.corpid and session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
    953             subtabs.append([localization.GetByLabel('UI/Calendar/EventWindow/TabInvitations'),
    954              self.sr.invitedCont,
    955              self,
    956              'invitations'])
    957         self.sr.tabs = TabGroup(name='tabs', parent=self.sr.tabCont, idx=0, tabs=subtabs, groupID='calenderEvent_tabs', autoselecttab=0)
    958         self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Calendar/EventWindow/TabDescription'))
    959         invTab = self.sr.tabs.sr.Get('%s_tab' % localization.GetByLabel('UI/Calendar/EventWindow/TabInvitations'), None)
    960         if invTab is not None:
    961             invTab.OnTabDropData = self.OnDropData
    962         if eventInfo is not None:
    963             eventDetails = sm.GetService('calendar').GetEventDetails(eventInfo.eventID, eventInfo.ownerID)
    964             self.eventID = eventInfo.eventID
    965             self.title = eventInfo.eventTitle
    966             self.descr = eventDetails.eventText
    967             self.creatorID = eventDetails.creatorID
    968             self.duration = eventInfo.eventDuration
    969             self.importance = eventInfo.importance
    970             self.eventTag = eventInfo.flag
    971             self.cbChecked = self.eventTag
    972             self.eventInfo = eventInfo
    973             self.year, self.month, cwd, self.monthdayday, self.hour, self.min, sec, ms = blue.os.GetTimeParts(eventInfo.eventDateTime)
    974             if edit:
    975                 self.SetupCreateControls(new=not edit)
    976             else:
    977                 self.SetupReadOnlyElements()
    978         else:
    979             self.eventID = None
    980             self.title = ''
    981             self.descr = ''
    982             self.creatorID = None
    983             self.duration = 0
    984             self.importance = 0
    985             self.eventTag = const.calendarTagPersonal
    986             self.cbChecked = const.calendarTagPersonal
    987             self.eventInfo = None
    988             self.SetupCreateControls()
    989 
    990     def Load(self, key, *args):
    991         if key == 'invitations':
    992             self.LoadInviteeTabScroll()
    993 
    994     def LoadInviteeTabScroll(self, *args):
    995         if getattr(self, 'eventID', None) is None:
    996             tag = self.cbChecked
    997         else:
    998             tag = self.eventTag
    999         if tag == const.calendarTagCCP:
   1000             return
   1001         if self.inEditMode:
   1002             if tag in (const.calendarTagCorp, const.calendarTagAutomated):
   1003                 self.LoadCorpAllianceInScroll(session.corpid)
   1004                 return
   1005             if tag == const.calendarTagAlliance:
   1006                 self.LoadCorpAllianceInScroll(session.allianceid)
   1007                 return
   1008         self.LoadInviteeScroll()
   1009 
   1010     def SetupCreateControls(self, new = 1, *args):
   1011         self.inEditMode = True
   1012         left = 6
   1013         top = 20
   1014         thisDay = [self.year,
   1015          self.month,
   1016          self.monthday,
   1017          self.hour,
   1018          self.min]
   1019         self.sr.infoCont.Flush()
   1020         self.sr.infoCont.clipChildren = True
   1021         if self.buttonGroup:
   1022             self.buttonGroup.Close()
   1023             self.buttonGroup = None
   1024         btns = []
   1025         if new:
   1026             caption = localization.GetByLabel('UI/Calendar/EventWindow/CaptionNew')
   1027             btns.append([localization.GetByLabel('UI/Calendar/EventWindow/Create'),
   1028              self.CreateOrEditEvent,
   1029              (1,),
   1030              None])
   1031         else:
   1032             caption = localization.GetByLabel('UI/Calendar/EventWindow/CaptionEdit')
   1033             btns.append([localization.GetByLabel('UI/Calendar/EventWindow/Save'),
   1034              self.CreateOrEditEvent,
   1035              (0,),
   1036              None])
   1037         btns.append([localization.GetByLabel('UI/Generic/Cancel'),
   1038          self.CloseByUser,
   1039          (),
   1040          None])
   1041         self.buttonGroup = ButtonGroup(btns=btns, parent=self.sr.main, idx=0)
   1042         self.SetCaption(caption)
   1043         label = eveLabel.EveLabelSmall(text=localization.GetByLabel('UI/Calendar/SingleDayWindow/Title'), parent=self.sr.infoCont, align=uiconst.TOTOP, padding=(const.defaultPadding,
   1044          const.defaultPadding,
   1045          const.defaultPadding,
   1046          0))
   1047         self.sr.titleEdit = SingleLineEditText(name='titleEdit', parent=self.sr.infoCont, setvalue=self.title, maxLength=const.calendarMaxTitleSize, align=uiconst.TOTOP, padding=(const.defaultPadding,
   1048          0,
   1049          const.defaultPadding,
   1050          const.defaultPadding))
   1051         dateParent = Container(parent=self.sr.infoCont, align=uiconst.TOTOP, padding=(const.defaultPadding,
   1052          label.textheight,
   1053          const.defaultPadding,
   1054          const.defaultPadding), height=100)
   1055         now = blue.os.GetWallclockTime()
   1056         cyear, cmonth, cwd, cday, chour, cmin, csec, cms = GetTimeParts(now)
   1057         yearRange = const.calendarViewRangeInMonths / 12 + 1
   1058         self.sr.fromDate = DatePicker(name='datepicker', parent=dateParent, align=uiconst.TOPLEFT, width=256, height=18, left=0, top=0)
   1059         self.sr.fromDate.Startup(thisDay, True, 4, cyear, yearRange)
   1060         durationOptions = [(localization.GetByLabel('UI/Calendar/EventWindow/DateNotSpecified'), None)]
   1061         for i in xrange(1, 25):
   1062             str = localization.GetByLabel('UI/Calendar/EventWindow/DateSpecified', hours=i)
   1063             durationOptions += [(str, i * 60)]
   1064 
   1065         dLeft = self.sr.fromDate.left + self.sr.fromDate.width + 16
   1066         self.sr.durationCombo = Combo(label=localization.GetByLabel('UI/Calendar/EventWindow/Duration'), parent=dateParent, options=durationOptions, name='duration', select=self.duration, left=dLeft, width=130, align=uiconst.TOPLEFT)
   1067         dateParent.height = max(self.sr.fromDate.height, self.sr.durationCombo.height)
   1068         self.sr.importantCB = Checkbox(text=localization.GetByLabel('UI/Calendar/EventWindow/Important'), parent=self.sr.infoCont, settingsKey='importantCB', checked=self.importance, align=uiconst.TOTOP, padLeft=const.defaultPadding)
   1069         self.radioBtns = []
   1070         if new:
   1071             checkboxes = [(localization.GetByLabel('UI/Calendar/EventWindow/GroupPersonal'),
   1072               'personal',
   1073               const.calendarTagPersonal,
   1074               const.calendarTagPersonal == self.eventTag)]
   1075             if session.corpid and session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
   1076                 checkboxes.append((localization.GetByLabel('UI/Calendar/EventWindow/GroupCorporation'),
   1077                  'corp',
   1078                  const.calendarTagCorp,
   1079                  const.calendarTagCorp == self.eventTag))
   1080             if session.allianceid and session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
   1081                 checkboxes.append((localization.GetByLabel('UI/Calendar/EventWindow/GroupAlliance'),
   1082                  'alliance',
   1083                  const.calendarTagAlliance,
   1084                  const.calendarTagAlliance == self.eventTag))
   1085             for label, config, tag, checked in checkboxes:
   1086                 cb = RadioButton(text=label, parent=self.sr.infoCont, settingsKey=config, retval=tag, checked=checked, align=uiconst.TOTOP, groupname='eventTag', callback=self.TagCheckboxChecked, left=const.defaultPadding)
   1087                 self.radioBtns.append(cb)
   1088 
   1089         else:
   1090             eventTypeH = localization.GetByLabel('UI/Calendar/EventWindow/EventType')
   1091             eventType = sm.GetService('calendar').GetEventTypes().get(self.eventTag, '-')
   1092             if eventType != '-':
   1093                 eventType = localization.GetByLabel(eventType)
   1094             eveLabel.EveHeaderSmall(text=eventTypeH, parent=self.sr.infoCont, name='eventType', align=uiconst.TOTOP, padLeft=const.defaultPadding, state=uiconst.UI_NORMAL)
   1095             eveLabel.EveLabelMedium(text=eventType, parent=self.sr.infoCont, align=uiconst.TOTOP, padLeft=const.defaultPadding, padBottom=const.defaultPadding, state=uiconst.UI_NORMAL)
   1096         self.sr.infoCont.height = sum([ each.height + each.padTop + each.padBottom for each in self.sr.infoCont.children ])
   1097         self.sr.eventDescrCont.Flush()
   1098         readonly = IsContentComplianceControlSystemActive(sm.GetService('machoNet'))
   1099         self.counter = None
   1100         self.counter = EveLabelSmall(text='0/%s' % const.calendarMaxDescrSize, parent=self.sr.eventDescrCont, color=TextColor.SECONDARY, align=uiconst.BOTTOMRIGHT, state=uiconst.UI_NORMAL)
   1101         self.sr.descrEdit = eveEditPlainText.EditPlainText(setvalue=self.descr, parent=self.sr.eventDescrCont, align=uiconst.TOALL, maxLength=const.calendarMaxDescrSize, showattributepanel=False, readonly=readonly, customCounter=self.counter)
   1102         self.sr.invitedCont.Flush()
   1103         self.sr.addIviteeeBtnCont = Container(name='btnCont', parent=self.sr.invitedCont, align=uiconst.TOTOP, pos=None, height=32, state=uiconst.UI_HIDDEN)
   1104         Button(parent=self.sr.addIviteeeBtnCont, label=localization.GetByLabel('UI/Calendar/EventWindow/AddInvitee'), func=self.OpenAddInvteeWnd)
   1105         if new or self.eventTag == const.calendarTagPersonal:
   1106             self.sr.addIviteeeBtnCont.state = uiconst.UI_PICKCHILDREN
   1107         self.AddQuickFilter(self.sr.addIviteeeBtnCont)
   1108         self.sr.inviteScroll = eveScroll.Scroll(name='invitedScroll', parent=self.sr.invitedCont, padding=(0, 8, 0, 0))
   1109         content = self.sr.inviteScroll.sr.content
   1110         content.OnDropData = self.OnDropData
   1111         if self.sr.tabs.GetSelectedArgs() == 'invitations':
   1112             self.LoadInviteeTabScroll()
   1113 
   1114     def TagCheckboxChecked(self, radioButton, *args):
   1115         tag = radioButton.GetReturnValue() or const.calendarTagPersonal
   1116         self.cbChecked = tag
   1117         if tag == const.calendarTagPersonal:
   1118             self.sr.addIviteeeBtnCont.state = uiconst.UI_PICKCHILDREN
   1119             self.LoadInviteeScroll()
   1120         else:
   1121             self.sr.addIviteeeBtnCont.state = uiconst.UI_HIDDEN
   1122             if tag in (const.calendarTagCorp, const.calendarTagAutomated):
   1123                 self.LoadCorpAllianceInScroll(session.corpid)
   1124             elif tag == const.calendarTagAlliance:
   1125                 self.LoadCorpAllianceInScroll(session.allianceid)
   1126 
   1127     def LoadCorpAllianceInScroll(self, entityID, *args):
   1128         if entityID is None:
   1129             return
   1130         owner = cfg.eveowners.GetIfExists(entityID)
   1131         if owner is None:
   1132             return
   1133         if evetypes.Exists(owner.typeID):
   1134             scrolllist = [GetFromClass(User, {'charID': entityID})]
   1135             self.sr.inviteScroll.Load(contentList=scrolllist, headers=[], noContentHint='')
   1136 
   1137     def AddSpacer(self, parent):
   1138         spacer = Container(pos=(0, 0, 0, 4), align=uiconst.TOPLEFT)
   1139         parent.AddCell(cellObject=spacer, colSpan=parent.columns)
   1140         parent.FillRow()
   1141 
   1142     def SetupReadOnlyElements(self, *args):
   1143         left = 8
   1144         top = 6
   1145         firstColumnItems = []
   1146         secondColumnItems = []
   1147         self.SetCaption(localization.GetByLabel('UI/Calendar/EventWindow/CaptionRead'))
   1148         btns = []
   1149         if not sm.GetService('calendar').IsInPastFromBlueTime(then=self.eventInfo.eventDateTime) and not self.eventInfo.isDeleted:
   1150             if self.eventInfo.flag in [const.calendarTagCorp, const.calendarTagAlliance]:
   1151                 self.AddAcceptDeclineBtns(btns)
   1152                 if self.eventInfo.ownerID in [session.corpid, session.allianceid] and session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
   1153                     self.InsertEditDeleteBtns(btns)
   1154             elif self.eventInfo.flag == const.calendarTagPersonal:
   1155                 if self.eventInfo.ownerID != session.charid:
   1156                     self.AddAcceptDeclineBtns(btns)
   1157                 else:
   1158                     self.InsertEditDeleteBtns(btns)
   1159         btns.append([localization.GetByLabel('UI/Generic/Close'),
   1160          self.CloseByUser,
   1161          (),
   1162          None])
   1163         if self.buttonGroup:
   1164             self.buttonGroup.Close()
   1165             self.buttonGroup = None
   1166         self.buttonGroup = ButtonGroup(btns=btns, parent=self.sr.main, idx=0)
   1167         infoCont = Container(name='infoCont', parent=self.sr.infoCont, align=uiconst.TOTOP)
   1168         title = self.title
   1169         if self.importance > 0:
   1170             title = '<color=red>!</color>%s' % title
   1171         caption = eveLabel.EveCaptionMedium(text=title, parent=infoCont, padding=(left,
   1172          top,
   1173          left,
   1174          top), align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
   1175         top += caption.textheight
   1176         self.infoContLayoutGrid = LayoutGrid(parent=infoCont, columns=2, top=top, left=6, cellSpacing=(20, 0))
   1177         startH = localization.GetByLabel('UI/Calendar/EventWindow/StartTime')
   1178         label = eveLabel.EveLabelSmallBold(text=startH, parent=self.infoContLayoutGrid, name='startTime', align=uiconst.TOPLEFT, idx=1, state=uiconst.UI_NORMAL)
   1179         startTime = FmtDate(self.eventInfo.eventDateTime - eveLocalization.GetTimeDelta() * const.SEC, 'ls')
   1180         dataLabel = eveLabel.EveLabelMedium(text=startTime, parent=self.infoContLayoutGrid, state=uiconst.UI_NORMAL)
   1181         eventTypeH = localization.GetByLabel('UI/Calendar/EventWindow/EventType')
   1182         label = eveLabel.EveLabelSmallBold(text=eventTypeH, parent=self.infoContLayoutGrid, name='eventType', align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL)
   1183         eventType = sm.GetService('calendar').GetEventTypes().get(self.eventTag, '-')
   1184         if eventType != '-':
   1185             eventType = localization.GetByLabel(eventType)
   1186         dataLabel2 = eveLabel.EveLabelMedium(text=eventType, parent=self.infoContLayoutGrid, width=200, state=uiconst.UI_NORMAL)
   1187         durationH = localization.GetByLabel('UI/Calendar/EventWindow/Duration')
   1188         label = eveLabel.EveLabelSmallBold(text=durationH, parent=self.infoContLayoutGrid, name='duration', align=uiconst.TOPLEFT, idx=1, state=uiconst.UI_NORMAL)
   1189         if self.eventInfo.eventDuration is None:
   1190             durationLabel = localization.GetByLabel('UI/Calendar/EventWindow/DateNotSpecified')
   1191         else:
   1192             hours = self.eventInfo.eventDuration / 60
   1193             durationLabel = localization.GetByLabel('UI/Calendar/EventWindow/DateSpecified', hours=hours)
   1194         dataLabel = eveLabel.EveLabelMedium(text=durationLabel, parent=self.infoContLayoutGrid, state=uiconst.UI_NORMAL)
   1195         creatorH = localization.GetByLabel('UI/Calendar/EventWindow/Creator')
   1196         creatorInfo = cfg.eveowners.Get(self.creatorID)
   1197         if self.eventTag == const.calendarTagCCP:
   1198             creatorNameText = localization.GetByLabel('UI/Calendar/CalendarWindow/GroupCcp')
   1199         elif self.creatorID == const.ownerSystem:
   1200             creatorNameText = creatorInfo.name
   1201         else:
   1202             showInfoData = ('showinfo', creatorInfo.typeID, self.creatorID)
   1203             creatorNameText = localization.GetByLabel('UI/Calendar/EventWindow/CreatorLink', charID=self.creatorID, showInfoData=showInfoData)
   1204         label = eveLabel.EveLabelSmallBold(text=creatorH, parent=self.infoContLayoutGrid, name='eventType', align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL)
   1205         dataLabel2 = eveLabel.EveLabelMedium(text=creatorNameText, parent=self.infoContLayoutGrid, state=uiconst.UI_NORMAL)
   1206         iconPath, myResponse = sm.GetService('calendar').GetMyResponseIconFromID(self.eventID, long=1, getDeleted=self.eventInfo.isDeleted)
   1207         response = localization.GetByLabel(sm.GetService('calendar').GetResponseType().get(myResponse, 'UI/Generic/Unknown'))
   1208         statusH = localization.GetByLabel('UI/Calendar/EventWindow/Status')
   1209         label = eveLabel.EveLabelSmallBold(text=statusH, parent=self.infoContLayoutGrid, name='status', align=uiconst.TOPLEFT, idx=1, state=uiconst.UI_NORMAL)
   1210         autosizeCont = ContainerAutoSize(name='autosizeCont', parent=self.infoContLayoutGrid, alignMode=uiconst.TOPLEFT)
   1211         self.sr.reponseText = eveLabel.EveLabelMedium(text=response, parent=autosizeCont, state=uiconst.UI_NORMAL, left=20)
   1212         if iconPath:
   1213             eveIcon.Icon(icon=iconPath, parent=autosizeCont, align=uiconst.CENTERLEFT, pos=(0, 0, 16, 16))
   1214         updateH = localization.GetByLabel('UI/Calendar/EventWindow/LastUpdated')
   1215         label = eveLabel.EveLabelSmallBold(text=updateH, parent=self.infoContLayoutGrid, name='updated', align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL)
   1216         updateTime = FmtDate(self.eventInfo.dateModified, 'ls')
   1217         dataLabel2 = eveLabel.EveLabelMedium(text=updateTime, parent=self.infoContLayoutGrid, width=200, state=uiconst.UI_NORMAL)
   1218         self.infoContLayoutGrid.RefreshGridLayout()
   1219         w, h = self.infoContLayoutGrid.GetSize()
   1220         infoCont.height = h + self.infoContLayoutGrid.top + 2
   1221         descr = self.descr
   1222         self.sr.descrEdit = eveEditPlainText.EditPlainText(setvalue=descr, parent=self.sr.eventDescrCont, align=uiconst.TOALL, maxLength=1000, padding=const.defaultPadding, readonly=1)
   1223         self.sr.invitedCont.Flush()
   1224         self.sr.searchCont = Container(name='searchCont', parent=self.sr.invitedCont, align=uiconst.TOTOP, pos=(0, 0, 0, 26))
   1225         self.AddQuickFilter(self.sr.searchCont)
   1226         if self.eventTag in [const.calendarTagCCP, const.calendarTagAutomated]:
   1227             self.sr.searchCont.state = uiconst.UI_HIDDEN
   1228         elif self.eventTag in [const.calendarTagCorp, const.calendarTagAlliance] and session.corpid and not session.corprole & const.corpRoleChatManager == const.corpRoleChatManager:
   1229             self.sr.searchCont.state = uiconst.UI_HIDDEN
   1230         self.sr.inviteScroll = eveScroll.Scroll(name='invitedScroll', parent=self.sr.invitedCont, padding=const.defaultPadding)
   1231 
   1232     def InsertEditDeleteBtns(self, btns, top = 6, *args):
   1233         editDeleteCont = ContainerAutoSize(name='editCont', parent=self.sr.infoCont, align=uiconst.TORIGHT)
   1234         editBtn = Button(parent=editDeleteCont, label=localization.GetByLabel('UI/Calendar/EventWindow/Edit'), func=self.ChangeToEditMode, align=uiconst.TOTOP, padBottom=8)
   1235         deleteBtn = Button(parent=editDeleteCont, label=localization.GetByLabel('UI/Calendar/EventWindow/Delete'), func=self.Delete, align=uiconst.TOTOP)
   1236         editBtn.width = deleteBtn.width = max(editBtn.width, deleteBtn.width)
   1237         editDeleteCont.width = 4 + editBtn.width
   1238 
   1239     def AddAcceptDeclineBtns(self, btns):
   1240         iconPath, myResponse = sm.GetService('calendar').GetMyResponseIconFromID(self.eventID)
   1241         if myResponse != const.eventResponseAccepted:
   1242             btns.insert(0, [localization.GetByLabel('/Carbon/UI/Calendar/Accept'),
   1243              self.RespondToEvent,
   1244              (const.eventResponseAccepted,),
   1245              None])
   1246         if myResponse != const.eventResponseMaybe:
   1247             btns.insert(1, [localization.GetByLabel('/Carbon/UI/Calendar/MaybeReply'),
   1248              self.RespondToEvent,
   1249              (const.eventResponseMaybe,),
   1250              None])
   1251         if myResponse != const.eventResponseDeclined:
   1252             btns.insert(2, [localization.GetByLabel('/Carbon/UI/Calendar/Decline'),
   1253              self.RespondToEvent,
   1254              (const.eventResponseDeclined,),
   1255              None])
   1256 
   1257     def AddQuickFilter(self, cont, *args):
   1258         self.sr.searchBox = QuickFilterEdit(name='searchBox', parent=cont, setvalue='', maxLength=37, align=uiconst.TOPRIGHT, isCharacterField=True)
   1259         self.sr.searchBox.ReloadFunction = self.LoadInviteeScroll
   1260 
   1261     def OpenAddInvteeWnd(self, *args):
   1262         actionBtn = [(localization.GetByLabel('UI/Calendar/FindInviteesWindow/Add'), self.AddInviteeToEvent, 1)]
   1263         caption = localization.GetByLabel('UI/Calendar/FindInviteesWindow/Caption')
   1264         OwnerSearchWindow.CloseIfOpen(windowID='searchWindow_calendar')
   1265         extraIconHintFlag = ['ui_73_16_13', localization.GetByLabel('UI/Calendar/Hints/CharacterAdded'), False]
   1266         wnd = OwnerSearchWindow.Open(windowID='searchWindow_calendar', actionBtns=actionBtn, caption=caption, input='', getMyCorp=False, getMyLists=False, getMyAlliance=False, showContactList=True, extraIconHintFlag=extraIconHintFlag, configname=self.configname, ownerGroups=[const.groupCharacter])
   1267         wnd.ExtraMenuFunction = self.InviteeMenuFunction
   1268         wnd.IsAdded = self.CheckIfAdded
   1269 
   1270     def CheckIfAdded(self, contactID):
   1271         if self.invitees is None:
   1272             self.PopulateInviteeDicts(self.eventID)
   1273         return contactID in self.invitees
   1274 
   1275     def AddInviteeToEvent(self, func, *args):
   1276         if self.inEditMode is False:
   1277             return
   1278         if not self or self.destroyed:
   1279             return
   1280         sel = apply(func)
   1281         selIDs = [ each.charID for each in sel ]
   1282         self.AddInvitees(selIDs)
   1283 
   1284     def AddInvitees(self, charIDList):
   1285         if self.inEditMode is False:
   1286             return
   1287         if self.invitees is None:
   1288             self.PopulateInviteeDicts(self.eventID)
   1289         for charID in charIDList:
   1290             if charID == session.charid or charID is None:
   1291                 continue
   1292             if len(self.invitees) >= const.calendarMaxInvitees:
   1293                 prompt_player_fsd_dialog('CustomInfo', {'info': localization.GetByLabel('UI/Calendar/FindInviteesWindow/TooMany', max=const.calendarMaxInvitees)})
   1294                 break
   1295             if charID not in self.invitees:
   1296                 self.invitees[charID] = const.eventResponseUndecided
   1297                 sm.ScatterEvent('OnSearcedUserAdded', charID, self.configname)
   1298 
   1299         self.LoadInviteeScroll()
   1300 
   1301     def LoadInviteeScroll(self, *args):
   1302         filter = self.sr.searchBox.GetValue()
   1303         if len(filter) >= 2:
   1304             bannedwords.check_search_words_allowed(filter)
   1305             return self.SearchInvitee()
   1306         if self.invitees is None:
   1307             self.PopulateInviteeDicts(self.eventID)
   1308         responseDict = sm.GetService('calendar').GetResponsesToEventInStatusDict(self.eventID, self.invitees)
   1309         scrolllist = []
   1310         responseCategoryList = [const.eventResponseAccepted, const.eventResponseMaybe, const.eventResponseDeclined]
   1311         if self.eventTag == const.calendarTagPersonal:
   1312             responseCategoryList.insert(-1, const.eventResponseUndecided)
   1313         for response in responseCategoryList:
   1314             label = localization.GetByLabel(sm.GetService('calendar').GetResponseType().get(response, 'UI/Generic/Unknown'))
   1315             scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetResponseSubContent,
   1316              'label': label,
   1317              'cleanLabel': label,
   1318              'id': ('calendarInvitees', response),
   1319              'state': 'locked',
   1320              'BlockOpenWindow': 1,
   1321              'showicon': sm.GetService('calendar').GetResponseIconNum(response),
   1322              'showlen': 1,
   1323              'groupName': 'labels',
   1324              'groupItems': responseDict[response],
   1325              'noItemText': localization.GetByLabel('UI/Calendar/EventWindow/NoCharacter'),
   1326              'response': response,
   1327              'DropData': self.DropUserOnGroup,
   1328              'allowGuids': ['listentry.User', 'listentry.Sender', 'listentry.ChatUser']}))
   1329 
   1330         self.sr.inviteScroll.Load(contentList=scrolllist, headers=[], noContentHint='')
   1331 
   1332     def GetResponseSubContent(self, data, *args):
   1333         response = data.response
   1334         scrolllist = []
   1335         if len(data.groupItems) > const.calendarMaxInviteeDisplayed:
   1336             if response == const.eventResponseDeclined:
   1337                 label = localization.GetByLabel('UI/Calendar/EventWindow/TooManyDeclined', max=const.calendarMaxInviteeDisplayed)
   1338             else:
   1339                 label = localization.GetByLabel('UI/Calendar/EventWindow/TooManyAccepted', max=const.calendarMaxInviteeDisplayed)
   1340             return [GetFromClass(Generic, {'label': label,
   1341               'sublevel': 1})]
   1342         cfg.eveowners.Prime(data.groupItems)
   1343         for charID in data.groupItems:
   1344             if response == const.eventResponseUninvited:
   1345                 continue
   1346             charinfo = cfg.eveowners.Get(charID)
   1347             entry = GetFromClass(User, {'charID': charID,
   1348              'MenuFunction': self.InviteeMenuFunction})
   1349             scrolllist.append((charinfo.name.lower(), entry))
   1350 
   1351         scrolllist = SortListOfTuples(scrolllist)
   1352         return scrolllist
   1353 
   1354     def InviteeMenuFunction(self, nodes, *args):
   1355         m = []
   1356         if self.inEditMode is False:
   1357             return m
   1358         if self.invitees is None:
   1359             self.PopulateInviteeDicts(self.eventID)
   1360         charIDs = [ node.charID for node in nodes if node.charID in self.invitees ]
   1361         if session.charid in charIDs:
   1362             charIDs.remove(session.charid)
   1363         numCharIDs = len(charIDs)
   1364         if numCharIDs > 0:
   1365             label = localization.GetByLabel('UI/Calendar/EventWindow/RemoveInvitee', num=numCharIDs)
   1366             m = [(label, self.RemoveInviteeFromScroll, (charIDs,))]
   1367         return m
   1368 
   1369     def RemoveInviteeFromScroll(self, charIDs):
   1370         if self.inEditMode is False:
   1371             return
   1372         if self.invitees is None:
   1373             self.PopulateInviteeDicts(self.eventID)
   1374         for charID in charIDs:
   1375             self.invitees.pop(charID, None)
   1376 
   1377         sm.ScatterEvent('OnSearcedUserRemoved', charIDs, self.configname)
   1378         self.LoadInviteeScroll()
   1379 
   1380     def ChangeToEditMode(self, *args):
   1381         self.FlushAll()
   1382         if self.invitees is None:
   1383             self.PopulateInviteeDicts(self.eventID)
   1384         self.oldInvitees = self.invitees.copy()
   1385         self.SetupCreateControls(new=0)
   1386 
   1387     def FlushAll(self, *args):
   1388         self.sr.infoCont.Flush()
   1389         self.sr.eventDescrCont.Flush()
   1390         self.sr.invitedCont.Flush()
   1391         if self.buttonGroup:
   1392             self.buttonGroup.Close()
   1393             self.buttonGroup = None
   1394 
   1395     def FindTimeToUse(self, year, month, day, hour):
   1396         firstDay, lastDay = calendar.monthrange(year, month)
   1397         hour = hour + 1
   1398         if hour > 23:
   1399             hour = 0
   1400             day = day + 1
   1401         if day > lastDay:
   1402             day = 1
   1403             month += 1
   1404         if month > const.calendarDecember:
   1405             month = const.calendarJanuary
   1406             year = year + 1
   1407         return (year,
   1408          month,
   1409          day,
   1410          hour)
   1411 
   1412     def CreateOrEditEvent(self, create = 1, *args):
   1413         if getattr(self, 'editing', 0):
   1414             return
   1415         self.editing = 1
   1416         try:
   1417             eventTag = self.radioBtns[0].GetGroupValue() if self.radioBtns else 0
   1418             if eventTag == 0:
   1419                 eventTag = self.eventTag
   1420             descr = self.sr.descrEdit.GetValue()
   1421             title = self.sr.titleEdit.GetValue()
   1422             fromDate = self.sr.fromDate.GetValue()
   1423             duration = self.sr.durationCombo.GetValue()
   1424             important = self.sr.importantCB.checked
   1425             cyear, cmonth, cwd, cday, chour, cmin, csec, cms = blue.os.GetTimeParts(fromDate + eveLocalization.GetTimeDelta() * const.SEC)
   1426             if sm.GetService('calendar').IsInPast(cyear, cmonth, cday, chour, cmin):
   1427                 raise UserError('CalendarCannotPlanThePast')
   1428             if create:
   1429                 if self.invitees is None:
   1430                     self.PopulateInviteeDicts(self.eventID)
   1431                 newInviteeCharIDs = self.invitees.keys()
   1432                 sm.GetService('calendar').CreateNewEvent(fromDate, duration, title, descr, eventTag, important, invitees=newInviteeCharIDs)
   1433             else:
   1434                 if self.invitees is None:
   1435                     self.PopulateInviteeDicts(self.eventID)
   1436                 newInviteeCharIDs = [ charID for charID in self.invitees.keys() if charID not in self.oldInvitees.keys() ]
   1437                 removedInviteeCharIDs = [ charID for charID in self.oldInvitees.keys() if charID not in self.invitees.keys() ]
   1438                 wasEdited = sm.GetService('calendar').EditEvent(self.eventID, self.eventInfo.eventDateTime, fromDate, duration, title, descr, eventTag, important)
   1439                 if not wasEdited:
   1440                     return
   1441                 if len(newInviteeCharIDs) + len(removedInviteeCharIDs) > 0:
   1442                     sm.GetService('calendar').UpdateEventParticipants(self.eventID, newInviteeCharIDs, removedInviteeCharIDs)
   1443         finally:
   1444             self.editing = 0
   1445 
   1446         sm.ScatterEvent('OnReloadEvents')
   1447         self.CloseByUser()
   1448 
   1449     def RespondToEvent(self, response, *args):
   1450         sm.GetService('calendar').RespondToEvent(self.eventID, self.eventInfo, response)
   1451 
   1452     def Delete(self, *args):
   1453         sm.GetService('calendar').DeleteEvent(self.eventID, self.eventInfo.ownerID)
   1454 
   1455     def Cancel(self, *args):
   1456         self.CloseByUser()
   1457 
   1458     def OnDropData(self, dragObj, nodes, *args):
   1459         toAdd = []
   1460         for node in nodes:
   1461             if node.__guid__ in ('listentry.User', 'listentry.Sender', 'listentry.ChatUser', 'listentry.SearchedUser') and node.IsCharacter and not IsNPC(node.itemID):
   1462                 toAdd.append(node.itemID)
   1463 
   1464         if len(toAdd) > 0:
   1465             self.AddInvitees(toAdd)
   1466 
   1467     def DropUserOnGroup(self, groupID, nodes, *args):
   1468         self.OnDropData(None, nodes)
   1469 
   1470     def _OnClose(self, *args):
   1471         wnd = OwnerSearchWindow.GetIfOpen(windowID='searchWindow_calendar')
   1472         if wnd and wnd.configname == self.configname:
   1473             wnd.CloseByUser()
   1474 
   1475     def SearchInvitee(self, *args):
   1476         if self.invitees is None:
   1477             self.PopulateInviteeDicts(self.eventID)
   1478         cfg.eveowners.Prime(self.invitees.keys())
   1479         matched = NiceFilter(self.sr.searchBox.QuickFilter, [ cfg.eveowners.Get(charID) for charID in self.invitees.keys() ])
   1480         extraIcons = {}
   1481         for each in [const.eventResponseAccepted, const.eventResponseDeclined, const.eventResponseUndecided]:
   1482             icon = sm.GetService('calendar').GetLongResponseIconPath(each)
   1483             label = sm.GetService('calendar').GetResponseType().get(each, '')
   1484             if label != '':
   1485                 label = localization.GetByLabel(label)
   1486             extraIcons[each] = [icon, label, True]
   1487 
   1488         scrolllist = []
   1489         for owner in matched:
   1490             charID = owner.ownerID
   1491             contact = utillib.KeyVal(contactID=charID)
   1492             response = self.invitees.get(charID, None)
   1493             if response is None:
   1494                 continue
   1495             extraIconHintFlag = extraIcons.get(response, None)
   1496             extraInfo = utillib.KeyVal(extraIconHintFlag=extraIconHintFlag, wndConfigname=self.configname)
   1497             entryTuple = sm.GetService('addressbook').GetContactEntry(None, contact, extraInfo=extraInfo, listentryType=SearchedUser)
   1498             scrolllist.append(entryTuple)
   1499 
   1500         scrolllist = SortListOfTuples(scrolllist)
   1501         self.sr.inviteScroll.Load(contentList=scrolllist, headers=[], noContentHint=localization.GetByLabel('UI/Calendar/FindInviteesWindow/NothingFound'))
   1502 
   1503     def PopulateInviteeDicts(self, eventID):
   1504         if eventID is None:
   1505             self.invitees = {}
   1506         else:
   1507             ownerID = GetAttrs(self, 'eventInfo', 'ownerID')
   1508             self.invitees = sm.GetService('calendar').GetResponsesToEvent(eventID, ownerID)
   1509         self.oldInvitees = self.invitees.copy()
   1510 
   1511     def OnRespondToEvent(self, *args):
   1512         self.CloseByUser()
   1513 
   1514     def OnRemoveCalendarEvent(self, eventID, eventDateTime, isDeleted):
   1515         if self.eventID == eventID:
   1516             self.CloseByUser()
   1517 
   1518 
   1519 class CalendarSingleDayWnd(Window):
   1520     __guid__ = 'form.CalendarSingleDayWnd'
   1521     __notifyevents__ = ['OnReloadCalendar', 'OnCalendarFilterChange']
   1522     default_iconNum = 'res:/ui/Texture/WindowIcons/calendar.png'
   1523 
   1524     def ApplyAttributes(self, attributes):
   1525         Window.ApplyAttributes(self, attributes)
   1526         header = attributes.header
   1527         year = attributes.year
   1528         month = attributes.month
   1529         monthday = attributes.monthday
   1530         events = attributes.events
   1531         wndType = attributes.wndType
   1532         isADay = attributes.isADay or False
   1533         self.date = (year, month, monthday)
   1534         self.year = year
   1535         self.month = month
   1536         self.monthday = monthday
   1537         self.wndType = wndType
   1538         self.isADay = isADay
   1539         sm.RegisterNotify(self)
   1540         if isADay:
   1541             dayDate = time.struct_time((year,
   1542              month,
   1543              monthday,
   1544              0,
   1545              0,
   1546              0,
   1547              0,
   1548              1,
   1549              0))
   1550             caption = localization.formatters.FormatDateTime(value=dayDate, dateFormat='long', timeFormat='none')
   1551         else:
   1552             caption = header
   1553         self.SetCaption(caption)
   1554         self.topParent = Container(name='topParent', parent=self.GetMainArea(), align=uiconst.TOTOP, height=52, clipChildren=True)
   1555         eveLabel.WndCaptionLabel(text=caption, parent=self.topParent)
   1556         self.SetMinSize([315, 300])
   1557         ButtonGroup(btns=[[localization.GetByLabel('UI/Generic/Close'),
   1558           self.CloseByUser,
   1559           (),
   1560           None]], parent=self.sr.main, idx=0)
   1561         self.sr.eventScroll = eveScroll.Scroll(name='eventScroll', parent=self.sr.main, padding=(const.defaultPadding,
   1562          const.defaultPadding,
   1563          const.defaultPadding,
   1564          const.defaultPadding))
   1565         self.sr.eventScroll.sr.id = 'calendar_singedaywnd'
   1566         self.sr.eventScroll.sr.maxDefaultColumns = {localization.GetByLabel('UI/Generic/Unknown'): 150}
   1567         self.LoadDaysEvents(events)
   1568 
   1569     def LoadDaysEvents(self, events, *args):
   1570         self.events = events
   1571         scrolllist = []
   1572         includeUpdatedColumn = self.wndType == 'latestUpdates'
   1573         for eventID, event in events.iteritems():
   1574             iconPath, myResponse = sm.GetService('calendar').GetMyResponseIconFromID(eventID, long=1, getDeleted=event.isDeleted)
   1575             if not settings.user.ui.Get('calendar_showDeclined', 1) and myResponse == const.eventResponseDeclined:
   1576                 continue
   1577             if event.isDeleted and self.isADay:
   1578                 continue
   1579             if self.isADay:
   1580                 timeStamp = getattr(event, 'eventTimeStamp', '')
   1581             else:
   1582                 timeStamp = FmtDate(event.eventDateTime - eveLocalization.GetTimeDelta() * const.SEC, 'ss')
   1583             label = '%s<t>%s' % (timeStamp, event.eventTitle)
   1584             if includeUpdatedColumn:
   1585                 modified = FmtDate(event.dateModified, 'ss')
   1586                 label += '<t>%s' % modified
   1587                 sortBy = event.dateModified
   1588             else:
   1589                 sortBy = event.eventDateTime
   1590             data = utillib.KeyVal()
   1591             data.label = label
   1592             data.cleanLabel = label
   1593             data.eventInfo = event
   1594             data.eventID = event.eventID
   1595             data.GetMenu = self.EventMenu
   1596             data.iconPath = iconPath
   1597             data.response = myResponse
   1598             data.OnDblClick = self.DblClickEventEntry
   1599             entry = GetFromClass(CalendarSingleDayEntry, {'label': label,
   1600              'cleanLabel': label,
   1601              'eventInfo': event,
   1602              'eventID': event.eventID,
   1603              'GetMenu': self.EventMenu,
   1604              'iconPath': iconPath,
   1605              'response': myResponse,
   1606              'OnDblClick': self.DblClickEventEntry})
   1607             scrolllist.append((sortBy, entry))
   1608 
   1609         scrolllist = SortListOfTuples(scrolllist, reverse=includeUpdatedColumn)
   1610         headers = [localization.GetByLabel('UI/Calendar/SingleDayWindow/Time'), localization.GetByLabel('UI/Calendar/SingleDayWindow/Title')]
   1611         if includeUpdatedColumn:
   1612             headers.append(localization.GetByLabel('UI/Calendar/CalendarWindow/LatestUpdates'))
   1613         self.sr.eventScroll.Load(contentList=scrolllist, headers=headers, noContentHint=localization.GetByLabel('UI/Calendar/SingleDayWindow/NoPlannedEvents'))
   1614 
   1615     def EventMenu(self, entry, *args):
   1616         eventInfo = entry.sr.node.eventInfo
   1617         m = sm.GetService('calendar').GetEventMenu(eventInfo, entry.sr.node.response)
   1618         return m
   1619 
   1620     def DblClickEventEntry(self, entry, *args):
   1621         eventInfo = entry.sr.node.eventInfo
   1622         self.OpenEvent(eventInfo)
   1623 
   1624     def OpenEvent(self, eventInfo, *args):
   1625         sm.GetService('calendar').OpenEventWnd(eventInfo)
   1626 
   1627     def OnReloadCalendar(self, *args):
   1628         showTag = sm.GetService('calendar').GetActiveTags()
   1629         if self.isADay:
   1630             eventDict = {}
   1631             events = sm.GetService('calendar').GetEventsByMonthYear(self.month, self.year)
   1632             for eventKV in events:
   1633                 if not eventKV.isDeleted:
   1634                     year, month, wd, day, hour, minute, sec, ms = blue.os.GetTimeParts(eventKV.eventDateTime)
   1635                     if (year, month, day) == self.date and (showTag is None or showTag & eventKV.flag != 0):
   1636                         eventDict[eventKV.eventID] = eventKV
   1637 
   1638             self.events = eventDict
   1639             self.LoadDaysEvents(eventDict)
   1640         elif self.wndType == 'upcomingEvents':
   1641             events = sm.GetService('calendar').GetMyNextEvents()
   1642             self.events = events
   1643             self.LoadDaysEvents(events)
   1644         elif self.wndType == 'latestUpdates':
   1645             events = sm.GetService('calendar').GetMyChangedEvents()
   1646             self.events = events
   1647             self.LoadDaysEvents(events)
   1648 
   1649     def OnCalendarFilterChange(self, *args):
   1650         self.OnReloadCalendar()
   1651 
   1652 
   1653 class CalendarSingleDayEntry(Generic):
   1654     __guid__ = 'listentry.CalendarSingleDayEntry'
   1655 
   1656     def Startup(self, *args):
   1657         self.sr.statusIconCont = Container(name='statusIconCont', parent=self, align=uiconst.TOPLEFT, pos=(0, 0, 16, 16))
   1658         self.sr.flagIconCont = Container(name='statusIconCont', parent=self, align=uiconst.TOPRIGHT, pos=(0, 0, 14, 14))
   1659         FrameThemeColored(parent=self.sr.flagIconCont)
   1660         Generic.Startup(self, args)
   1661 
   1662     def Load(self, node):
   1663         Generic.Load(self, node)
   1664         self.sr.label.left = 16
   1665         self.LoadStatusIcon(node)
   1666         sm.GetService('calendar').LoadTagIconInContainer(node.eventInfo.flag, self.sr.flagIconCont)
   1667         if node.eventInfo.importance > 0:
   1668             self.UpdateLabel(node)
   1669         node.Set('sort_%s' % localization.GetByLabel('UI/Calendar/SingleDayWindow/Time'), node.eventInfo.eventDateTime)
   1670         self.hint = sm.GetService('calendar').GetEventHint(node.eventInfo, node.response)
   1671         self.sr.label.Update()
   1672 
   1673     def LoadStatusIcon(self, data):
   1674         self.sr.statusIconCont.Flush()
   1675         icon = eveIcon.Icon(icon=data.iconPath, parent=self.sr.statusIconCont, align=uiconst.CENTERLEFT, pos=(0, 0, 16, 16))
   1676         icon.hint = localization.GetByLabel(sm.GetService('calendar').GetResponseType().get(data.response, 'UI/Generic/Unknown'))
   1677 
   1678     def UpdateLabel(self, data):
   1679         label = data.cleanLabel
   1680         label = '<color=red>!</color> %s' % label
   1681         self.sr.label.text = label
   1682         self.sr.node.label = label
   1683         self.sr.label.Update()
   1684 
   1685 
   1686 class EventList(Container):
   1687     __notifyevents__ = ['OnReloadToDo', 'OnCalendarFilterChange']
   1688 
   1689     def ApplyAttributes(self, attributes):
   1690         Container.ApplyAttributes(self, attributes)
   1691         self.maxEntries = 25
   1692         self.events = {}
   1693         self.listentryClass = attributes.get('listentryClass')
   1694         self.getEventsFunc = attributes.get('getEventsFunc', sm.GetService('calendar').GetMyNextEvents)
   1695         self.getEventsArgs = attributes.get('getEventsArgs', ())
   1696         self.header = attributes.get('header', '')
   1697         self.listType = attributes.get('listType', 'eventList')
   1698         self.Setup()
   1699 
   1700     def Setup(self):
   1701         sm.RegisterNotify(self)
   1702         self.sr.moreCont = Container(name='moreCont', parent=self, align=uiconst.TOBOTTOM, pos=(0, 0, 0, 10), state=uiconst.UI_NORMAL, padding=(0, 0, 0, 0))
   1703         self.AddMoreContFill()
   1704         self.SetupScroll()
   1705         self.LoadNextEvents()
   1706 
   1707     def LoadNextEvents(self, *args):
   1708         nextEvents = self.GetEvents()
   1709         scrolllist = []
   1710         self.events = {}
   1711         for eventID, eventKV in nextEvents.iteritems():
   1712             eventEntryTuple = self.GetEventEntryTuple(eventKV)
   1713             if eventEntryTuple is None:
   1714                 continue
   1715             self.events[eventID] = eventKV
   1716             scrolllist.append(eventEntryTuple)
   1717 
   1718         scrolllist = SortListOfTuples(scrolllist, reverse=self.GetSortOrder())
   1719         self.LoadScroll(scrolllist)
   1720         self.OnResize()
   1721 
   1722     def SetupScroll(self, *args):
   1723         self.sr.eventScroll = eveScroll.Scroll(name='eventScroll', parent=self)
   1724         self.sr.eventScroll.scrollEnabled = 0
   1725         self.sr.eventScroll.multiSelect = 0
   1726 
   1727     def GetEvents(self, *args):
   1728         return self.getEventsFunc(*self.getEventsArgs)
   1729 
   1730     def GetEventEntryTuple(self, eventKV, *args):
   1731         entry = self.GetEventEntry(eventKV)
   1732         if entry is None:
   1733             return
   1734         return (eventKV.eventDateTime, entry)
   1735 
   1736     def GetSortOrder(self, *args):
   1737         return 0
   1738 
   1739     def LoadScroll(self, scrolllist, *args):
   1740         scrolllist = scrolllist[:self.maxEntries]
   1741         self.sr.eventScroll.Load(contentList=scrolllist, headers=[], noContentHint='')
   1742 
   1743     def AddMoreContFill(self, *args):
   1744         self.sr.backgroundFrame = PanelUnderlay(parent=self.sr.moreCont, padding=(-1, -1, -1, -1))
   1745         icon = eveIcon.Icon(icon='ui_38_16_229', parent=self.sr.moreCont, pos=(0, -3, 16, 16), align=uiconst.CENTERTOP, idx=0, ignoreSize=True)
   1746         icon.OnClick = self.OnMoreClick
   1747 
   1748     def GetEventEntry(self, eventInfo, *args):
   1749         showTag = sm.GetService('calendar').GetActiveTags()
   1750         if showTag is not None and showTag & eventInfo.flag == 0:
   1751             return
   1752         icon, myResponse = sm.GetService('calendar').GetMyResponseIconFromID(eventInfo.eventID, long=0, getDeleted=eventInfo.isDeleted)
   1753         hint = localization.GetByLabel(sm.GetService('calendar').GetResponseType().get(myResponse, 'UI/Generic/Unknown'))
   1754         return GetFromClass(self.listentryClass, {'label': eventInfo.eventTitle,
   1755          'eventInfo': eventInfo,
   1756          'icon': icon,
   1757          'hint': hint,
   1758          'response': myResponse})
   1759 
   1760     def OnResize(self, *args):
   1761         uthread.new(self.UpdateMoreIndicators)
   1762 
   1763     def UpdateMoreIndicators(self, *args):
   1764         if self.sr.eventScroll.scrollingRange >= self.sr.moreCont.height:
   1765             self.sr.moreCont.state = uiconst.UI_PICKCHILDREN
   1766         else:
   1767             self.sr.moreCont.state = uiconst.UI_HIDDEN
   1768 
   1769     def OnReloadToDo(self, *args):
   1770         self.LoadNextEvents()
   1771 
   1772     def OnCalendarFilterChange(self, *args):
   1773         self.OnReloadToDo()
   1774 
   1775     def OnMoreClick(self, *args):
   1776         sm.GetService('calendar').OpenSingleDayWnd(self.header, '', '', '', self.events, isADay=0, wndType=self.listType)
   1777 
   1778 
   1779 class UpdateEventsList(EventList):
   1780 
   1781     def GetEventEntryTuple(self, eventKV, *args):
   1782         entry = self.GetEventEntry(eventKV)
   1783         if entry is None:
   1784             return
   1785         return (eventKV.dateModified, entry)
   1786 
   1787     def GetSortOrder(self, *args):
   1788         return 1
   1789 
   1790 
   1791 class CalendarListEntry(Generic):
   1792     __guid__ = 'listentry.CalendarListEntry'
   1793     __notifyevents__ = []
   1794     TEXTMARGIN = 2
   1795 
   1796     def Startup(self, *args):
   1797         self.sr.statusIconCont = Container(name='statusIconCont', parent=self, align=uiconst.TOPLEFT, pos=(0, 0, 16, 16))
   1798         self.sr.tagIconCont = Container(name='statusIconCont', parent=self, align=uiconst.TOPRIGHT, pos=(0, 0, 16, 16))
   1799         Frame(parent=self.sr.statusIconCont, color=(1.0, 1.0, 1.0, 0.5))
   1800         Generic.Startup(self, args)
   1801         self.sr.label.align = uiconst.TOPLEFT
   1802         self.sr.label.top = self.TEXTMARGIN
   1803         self.sr.timeLabel = eveLabel.EveLabelMedium(text='', parent=self, left=20, top=14, state=uiconst.UI_DISABLED, align=uiconst.TOPLEFT, maxLines=1, color=(0.7, 0.7, 0.7, 0.75))
   1804         self.sr.fill = Frame(parent=self, name='fill', frameConst=uiconst.FRAME_FILLED_SHADOW_CORNER0, color=(1.0, 1.0, 1.0, 0.05))
   1805         sm.RegisterNotify(self)
   1806 
   1807     def Load(self, node):
   1808         Generic.Load(self, node)
   1809         self.sr.label.left = 20
   1810         eventInfo = node.eventInfo
   1811         hint = self.GetEventHint(eventInfo, node.response)
   1812         self.hint = hint
   1813         if eventInfo.importance > 0:
   1814             label = self.sr.node.label
   1815             newLabel = '<color=red>!</color> %s' % label
   1816             self.sr.label.text = newLabel
   1817         self.SetTime(eventInfo.eventDateTime - eveLocalization.GetTimeDelta() * const.SEC)
   1818         self.sr.timeLabel.top = self.sr.label.top + self.sr.label.height
   1819         self.LoadStatusIcon()
   1820         sm.GetService('calendar').LoadTagIconInContainer(eventInfo.flag, self.sr.tagIconCont)
   1821         self.sr.label.Update()
   1822 
   1823     def GetMenu(self, *args):
   1824         eventInfo = self.sr.node.eventInfo
   1825         m = sm.GetService('calendar').GetEventMenu(eventInfo, self.sr.node.response)
   1826         return m
   1827 
   1828     def GetEventHint(self, eventInfo, myResponse, *args):
   1829         hint = sm.GetService('calendar').GetEventHint(eventInfo, myResponse)
   1830         return hint
   1831 
   1832     def _OnClose(self):
   1833         sm.UnregisterNotify(self)
   1834 
   1835     def LoadStatusIcon(self, *args):
   1836         data = self.sr.node
   1837         self.sr.statusIconCont.Flush()
   1838         iconPath = data.icon
   1839         hint = data.hint
   1840         icon = eveIcon.Icon(icon=iconPath, parent=self.sr.statusIconCont, align=uiconst.CENTER, pos=(0, 2, 16, 16))
   1841         icon.hint = hint
   1842 
   1843     def GetHeight(self, node, width):
   1844         labelWidth, labelHeight = eveLabel.EveLabelMedium.MeasureTextSize(node.label)
   1845         timeWidth, timeHeight = eveLabel.EveLabelMedium.MeasureTextSize(FmtDate(node.eventInfo.eventDateTime, 'ls'))
   1846         return CalendarListEntry.TEXTMARGIN * 2 + labelHeight + timeHeight
   1847 
   1848     def SetTime(self, eventDateTime, *args):
   1849         self.sr.timeLabel.text = FmtDate(eventDateTime, 'ls')
   1850 
   1851     def OnDblClick(self, *args):
   1852         sm.GetService('calendar').OpenEventWnd(self.sr.node.eventInfo)
   1853 
   1854 
   1855 class CalendarUpdatedEntry(CalendarListEntry):
   1856     __guid__ = 'listentry.CalendarUpdatedEntry'
   1857 
   1858     def GetEventHint(self, eventInfo, myResponse, *args):
   1859         eventDateTime = FmtDate(eventInfo.eventDateTime, 'ls')
   1860         lastUpdatedTime = FmtDate(eventInfo.dateModified, 'ls')
   1861         hint = localization.GetByLabel('UI/Calendar/EventWindow/LastUpdateHint', eventDateTime=eventDateTime, eventTitle=eventInfo.eventTitle, lastUpdatedTime=lastUpdatedTime)
   1862         return hint