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