예제 #1
0
class TagStar(gtk.HBox):
    """
    A L{gtk.HBox} which arranges togglebuttons around the current position
    within a L{gtk.Fixed} widget.

    This is the central tag element, where a user can either tag his current
    position with a category specified in L{geotagplugin.ECategory}. If
    one of the user's already tagged features is selected in the tree, the
    made change action will be handled as an edit.
    """

    IMG_SIZE = (100, 100)
    BUTTON_SIZE = (100, 100)
    EMPTY_LIST_STORE = gtk.ListStore(gobject.TYPE_STRING)

    toggled = NONE_CATEGORY # selected category
    selected = None # gtk.Image displaying selected category

    def __init__(self, toolbar, control):
        gtk.HBox.__init__(self)
        self._logger = logging.getLogger('TagStar')
        self._logger.setLevel(constants.LOG_LEVEL)
        self.toolbar = toolbar
        self.control = control

        self.size_cb = self.connect('size_allocate', self.size_allocate_cb)

        self.fixed = gtk.Fixed()
        self.pack_start(self.fixed)
        self.show_all()

    def size_allocate_cb(self, widget, event):
        """
        Builds the tag star around the center where the selected
        category is shown.
        """
        self._logger.debug('size_allocate_cb()')
        x, y, width, height = self.fixed.get_allocation()
        self._logger.debug('x: %s, y: %s, w: %s, h: %s', x, y, width, height)
        self.set_size_request(width, height)

        ######################################################################
        # place togglebuttons around the current position in a radio group

        color_fill = profile.get_color().get_fill_color()
        color_stroke = profile.get_color().get_stroke_color()
        button_width, button_height = self.BUTTON_SIZE
        cat_names = get_categories()

        radius = 300 # px
        x_center = width / 2 - 40
        y_center = height / 2 - 40
        step_angle = math.radians(360 / (len(cat_names) + 1)) # plus reset btn

        # add a reset button
        self.reset_selected_btn = RadioToolButton()
        img_name = os.path.join(GeoTag.ICONS_PATH, 'reset.svg')
        icon = gtk.image_new_from_pixbuf(utils.load_svg_image(img_name,
                                                   color_stroke,
                                                   color_fill,
                                                   self.IMG_SIZE))
        self.reset_selected_btn.set_icon_widget(icon)
        self.reset_selected_btn.set_tooltip(_('Reset selected tag.'))
        self.reset_selected_btn.connect('clicked', self.reset_toggled)
        self.reset_selected_btn.show_all()
        self.reset_selected_btn.set_size_request(button_width, button_height)
        self.fixed.put(self.reset_selected_btn,
                       x_center,          # + int(radius * math.sin(i * step_angle)),
                       y_center + radius) # + int(radius * math.cos(i * step_angle)))
        self.reset_selected_btn.set_active(False)

        # read all available categories dynamically
        for i, category in enumerate(cat_names):
            button = RadioToolButton(group=self.reset_selected_btn)
            img_name = os.path.join(GeoTag.ICONS_PATH, category)
            icon = get_gtkimage_from_plugin(img_name, color_stroke, color_fill, self.IMG_SIZE)
            button.set_icon_widget(icon)
            button.set_tooltip(_('Tag some %s.' % category))            # XXX check translation here!!
            button.connect('clicked', self.set_toggled, category)
            button.show_all()
            button.set_size_request(button_width, button_height)
            self.fixed.put(button,
                           x_center + int(radius * math.sin((i + 1) * step_angle)),
                           y_center + int(radius * math.cos((i + 1) * step_angle)))
            button.set_active(False)

        img_name = os.path.join(GeoTag.ICONS_PATH, NONE_CATEGORY)
        self._set_selected(get_gtkimage_from_plugin(img_name, color_stroke,color_fill, self.IMG_SIZE))

        ###################################################################

        self._logger.debug("size_allocation done")
        self.disconnect(self.size_cb) ## use only once

    def reset_toggled(self, button):
        """
        Resets toggled property and combobox liststore.

        @param button: The reset button (can be omitted by passing None).
        @note: If a tag was selected within the L{geotagmodel.GeotagModel},
        the tag will be deleted.
        """
        self.toggled = NONE_CATEGORY

        # reset liststore
        combo = self.toolbar.combobox
        combo.set_model(self.EMPTY_LIST_STORE)

        # reset selected widget
        color_fill = profile.get_color().get_fill_color()
        color_stroke = profile.get_color().get_stroke_color()
        self._set_selected(get_gtkimage_from_plugin(NONE_CATEGORY,
                                                    color_stroke,
                                                    color_fill,
                                                    self.IMG_SIZE))

        self.reset_selected_btn.set_active(True)
        self.selected.queue_draw()
        combo.queue_draw()

    def set_toggled(self, button, category):
        """
        Switches the empty Button and the tagged category button clicked.
        Also, sets the appropriate liststore for the combobox.

        @param button: Toggled button (can be omittted).
        @param category: The corresponding category to set.
        """
        self._logger.debug("set_toggled()")

        self.toggled = category

        # set liststore
        combo = self.toolbar.combobox
        combo.set_model(self.toolbar.description_sets[category])

        color_fill = profile.get_color().get_fill_color()
        color_stroke = profile.get_color().get_stroke_color()

#        self._logger.debug("storage type: %s", self.selected.get_property("storage-type"))
        self._set_selected(get_gtkimage_from_plugin(category,
                                                    color_stroke,
                                                    color_fill,
                                                    self.IMG_SIZE))
        combo.queue_draw()

    def _set_selected(self, widget):
        """
        Sets the widget as the currently selected tag category.

        @param widget: The L{gtk.Image} to set.
        """
        x, y, width, height = self.fixed.get_allocation()
        x_center = width / 2 - 40
        y_center = height / 2 - 40

        if self.selected:
            self.selected.clear()
        button_width, button_height = self.BUTTON_SIZE
        widget.set_size_request(button_width, button_height)
        widget.show_all()
        self.selected = widget
        self.selected.queue_draw()

        self.fixed.put(self.selected, x_center, y_center)
예제 #2
0
    def size_allocate_cb(self, widget, event):
        """
        Builds the tag star around the center where the selected
        category is shown.
        """
        self._logger.debug('size_allocate_cb()')
        x, y, width, height = self.fixed.get_allocation()
        self._logger.debug('x: %s, y: %s, w: %s, h: %s', x, y, width, height)
        self.set_size_request(width, height)

        ######################################################################
        # place togglebuttons around the current position in a radio group

        color_fill = profile.get_color().get_fill_color()
        color_stroke = profile.get_color().get_stroke_color()
        button_width, button_height = self.BUTTON_SIZE
        cat_names = get_categories()

        radius = 300 # px
        x_center = width / 2 - 40
        y_center = height / 2 - 40
        step_angle = math.radians(360 / (len(cat_names) + 1)) # plus reset btn

        # add a reset button
        self.reset_selected_btn = RadioToolButton()
        img_name = os.path.join(GeoTag.ICONS_PATH, 'reset.svg')
        icon = gtk.image_new_from_pixbuf(utils.load_svg_image(img_name,
                                                   color_stroke,
                                                   color_fill,
                                                   self.IMG_SIZE))
        self.reset_selected_btn.set_icon_widget(icon)
        self.reset_selected_btn.set_tooltip(_('Reset selected tag.'))
        self.reset_selected_btn.connect('clicked', self.reset_toggled)
        self.reset_selected_btn.show_all()
        self.reset_selected_btn.set_size_request(button_width, button_height)
        self.fixed.put(self.reset_selected_btn,
                       x_center,          # + int(radius * math.sin(i * step_angle)),
                       y_center + radius) # + int(radius * math.cos(i * step_angle)))
        self.reset_selected_btn.set_active(False)

        # read all available categories dynamically
        for i, category in enumerate(cat_names):
            button = RadioToolButton(group=self.reset_selected_btn)
            img_name = os.path.join(GeoTag.ICONS_PATH, category)
            icon = get_gtkimage_from_plugin(img_name, color_stroke, color_fill, self.IMG_SIZE)
            button.set_icon_widget(icon)
            button.set_tooltip(_('Tag some %s.' % category))            # XXX check translation here!!
            button.connect('clicked', self.set_toggled, category)
            button.show_all()
            button.set_size_request(button_width, button_height)
            self.fixed.put(button,
                           x_center + int(radius * math.sin((i + 1) * step_angle)),
                           y_center + int(radius * math.cos((i + 1) * step_angle)))
            button.set_active(False)

        img_name = os.path.join(GeoTag.ICONS_PATH, NONE_CATEGORY)
        self._set_selected(get_gtkimage_from_plugin(img_name, color_stroke,color_fill, self.IMG_SIZE))

        ###################################################################

        self._logger.debug("size_allocation done")
        self.disconnect(self.size_cb) ## use only once
예제 #3
0
파일: geo.py 프로젝트: 52North/glaps
class GeoToolbar(gtk.Toolbar):
    """
    Tools which interacts with the currently chosen view.

    This toolbar is meant general: General map tools can be enabled. The
    toolbar serves as controller. Because you use a specific geo you have
    to wire specific functionality to the common tools offered by this toolbar.

    Tools you may want to enable:
    ===========     ==========================
    enable_goto_current_position
                                   User wants to center map over current
                                   position.

    toggle_crosslines
                                   User wants to show crosslines.

    navigation
                                   User wants to navigate the map. Includes
                                   buttons for NESW.

    zoom-in
                                   User wants to zoom-in the current map view.

    zoom-out
                                   User wants to zoom-out the current map view.

    zoom-bestfit
                                   User wants to zoom-in the current map view.
    ===========     ==========================

    Enable one of these tools by calling the appropriate method with your
    custom callback method before adding the toolbar to the toolbox.
    """
    title = _('Map tools')
    radio_show_own_pos_btn = None
    radio_show_all_pos_btn = None

    def __init__(self, view, name=None):
        """
        Creates general toolbar where general map tools can be enabled.

        @param name: The name of the toolbar.
        """
        gtk.Toolbar.__init__(self)
        self.set_property('can-focus', False)
        self.view = view
        if name:
            self.name = name
            self._logger = logging.getLogger(name)
        else:
            self._logger = logging.getLogger('geo.GeoToolbar')
        self._logger.setLevel(constants.LOG_LEVEL)

        # remove predefined key bindings
        gtk.binding_entry_remove(self, gtk.keysyms.Left, 0)
        gtk.binding_entry_remove(self, gtk.keysyms.Right, 0)
        gtk.binding_entry_remove(self, gtk.keysyms.Up, 0)
        gtk.binding_entry_remove(self, gtk.keysyms.Down, 0)
        gtk.binding_entry_remove(self, gtk.keysyms.plus, 0)
        gtk.binding_entry_remove(self, gtk.keysyms.minus, 0)

        self.callbacks = {}
        self.connect('key-press-event', self.key_pressed_cb, self.callbacks)

        self.show_no_positions = RadioToolButton()
        icon_name = os.path.join(constants.ICON_PATH, "show-no-positions.svg")
        icon = utils.load_svg_image(icon_name, None, None, BTN_ICON_SIZE)
        img = gtk.image_new_from_pixbuf(icon)
        self.show_no_positions.set_icon_widget(img)
        self.show_no_positions.set_tooltip(_('Show no players.'))

    def enable_show_own_position(self, view):
        """
        Shows the only the own position on the map.
        """
        self.radio_show_own_pos_btn = RadioToolButton(group=self.show_no_positions)
        (fill, stroke) = ('#ffffff', '#000000') # black/white explicit
        buddy_icon = utils.get_xo_icon(stroke, fill, BTN_ICON_SIZE)
        img = gtk.image_new_from_pixbuf(buddy_icon)
        self.radio_show_own_pos_btn.set_icon_widget(img)
        self.radio_show_own_pos_btn.set_tooltip(_('Show only me.'))
        self.radio_show_own_pos_btn.connect('clicked', view.radio_show_own_position_cb)
        self.insert(self.radio_show_own_pos_btn, -1)
        self.radio_show_own_pos_btn.show_all()
        if self.radio_show_all_pos_btn:
            self.show_no_positions.connect("clicked", view.radio_show_no_positions_cb)
            self.show_no_positions.show_all()
            self.insert(self.show_no_positions, -1)

    def enable_show_all_positions(self, view):
        """
        Shows the position of all players participating the game.
        """
        self.radio_show_all_pos_btn = RadioToolButton(group=self.show_no_positions)
        icon_name = os.path.join(constants.ICON_PATH , 'show-all-players.svg')
        icon = utils.load_svg_image(icon_name, None, None, BTN_ICON_SIZE)
        img = gtk.image_new_from_pixbuf(icon)
        self.radio_show_all_pos_btn.set_icon_widget(img)
        self.radio_show_all_pos_btn.set_tooltip(_('Show all players.'))
        self.radio_show_all_pos_btn.connect('clicked', view.radio_show_all_position_cb)
        self.insert(self.radio_show_all_pos_btn, -1)
        self.radio_show_all_pos_btn.show_all()
        if self.radio_show_own_pos_btn:
            self.show_no_positions.connect("clicked", view.radio_show_no_positions_cb)
            self.show_no_positions.show_all()
            self.insert(self.show_no_positions, -1)
            self.radio_show_all_pos_btn.set_active(True)

    def enable_center_current_position(self, on_center_on_current_position):
        """
        Enables tool to set the map center to current lon/lat position.

        @param on_goto_current_position: The callback function to be called when
        user wants to center the map to current position.
        """
        goto_current_pos_btn = ToggleToolButton('goto-current-pos')
        goto_current_pos_btn.set_tooltip(_('Center map on my position.'))
        goto_current_pos_btn.connect('clicked', on_center_on_current_position)
        goto_current_pos_btn.set_active(GeoCanvas._CENTER_MAP)
        goto_current_pos_btn.show()
        self.insert(goto_current_pos_btn, -1)

    def enable_toggle_crosslines(self, view):
        """
        Enables tool to toggle crosslines.

        @param view: The view for which the crosslines shall be displayed.
        """
        toggle_crossline_btn = ToggleToolButton('toggle-crosslines')
        toggle_crossline_btn.set_tooltip(_('Show crossline.'))
        toggle_crossline_btn.set_active(GeoCanvas._CROSSLINES)
        toggle_crossline_btn.connect('clicked', view.toggle_crossline_cb)
        toggle_crossline_btn.show()
        self.insert(toggle_crossline_btn, -1)

    def enable_zoom(self, zoom_callbacks):
        """
        Enables tools to zoom the map via buttons.

        @param zoom_callbacks: A dict containing zoom callbacks:
                ===========  =============
                zoom_callbacks['zoom_in']   A callback to zoom in

                zoom_callbacks['zoom_out']  A callback to zoom out
                ===========  =============
        """
        self.zoom_in_btn = ToolButton('zoom-in')
        self.zoom_in_btn.set_tooltip(_('Zoom in.'))
        self.zoom_in_btn.connect('clicked', zoom_callbacks['zoom_in'])
        self.zoom_in_btn.show()
        self.insert(self.zoom_in_btn, -1)

        self.zoom_out_btn = ToolButton('zoom-out')
        self.zoom_out_btn.set_tooltip(_('Zoom out.'))
        self.zoom_out_btn.connect('clicked',  zoom_callbacks['zoom_out'])
        self.zoom_out_btn.show()
        self.insert(self.zoom_out_btn, -1)

        self.callbacks.update(zoom_callbacks)

    def enable_zoom_bestfit(self, on_zoom_bestfit):
        """
        Enables zoom-to-best-fit support on this toolbar.

        @param on_zoom_bestfit: The callback function to be called when user
        wants to zoom to best extent.
        """
        zoom_best_fit_btn = ToolButton('zoom-best-fit')
        zoom_best_fit_btn.set_tooltip(_('Zoom best fitting extent.'))
        zoom_best_fit_btn.connect('clicked', on_zoom_bestfit)
        zoom_best_fit_btn.show()
        self.insert(zoom_best_fit_btn, -1)

    def enable_navigation(self, nav_callbacks):
        """
        Enables tools to navigate the map via buttons.

        @param nav_callbacks: A dict containing navigation callbacks:
                ===========  =============
                nav_callbacks['west']   A callback to step west

                nav_callbacks['north']   A callback to step north

                nav_callbacks['south']   A callback to step south

                nav_callbacks['east']   A callback to step east
                ===========  =============
        """
        self._enable_step_west(nav_callbacks['west'])
        self._enable_step_north(nav_callbacks['north'])
        self._enable_step_south(nav_callbacks['south'])
        self._enable_step_east(nav_callbacks['east'])
        self.callbacks.update(nav_callbacks)

    def enable_custom_Button(self, button):
        """
        Inserts a custom button to the map toolbar.

        Consider to use it only, if it does not make much sense to place
        the button in its own toolbar (e.g. if there will be only one
        button, which might an extra toolbar dispensable).
        """
        self.insert(button, -1)

    def key_pressed_cb(self, widget, event, callbacks):
        """
        Callback handles all incoming keyevents and calls the appropriate
        callback-method.
        """
        keyname = gtk.gdk.keyval_name(event.keyval)
        #self._logger.debug('\'%s\' key pressed' % keyname)
        if(keyname in ['KP_Up']): # up
            self.set_focus_child(self.step_north_btn)
            callbacks['north'](None)
        elif(keyname in ['KP_Down']): # down
            self.set_focus_child(self.step_south_btn)
            callbacks['south'](None)
        elif(keyname in ['KP_Left']): #left
            self.set_focus_child(self.step_west_btn)
            callbacks['west'](None)
        elif(keyname in ['KP_Right']): #right
            self.set_focus_child(self.step_east_btn)
            callbacks['east'](None)
        elif(keyname in ['plus', 'KP_Add', 'KP_Page_Up']): # zoom in
            self.set_focus_child(self.zoom_in_btn)
            callbacks['zoom_in'](None)
        elif(keyname in ['minus', 'KP_Substract', 'KP_Page_Down']): # zoom out
            self.set_focus_child(self.zoom_out_btn)
            callbacks['zoom_out'](None)
        if self.view._CROSSLINES:
            self.view.motion_crosslines(self.view.fixed)

    def _enable_step_north(self, on_step_north):
        """
        Enables button to step north.

        @param on_step_north: The callback function to be called when the user
        wants to step north.
        """
        self.step_north_btn = ToolButton('step-north')
        self.step_north_btn.set_tooltip(_('Move North.'))
        self.step_north_btn.connect('clicked', on_step_north)
        self.step_north_btn.show()
        self.insert(self.step_north_btn, -1)

    def _enable_step_east(self, on_step_east):
        """
        Enables button to step east.

        @param on_step_east: The callback function to be called when the user
        wants to step east.
        """
        self.step_east_btn = ToolButton('step-east')
        self.step_east_btn.set_tooltip(_('Move East.'))
        self.step_east_btn.connect('clicked', on_step_east)
        self.step_east_btn.show()
        self.insert(self.step_east_btn, -1)

    def _enable_step_south(self, on_step_south):
        """
        Enables button to step south.

        @param on_step_south: The callback function to be called when the user
        wants to step south.
        """
        self.step_south_btn = ToolButton('step-south')
        self.step_south_btn.set_tooltip(_('Move South.'))
        self.step_south_btn.connect('clicked', on_step_south)
        self.step_south_btn.show()
        self.insert(self.step_south_btn, -1)

    def _enable_step_west(self, on_step_west):
        """
        Enables button to step west.

        @param on_step_west: The callback function to be called when the user
        wants to step west.
        """
        self.step_west_btn = ToolButton('step-west')
        self.step_west_btn.set_tooltip(_('Move West.'))
        self.step_west_btn.connect('clicked', on_step_west)
        self.step_west_btn.show()
        self.insert(self.step_west_btn, -1)