class TimezoneWindow(Singleton): SCREEN_NAME = 'timezone' def _singleton_init(self, controlState, xml): self.timezones = TimezoneList() chosenTZ = userchoices.getTimezone() if chosenTZ: self.selectedTZ = self.timezones.findByCityName( chosenTZ['city'] ) else: self.selectedTZ = self.timezones.defaultTimezone connectSignalHandlerByDict(self, TimezoneWindow, xml, { ('advanced_ok', 'clicked'): 'onCityListSelect', ('advanced_cancel', 'clicked'): 'onCityListCancel', ('tz_button', 'clicked'): 'onAdvancedClicked', ('TimezoneDrawingArea', 'motion_notify_event'): 'onTZDrawMotion', ('TimezoneDrawingArea', 'button_press_event'): 'onTZDrawPress', ('TimezoneDrawingArea', 'button_release_event'): 'onTZDrawRelease', ('TimezoneDrawingArea', 'expose_event'): 'onTZDrawExpose', }) self.tzEntry = xml.get_widget("tz_entry") self.advancedDialog = AdvancedDialog(xml) self.allTZsView = xml.get_widget("tz_treeview") self.setupMap(xml) self.setupTimezone(xml) def __init__(self, controlState, xml): controlState.displayHeaderBar = 1 controlState.windowIcon = 'timezone.png' controlState.windowTitle = "Time Zone Settings" controlState.windowText = "Select the time zone for ESX" def prepareAdvancedDialog(self): # Note, the Advanced Dialog should be prepared every time before it is # shown, that will set the active city and scroll to it. # prepare the TreeView with its model and columns allTZsModel = gtk.ListStore(str, str, object) self.allTZsView.set_model(allTZsModel) if not self.allTZsView.get_columns(): renderer = gtk.CellRendererText() # zoneColumn gets its text from index 0 in the model zoneColumn = gtk.TreeViewColumn('Zone Name', renderer, text=0) self.allTZsView.append_column(zoneColumn) # zoneColumn gets its text from index 1 in the model offsetColumn = gtk.TreeViewColumn('UTC Offset', renderer, text=1) self.allTZsView.append_column(offsetColumn) self.allTZsView.set_search_column(0) # populate the model, highlight the selected timezone seenZoneNames = [] for index, tz in enumerate(self.timezones.sortedIter()): if tz.zoneName in seenZoneNames: continue # don't show duplicate zone names seenZoneNames.append(tz.zoneName) allTZsModel.append((tz.zoneName, tz.offset, tz)) if self.selectedTZ == tz: # NOTE, this "cursor" is the highlighted row, not the mouse self.allTZsView.set_cursor(index) self.allTZsView.scroll_to_cell(index, None, True, 0.5) def setupTimezone(self, xml): self.tzEntry.set_text(self.selectedTZ.zoneName) def setupMap(self, xml): self.cityHoverLabel = xml.get_widget("hover_label") self.drawingArea = xml.get_widget("TimezoneDrawingArea") bgFileName = os.path.join(IMAGE_DIR, 'background.png') self.bgImage = PixbufSprite(bgFileName) bgFileName = os.path.join(IMAGE_DIR, 'map.png') self.mapImage = PixbufSprite(bgFileName) self.sprites = [ self.bgImage, self.mapImage, ] #note: order is important. it is the drawing order self.listeners= [] #note: order is important. (event handling order) def placeCityDot(tz, clickCB, offsetSlice, isSelected): if not tz.cityPos: return #this city doesn't have a place on the map city = City(tz.city, tz.cityPos) city.clickCB = clickCB offsetSlice.cityGroup.cities.append(city) if isSelected: offsetSlice.selected = True city.selected = True offsetSlicesByName = {} secondPass = [] for tzList in self.timezones.groupByOffsets().values(): offsetName = tzList[0].offset offsetPos = tzList[0].offsetPos if not offsetPos: secondPass += [tz for tz in tzList if tz.showAsMapOffset] continue #this offset doesn't have a place on the map offsetSlice = OffsetSlice(offsetName, offsetPos) offsetSlice.cityGroup = CityGroup(self) offsetSlice.clickCB = self.onOffsetSliceClick offsetSlicesByName[offsetName] = offsetSlice for tz in tzList: isSelected = (tz == self.selectedTZ) placeCityDot(tz, self.onCityClick, offsetSlice, isSelected) self.sprites.append(offsetSlice) self.listeners.append(offsetSlice) # Second pass: collect those cities important enough to be on # the map, but whose offset is weird, so we put them in the slice # that best approximates it. for tz in secondPass: offsetSlice = offsetSlicesByName.get(tz.showAsMapOffset, None) if not offsetSlice: log.warn('Offset %s not on the map. TZ %s could not be drawn' % (tz.showAsMapOffset, tz.zoneName)) continue isSelected = (tz == self.selectedTZ) placeCityDot(tz, self.onCityClick, offsetSlice, isSelected) def notifyCityHovered(self, city): self.cityHoverLabel.set_text( city.cityName ) def drawAll(self): for sprite in self.sprites: sprite.DrawOn( self.drawWindow ) def onCityListCancel(self, widget, *args): self.advancedDialog.hide() def onAdvancedClicked(self, *args): self.prepareAdvancedDialog() self.advancedDialog.show() def onCityListSelect(self, widget, *args): model, treeIter = self.allTZsView.get_selection().get_selected() if not treeIter: MessageWindow(None, "Invalid Time Zone", "You must select a time zone.") return zoneName, offset, tz = model[treeIter] self.selectedTZ = tz log.debug('TZ %s chosen from list.' % str(tz)) self.tzEntry.set_text(tz.zoneName) for sprite in self.sprites: if not isinstance(sprite, OffsetSlice): continue if sprite.offsetName in [tz.offset, tz.showAsMapOffset]: sprite.selected = True else: sprite.selected = False for citySprite in sprite.cityGroup.cities: if citySprite.cityName == tz.city: citySprite.selected = True else: citySprite.selected = False self.advancedDialog.hide() self.drawingArea.queue_draw() def onOffsetSliceClick(self, offsetSlice): # current behaviour is for the city closest to the mouse to be # always highlighted, so an offset will never get a click by # itself. Therefore, pass. return def onCityClick(self, city): log.debug( 'onCityClick %s' % (city.cityName) ) tz = self.timezones.findByCityName( city.cityName ) self.tzEntry.set_text(tz.zoneName) self.selectedTZ = tz def onTZDrawExpose(self, *args): self.drawWindow = self.drawingArea.window assert self.drawWindow self.drawAll() #return False def onTZDrawMotion(self, widget, event): self.cityHoverLabel.set_text('') for listener in self.listeners: if hasattr(listener, 'HandleMotion'): listener.HandleMotion( (event.x, event.y) ) self.drawingArea.queue_draw() def onTZDrawPress(self, widget, event): log.debug( 'Press at %d %d' % (event.x, event.y) ) for listener in self.listeners: if hasattr(listener, 'HandlePress'): listener.HandlePress( (event.x, event.y) ) self.drawingArea.queue_draw() def onTZDrawRelease(self, widget, event): log.debug( 'Release at %d %d' % (event.x, event.y) ) for listener in self.listeners: if hasattr(listener, 'HandleRelease'): listener.HandleRelease( (event.x, event.y) ) self.drawingArea.queue_draw() def getNext(self): tz = self.selectedTZ userchoices.setTimezone(tz.zoneName, tz.offset, tz.city) tz.runtimeAction()
class TimezoneWindow(Singleton): SCREEN_NAME = 'timezone' def _singleton_init(self, controlState, xml): self.timezones = TimezoneList() chosenTZ = userchoices.getTimezone() if chosenTZ: self.selectedTZ = self.timezones.findByCityName(chosenTZ['city']) else: self.selectedTZ = self.timezones.defaultTimezone connectSignalHandlerByDict( self, TimezoneWindow, xml, { ('advanced_ok', 'clicked'): 'onCityListSelect', ('advanced_cancel', 'clicked'): 'onCityListCancel', ('tz_button', 'clicked'): 'onAdvancedClicked', ('TimezoneDrawingArea', 'motion_notify_event'): 'onTZDrawMotion', ('TimezoneDrawingArea', 'button_press_event'): 'onTZDrawPress', ('TimezoneDrawingArea', 'button_release_event'): 'onTZDrawRelease', ('TimezoneDrawingArea', 'expose_event'): 'onTZDrawExpose', }) self.tzEntry = xml.get_widget("tz_entry") self.advancedDialog = AdvancedDialog(xml) self.allTZsView = xml.get_widget("tz_treeview") self.setupMap(xml) self.setupTimezone(xml) def __init__(self, controlState, xml): controlState.displayHeaderBar = 1 controlState.windowIcon = 'timezone.png' controlState.windowTitle = "Time Zone Settings" controlState.windowText = "Select the time zone for ESX" def prepareAdvancedDialog(self): # Note, the Advanced Dialog should be prepared every time before it is # shown, that will set the active city and scroll to it. # prepare the TreeView with its model and columns allTZsModel = gtk.ListStore(str, str, object) self.allTZsView.set_model(allTZsModel) if not self.allTZsView.get_columns(): renderer = gtk.CellRendererText() # zoneColumn gets its text from index 0 in the model zoneColumn = gtk.TreeViewColumn('Zone Name', renderer, text=0) self.allTZsView.append_column(zoneColumn) # zoneColumn gets its text from index 1 in the model offsetColumn = gtk.TreeViewColumn('UTC Offset', renderer, text=1) self.allTZsView.append_column(offsetColumn) self.allTZsView.set_search_column(0) # populate the model, highlight the selected timezone seenZoneNames = [] for index, tz in enumerate(self.timezones.sortedIter()): if tz.zoneName in seenZoneNames: continue # don't show duplicate zone names seenZoneNames.append(tz.zoneName) allTZsModel.append((tz.zoneName, tz.offset, tz)) if self.selectedTZ == tz: # NOTE, this "cursor" is the highlighted row, not the mouse self.allTZsView.set_cursor(index) self.allTZsView.scroll_to_cell(index, None, True, 0.5) def setupTimezone(self, xml): self.tzEntry.set_text(self.selectedTZ.zoneName) def setupMap(self, xml): self.cityHoverLabel = xml.get_widget("hover_label") self.drawingArea = xml.get_widget("TimezoneDrawingArea") bgFileName = os.path.join(IMAGE_DIR, 'background.png') self.bgImage = PixbufSprite(bgFileName) bgFileName = os.path.join(IMAGE_DIR, 'map.png') self.mapImage = PixbufSprite(bgFileName) self.sprites = [ self.bgImage, self.mapImage, ] #note: order is important. it is the drawing order self.listeners = [] #note: order is important. (event handling order) def placeCityDot(tz, clickCB, offsetSlice, isSelected): if not tz.cityPos: return #this city doesn't have a place on the map city = City(tz.city, tz.cityPos) city.clickCB = clickCB offsetSlice.cityGroup.cities.append(city) if isSelected: offsetSlice.selected = True city.selected = True offsetSlicesByName = {} secondPass = [] for tzList in self.timezones.groupByOffsets().values(): offsetName = tzList[0].offset offsetPos = tzList[0].offsetPos if not offsetPos: secondPass += [tz for tz in tzList if tz.showAsMapOffset] continue #this offset doesn't have a place on the map offsetSlice = OffsetSlice(offsetName, offsetPos) offsetSlice.cityGroup = CityGroup(self) offsetSlice.clickCB = self.onOffsetSliceClick offsetSlicesByName[offsetName] = offsetSlice for tz in tzList: isSelected = (tz == self.selectedTZ) placeCityDot(tz, self.onCityClick, offsetSlice, isSelected) self.sprites.append(offsetSlice) self.listeners.append(offsetSlice) # Second pass: collect those cities important enough to be on # the map, but whose offset is weird, so we put them in the slice # that best approximates it. for tz in secondPass: offsetSlice = offsetSlicesByName.get(tz.showAsMapOffset, None) if not offsetSlice: log.warn( 'Offset %s not on the map. TZ %s could not be drawn' % (tz.showAsMapOffset, tz.zoneName)) continue isSelected = (tz == self.selectedTZ) placeCityDot(tz, self.onCityClick, offsetSlice, isSelected) def notifyCityHovered(self, city): self.cityHoverLabel.set_text(city.cityName) def drawAll(self): for sprite in self.sprites: sprite.DrawOn(self.drawWindow) def onCityListCancel(self, widget, *args): self.advancedDialog.hide() def onAdvancedClicked(self, *args): self.prepareAdvancedDialog() self.advancedDialog.show() def onCityListSelect(self, widget, *args): model, treeIter = self.allTZsView.get_selection().get_selected() if not treeIter: MessageWindow(None, "Invalid Time Zone", "You must select a time zone.") return zoneName, offset, tz = model[treeIter] self.selectedTZ = tz log.debug('TZ %s chosen from list.' % str(tz)) self.tzEntry.set_text(tz.zoneName) for sprite in self.sprites: if not isinstance(sprite, OffsetSlice): continue if sprite.offsetName in [tz.offset, tz.showAsMapOffset]: sprite.selected = True else: sprite.selected = False for citySprite in sprite.cityGroup.cities: if citySprite.cityName == tz.city: citySprite.selected = True else: citySprite.selected = False self.advancedDialog.hide() self.drawingArea.queue_draw() def onOffsetSliceClick(self, offsetSlice): # current behaviour is for the city closest to the mouse to be # always highlighted, so an offset will never get a click by # itself. Therefore, pass. return def onCityClick(self, city): log.debug('onCityClick %s' % (city.cityName)) tz = self.timezones.findByCityName(city.cityName) self.tzEntry.set_text(tz.zoneName) self.selectedTZ = tz def onTZDrawExpose(self, *args): self.drawWindow = self.drawingArea.window assert self.drawWindow self.drawAll() #return False def onTZDrawMotion(self, widget, event): self.cityHoverLabel.set_text('') for listener in self.listeners: if hasattr(listener, 'HandleMotion'): listener.HandleMotion((event.x, event.y)) self.drawingArea.queue_draw() def onTZDrawPress(self, widget, event): log.debug('Press at %d %d' % (event.x, event.y)) for listener in self.listeners: if hasattr(listener, 'HandlePress'): listener.HandlePress((event.x, event.y)) self.drawingArea.queue_draw() def onTZDrawRelease(self, widget, event): log.debug('Release at %d %d' % (event.x, event.y)) for listener in self.listeners: if hasattr(listener, 'HandleRelease'): listener.HandleRelease((event.x, event.y)) self.drawingArea.queue_draw() def getNext(self): tz = self.selectedTZ userchoices.setTimezone(tz.zoneName, tz.offset, tz.city) tz.runtimeAction()