コード例 #1
0
ファイル: timezone_gui.py プロジェクト: vmware-archive/weasel
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()
コード例 #2
0
ファイル: timezone_gui.py プロジェクト: vmware/weasel
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()
コード例 #3
0
class TimezoneWindow(TextRunner):
    "Determine timezone of the system."

    def __init__(self):
        super(TimezoneWindow, self).__init__()
        self.substep = self.start
        self.timezones = TimezoneList()
        self.userinput = None
        self.uiTitle = 'Timezone'

        if not userchoices.getTimezone():  # not set in userchoices
            # copy default timezone values into userchoices
            dtz = self.timezones.defaultTimezone
            userchoices.setTimezone(dtz.zoneName, dtz.offset, dtz.city)
            dtz.runtimeAction()

        self.scrollable = None

    def start(self):
        self.setSubstepEnv( {'next': self.askConfirm } )

    def askConfirm(self):
        currentTz = userchoices.getTimezone()
        if currentTz['city']:
            formattedTz = tzDictStrWithCity % currentTz
        else:
            formattedTz = tzDictStrWithoutCity % currentTz
        ui = {
            'title': self.uiTitle,
            'body': askConfirmText % formattedTz,
            'menu': {
                '1': self.stepForward,
                '2': self.showTzList,
                '<': self.stepBack,
                '?': self.help,
            }
        }
        self.setSubstepEnv(ui)

    def help(self):
        self.pushSubstep()
        ui = {
            'title': self.uiTitle + ' (Help)',
            'body': helpText,
            'menu': { '*': self.popSubstep }
        }
        self.setSubstepEnv(ui)

    def showTzList(self):
        scrollable = []
        for iName, tz in enumerate(self.timezones.sortedIter()):
            if tz.city:
                format = tzEnumStrWithCity
            else:
                format = tzEnumStrWithoutCity
            # use 1-indexed
            formattedTz = format % (iName+1, tz.offset, tz.zoneName, tz.city)
            scrollable.append(formattedTz)
        self.setScrollEnv(scrollable, SCROLL_LIMIT)
        self.setSubstepEnv( {'next': self.scrollDisplay } )

    def scrollDisplay(self):
        "display timezone choices"
        self.buildScrollDisplay(self.scrollable, self.uiTitle,
            self.update, "<number>: keyboard choice", allowStepRestart=True)

    def update(self):

        # use skeleton below for exceptions
        errorSkeleton = {
            'title': self.uiTitle + ' (Update)',
            'menu': { '*': self.popSubstep },
            # add 'body'
        }

        # check for numeric input
        try:
            selected = int(self.userinput)-1    # revert to 0-indexed
        except ValueError:                      # non-integer input
            tz = None
        else:
            sortedTimezones = list(self.timezones.sortedIter())
            if 0 <= selected < len(sortedTimezones):
                tz = sortedTimezones[selected]
            else:
                tz = None

        if not tz:
            self.pushSubstep()
            errorSkeleton['body'] = helpText
            self.setSubstepEnv(errorSkeleton)
            return

        # register the choice
        userchoices.setTimezone(tz.zoneName, tz.offset, tz.city)
        tz.runtimeAction()
        log.debug('set tz to %s (%s)' % (tz.zoneName, tz.city))

        # choice acepted
        self.setSubstepEnv( {'next': self.askConfirm } )