class ColorSelectDialog(DialogBox): ''' ColorSelectionDialog widget. @undocumented: click_confirm_button @undocumented: click_cancel_button @undocumented: click_rgb_spin @undocumented: press_return_color_entry @undocumented: expose_display_button ''' DEFAULT_COLOR_LIST = ["#000000", "#808080", "#E20417", "#F29300", "#FFEC00", "#95BE0D", "#008F35", "#00968F", "#FFFFFF", "#C0C0C0", "#E2004E", "#E2007A", "#920A7E", "#162883", "#0069B2", "#009DE0"] def __init__(self, confirm_callback=None, cancel_callback=None): ''' Initialize ColorSelectDialog class. @param confirm_callback: Callback when user click OK, this callback accept one argument, color string. @param cancel_callback: Callback when user click cancel, this callback don't accept any argument. ''' DialogBox.__init__(self, _("Select color"), mask_type=DIALOG_MASK_SINGLE_PAGE) self.confirm_callback = confirm_callback self.cancel_callback = cancel_callback self.color_box = gtk.HBox() self.color_align = gtk.Alignment() self.color_align.set(0.5, 0.5, 0.0, 0.0) self.color_align.set_padding(10, 0, 8, 8) self.color_align.add(self.color_box) self.color_hsv = HSV() self.color_string = self.color_hsv.get_color_string() (self.color_r, self.color_g, self.color_b) = self.color_hsv.get_rgb_color() self.color_hsv.get_hsv_widget().connect( "button-release-event", lambda w, e: self.update_color_info(self.color_hsv.get_color_string())) self.color_box.pack_start(self.color_hsv, False, False) self.color_right_box = gtk.VBox() self.color_right_align = gtk.Alignment() self.color_right_align.set(0.5, 0.5, 0.0, 0.0) self.color_right_align.set_padding(8, 0, 0, 0) self.color_right_align.add(self.color_right_box) self.color_box.pack_start(self.color_right_align) self.color_info_box = gtk.HBox() self.color_right_box.pack_start(self.color_info_box, False, False) self.color_display_box = gtk.VBox() self.color_display_button = gtk.Button() self.color_display_button.connect("expose-event", self.expose_display_button) self.color_display_button.set_size_request(70, 49) self.color_display_align = gtk.Alignment() self.color_display_align.set(0.5, 0.5, 1.0, 1.0) self.color_display_align.set_padding(5, 5, 5, 5) self.color_display_align.add(self.color_display_button) self.color_display_box.pack_start(self.color_display_align, False, False, 5) self.color_hex_box = gtk.HBox() self.color_hex_label = Label(_("Color value")) self.color_hex_box.pack_start(self.color_hex_label, False, False, 5) self.color_hex_entry = TextEntry(self.color_string) self.color_hex_entry.entry.check_text = is_hex_color self.color_hex_entry.entry.connect("press-return", self.press_return_color_entry) self.color_hex_entry.set_size(70, 24) self.color_hex_box.pack_start(self.color_hex_entry, False, False, 5) self.color_display_box.pack_start(self.color_hex_box, False, False, 5) self.color_info_box.pack_start(self.color_display_box, False, False, 5) self.color_rgb_box = gtk.VBox() self.color_r_box = gtk.HBox() self.color_r_label = Label(_("Red: ")) self.color_r_spin = SpinBox(self.color_r, 0, 255, 1) self.color_r_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_r_box.pack_start(self.color_r_label, False, False) self.color_r_box.pack_start(self.color_r_spin, False, False) self.color_g_box = gtk.HBox() self.color_g_label = Label(_("Green: ")) self.color_g_spin = SpinBox(self.color_g, 0, 255, 1) self.color_g_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_g_box.pack_start(self.color_g_label, False, False) self.color_g_box.pack_start(self.color_g_spin, False, False) self.color_b_box = gtk.HBox() self.color_b_label = Label(_("Blue: ")) self.color_b_spin = SpinBox(self.color_b, 0, 255, 1) self.color_b_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_b_box.pack_start(self.color_b_label, False, False) self.color_b_box.pack_start(self.color_b_spin, False, False) self.color_rgb_box.pack_start(self.color_r_box, False, False, 8) self.color_rgb_box.pack_start(self.color_g_box, False, False, 8) self.color_rgb_box.pack_start(self.color_b_box, False, False, 8) self.color_info_box.pack_start(self.color_rgb_box, False, False, 5) self.color_select_view = IconView() self.color_select_view.set_size_request(250, 60) self.color_select_view.connect("button-press-item", lambda view, item, x, y: self.update_color_info(item.color, False)) self.color_select_view.draw_mask = self.get_mask_func(self.color_select_view) self.color_select_scrolled_window = ScrolledWindow() for color in self.DEFAULT_COLOR_LIST: self.color_select_view.add_items([ColorItem(color)]) self.color_select_align = gtk.Alignment() self.color_select_align.set(0.5, 0.5, 1.0, 1.0) self.color_select_align.set_padding(10, 5, 6, 5) self.color_select_scrolled_window.add_child(self.color_select_view) self.color_select_scrolled_window.set_size_request(-1, 60) self.color_select_align.add(self.color_select_scrolled_window) self.color_right_box.pack_start(self.color_select_align, True, True) self.confirm_button = Button(_("OK")) self.cancel_button = Button(_("Cancel")) self.confirm_button.connect("clicked", lambda w: self.click_confirm_button()) self.cancel_button.connect("clicked", lambda w: self.click_cancel_button()) self.right_button_box.set_buttons([self.confirm_button, self.cancel_button]) self.body_box.pack_start(self.color_align, True, True) self.update_color_info(self.color_string) def click_confirm_button(self): ''' Wrap callback when user click ok button. ''' if self.confirm_callback != None: self.confirm_callback(self.color_hex_entry.get_text()) self.destroy() def click_cancel_button(self): ''' Wrap callback when user click cancel button. ''' if self.cancel_callback != None: self.cancel_callback() self.destroy() def click_rgb_spin(self): ''' Callback when user click RGB spin. ''' self.update_color_info(color_rgb_to_hex((self.color_r_spin.get_value(), self.color_g_spin.get_value(), self.color_b_spin.get_value()))) def press_return_color_entry(self, entry): ''' Callback when user press `return` key on entry. @param entry: Color input entry. ''' self.update_color_info(entry.get_text()) entry.select_all() def expose_display_button(self, widget, event): ''' Callback for `expose-event` signal. @param widget: Gtk.Widget instance. @param event: Expose event. @return: Always return True ''' # Init. cr = widget.window.cairo_create() rect = widget.allocation cr.set_source_rgb(*color_hex_to_cairo(self.color_string)) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() # Propagate expose. propagate_expose(widget, event) return True def update_color_info(self, color_string, clear_highlight=True): ''' Update color information. @param color_string: Hex color string. @param clear_highlight: Whether clear color select view's highlight status, default is True. ''' self.color_string = color_string (self.color_r, self.color_g, self.color_b) = color_hex_to_rgb(self.color_string) self.color_r_spin.update(self.color_r) self.color_g_spin.update(self.color_g) self.color_b_spin.update(self.color_b) self.color_hex_entry.set_text(self.color_string) if not color_string.startswith("#"): color_string = "#" + color_string self.color_hsv.set_current_color(gtk.gdk.color_parse(color_string)) if clear_highlight: self.color_select_view.clear_highlight() self.color_display_button.queue_draw()
class ColorSelectDialog(DialogBox): ''' ColorSelectionDialog widget. @undocumented: click_confirm_button @undocumented: click_cancel_button @undocumented: click_rgb_spin @undocumented: press_return_color_entry @undocumented: expose_display_button ''' DEFAULT_COLOR_LIST = [ "#000000", "#808080", "#E20417", "#F29300", "#FFEC00", "#95BE0D", "#008F35", "#00968F", "#FFFFFF", "#C0C0C0", "#E2004E", "#E2007A", "#920A7E", "#162883", "#0069B2", "#009DE0" ] def __init__( self, init_color="#FFFFFF", confirm_callback=None, cancel_callback=None, cancel_first=True, ): ''' Initialize ColorSelectDialog class. @param init_color: Initialize color of dialog. @param confirm_callback: Callback when user click OK, this callback accept one argument, color string. @param cancel_callback: Callback when user click cancel, this callback don't accept any argument. @param cancel_first: Set as True if to make cancel button before confirm button, default is True. ''' DialogBox.__init__(self, _("Select color"), mask_type=DIALOG_MASK_SINGLE_PAGE) self.confirm_callback = confirm_callback self.cancel_callback = cancel_callback self.cancel_first = cancel_first self.color_box = gtk.HBox() self.color_align = gtk.Alignment() self.color_align.set(0.5, 0.5, 0.0, 0.0) self.color_align.set_padding(10, 0, 8, 8) self.color_align.add(self.color_box) self.color_hsv = HSV() self.color_string = init_color (self.color_r, self.color_g, self.color_b) = self.color_hsv.get_rgb_color() self.color_hsv.get_hsv_widget().connect( "button-release-event", lambda w, e: self.update_color_info( self.color_hsv.get_color_string())) self.color_box.pack_start(self.color_hsv, False, False) self.color_right_box = gtk.VBox() self.color_right_align = gtk.Alignment() self.color_right_align.set(0.5, 0.5, 0.0, 0.0) self.color_right_align.set_padding(8, 0, 0, 0) self.color_right_align.add(self.color_right_box) self.color_box.pack_start(self.color_right_align) self.color_info_box = gtk.HBox() self.color_right_box.pack_start(self.color_info_box, False, False) self.color_display_box = gtk.VBox() self.color_display_button = gtk.Button() self.color_display_button.connect("expose-event", self.expose_display_button) self.color_display_button.set_size_request(70, 58) self.color_display_align = gtk.Alignment() self.color_display_align.set(0.5, 0.5, 1.0, 1.0) self.color_display_align.set_padding(5, 5, 5, 5) self.color_display_align.add(self.color_display_button) self.color_display_box.pack_start(self.color_display_align, False, False, 5) self.color_hex_box = gtk.HBox() self.color_hex_label = Label(_("Color value")) self.color_hex_box.pack_start(self.color_hex_label, False, False, 5) self.color_hex_entry = InputEntry(self.color_string) self.color_hex_entry.entry.check_text = is_hex_color self.color_hex_entry.entry.connect("press-return", self.press_return_color_entry) self.color_hex_entry.set_size(70, 24) self.color_hex_box.pack_start(self.color_hex_entry, False, False, 5) self.color_display_box.pack_start(self.color_hex_box, False, False, 5) self.color_info_box.pack_start(self.color_display_box, False, False, 5) self.color_rgb_box = gtk.VBox() self.color_r_box = gtk.HBox() self.color_r_label = Label(_("Red: ")) self.color_r_spin = SpinBox(self.color_r, 0, 255, 1, check_text=self.is_color_value) self.color_r_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_r_box.pack_start(self.color_r_label, False, False) self.color_r_box.pack_start(self.color_r_spin, False, False) self.color_g_box = gtk.HBox() self.color_g_label = Label(_("Green: ")) self.color_g_spin = SpinBox(self.color_g, 0, 255, 1, check_text=self.is_color_value) self.color_g_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_g_box.pack_start(self.color_g_label, False, False) self.color_g_box.pack_start(self.color_g_spin, False, False) self.color_b_box = gtk.HBox() self.color_b_label = Label(_("Blue: ")) self.color_b_spin = SpinBox(self.color_b, 0, 255, 1, check_text=self.is_color_value) self.color_b_spin.connect("value-changed", lambda s, v: self.click_rgb_spin()) self.color_b_box.pack_start(self.color_b_label, False, False) self.color_b_box.pack_start(self.color_b_spin, False, False) self.color_rgb_box.pack_start(self.color_r_box, False, False, 8) self.color_rgb_box.pack_start(self.color_g_box, False, False, 8) self.color_rgb_box.pack_start(self.color_b_box, False, False, 8) self.color_info_box.pack_start(self.color_rgb_box, False, False, 5) self.color_select_view = IconView() self.color_select_view.set_size_request(250, 60) self.color_select_view.connect( "button-press-item", lambda view, item, x, y: self.update_color_info(item.color, False)) self.color_select_view.draw_mask = self.get_mask_func( self.color_select_view) self.color_select_scrolled_window = ScrolledWindow() for color in self.DEFAULT_COLOR_LIST: self.color_select_view.add_items([ColorItem(color)]) self.color_select_align = gtk.Alignment() self.color_select_align.set(0.5, 0.5, 1.0, 1.0) self.color_select_align.set_padding(10, 5, 6, 5) self.color_select_scrolled_window.add_child(self.color_select_view) self.color_select_scrolled_window.set_size_request(-1, 60) self.color_select_align.add(self.color_select_scrolled_window) self.color_right_box.pack_start(self.color_select_align, True, True) self.confirm_button = Button(_("OK")) self.cancel_button = Button(_("Cancel")) self.confirm_button.connect("clicked", lambda w: self.click_confirm_button()) self.cancel_button.connect("clicked", lambda w: self.click_cancel_button()) if self.cancel_first: self.right_button_box.set_buttons( [self.cancel_button, self.confirm_button]) else: self.right_button_box.set_buttons( [self.confirm_button, self.cancel_button]) self.body_box.pack_start(self.color_align, True, True) self.update_color_info(self.color_string) def is_color_value(self, string): return len(string) == 0 or (is_int(string) and 0 <= int(string) <= 255) def click_confirm_button(self): ''' Wrap callback when user click ok button. ''' if self.confirm_callback != None: self.confirm_callback(self.color_hex_entry.get_text()) self.destroy() def click_cancel_button(self): ''' Wrap callback when user click cancel button. ''' if self.cancel_callback != None: self.cancel_callback() self.destroy() def click_rgb_spin(self): ''' Callback when user click RGB spin. ''' self.update_color_info( color_rgb_to_hex( (self.color_r_spin.get_value(), self.color_g_spin.get_value(), self.color_b_spin.get_value()))) def press_return_color_entry(self, entry): ''' Callback when user press `return` key on entry. @param entry: Color input entry. ''' self.update_color_info(entry.get_text()) entry.select_all() def expose_display_button(self, widget, event): ''' Callback for `expose-event` signal. @param widget: Gtk.Widget instance. @param event: Expose event. @return: Always return True ''' # Init. cr = widget.window.cairo_create() rect = widget.allocation cr.set_source_rgb(*color_hex_to_cairo(self.color_string)) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.fill() # Propagate expose. propagate_expose(widget, event) return True def update_color_info(self, color_string, clear_highlight=True): ''' Update color information. @param color_string: Hex color string. @param clear_highlight: Whether clear color select view's highlight status, default is True. ''' self.color_string = color_string (self.color_r, self.color_g, self.color_b) = color_hex_to_rgb(self.color_string) self.color_r_spin.update(self.color_r) self.color_g_spin.update(self.color_g) self.color_b_spin.update(self.color_b) self.color_hex_entry.set_text(self.color_string) if not color_string.startswith("#"): color_string = "#" + color_string self.color_hsv.set_current_color(gtk.gdk.color_parse(color_string)) if clear_highlight: self.color_select_view.clear_highlight() self.color_rgb_box.queue_draw() self.color_display_button.queue_draw()
class ImageFileChooser(Gtk.Window): __gsignals__ = { 'response': (GObject.SignalFlags.RUN_FIRST, None, ([int])), } def __init__(self, image_type, title=None, parent=None, categories=None, language=None, translations=None): """ image_type (str) -- A string identifying the images to show, in the case we are using the imagechooser with differnt groups of images. title (str) -- A optional string to display in the main toolbar parent -- the widget calling ObjectChooser categories (dict) -- A dictionary with categories and path associated. language (str) --if is not None, is used to try translate the image file names translations (dict) -- is a list of filenames and translated names """ Gtk.Window.__init__(self) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.set_decorated(False) self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.set_border_width(style.LINE_WIDTH) self.set_has_resize_grip(False) self._selected_object_id = None self._language = language self._translations = translations self.add_events(Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self.connect('visibility-notify-event', self.__visibility_notify_event_cb) self.connect('delete-event', self.__delete_event_cb) self.connect('key-press-event', self.__key_press_event_cb) if parent is None: logging.warning('ObjectChooser: No parent window specified') else: self.connect('realize', self.__realize_cb, parent) screen = Wnck.Screen.get_default() screen.connect('window-closed', self.__window_closed_cb, parent) self._vbox = Gtk.VBox() self.add(self._vbox) self._vbox.show() title_box = TitleBox(title) title_box.close_button.connect('clicked', self.__close_button_clicked_cb) title_box.set_size_request(-1, style.GRID_CELL_SIZE) self._vbox.pack_start(title_box, False, True, 0) title_box.show() title_box.journal_button.connect('clicked', self.__journal_button_clicked_cb) separator = Gtk.HSeparator() self._vbox.pack_start(separator, False, True, 0) separator.show() self._main_path = os.path.join(activity.get_activity_root(), 'data', image_type) if not os.path.exists(self._main_path): os.makedirs(self._main_path) self._image_type = image_type self._toolbar = SearchToolbox(self._main_path, add_back_button=True) self._toolbar.connect('query-changed', self.__query_changed_cb) self._toolbar.connect('go-back', self.__go_back_cb) self._toolbar.set_size_request(-1, style.GRID_CELL_SIZE) self._toolbar.show() self._vbox.pack_start(self._toolbar, False, True, 0) width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2 height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2 self.set_size_request(width, height) self._icon_view = None self._buttons_vbox = None self._categories = categories if categories is None: self.show_icon_view(self._main_path) else: self.show_categories_buttons() def show_categories_buttons(self): if self._icon_view is not None: self._vbox.remove(self._icon_view) self._icon_view = None if self._buttons_vbox is not None: self._vbox.remove(self._buttons_vbox) # if categories are defined, show a list of buttons # with the categories, when the user press a button, # load the images in the catgories path self._buttons_vbox = Gtk.VBox() for category in self._categories.keys(): button = Gtk.Button(category) button.connect('clicked', self.__category_btn_clicked_cb, category) self._buttons_vbox.pack_start(button, False, False, 10) self._buttons_vbox.show_all() self._vbox.pack_start(self._buttons_vbox, True, True, 0) def __category_btn_clicked_cb(self, button, category): category_paths = self._categories[category] # category_paths is a array, but we only can show a single # directory using the datastore backend. # we also want be able to show and search by translated names # the solution is create a cached directory with symlinks to # the media found in the category_paths. If a dictionary data file # is found, the filenames for the links will be translated. if len(category_paths) == 1 and self._translations is None: # if is only one directory and there are not translations # we don't need create the directory with the links origin = category_paths[0] category = origin[origin.rfind('/') + 1:] category_directory = os.path.join(self._main_path, category) if not os.path.exists(category_directory): os.symlink(origin, category_directory) else: if self._translations is None: category_directory = os.path.join(self._main_path, category) else: category_directory = os.path.join( self._main_path, "%s_%s" % (category, self._language)) logging.debug('category_directory %s', category_directory) if not os.path.exists(category_directory): os.makedirs(category_directory) # create links for the media files for category_path in category_paths: for root, dirs, files in os.walk(category_path): for name in files: extension = name[name.rfind('.') + 1:].lower() if extension not in ['jpg', 'png', 'svg']: continue origin = os.path.join(root, name) if self._translations is not None and \ name in self._translations: destination = os.path.join( category_directory, self._translations[name]) else: destination = os.path.join( category_directory, name) if not os.path.exists(destination): os.symlink(origin, destination) self.show_icon_view(category_directory) def show_icon_view(self, path): self._vbox.remove(self._buttons_vbox) self._toolbar.set_path(path) self._icon_view = IconView(self._toolbar) self._icon_view.connect('entry-activated', self.__entry_activated_cb) self._icon_view.connect('clear-clicked', self.__clear_clicked_cb) self._vbox.pack_start(self._icon_view, True, True, 0) self._icon_view.show() self._icon_view.update_with_query(self._toolbar.get_query()) self._toolbar.show() def __go_back_cb(self, toolbar): self.show_categories_buttons() def __realize_cb(self, chooser, parent): self.get_window().set_transient_for(parent) # TODO: Should we disconnect the signal here? def __window_closed_cb(self, screen, window, parent): if window.get_xid() == parent.get_xid(): self.destroy() def __journal_button_clicked_cb(self, button): # use reject to signal open the objectchooser self.emit('response', Gtk.ResponseType.REJECT) def __entry_activated_cb(self, list_view, uid): self._selected_object_id = uid self.emit('response', Gtk.ResponseType.ACCEPT) def __delete_event_cb(self, chooser, event): self.emit('response', Gtk.ResponseType.DELETE_EVENT) def __key_press_event_cb(self, widget, event): keyname = Gdk.keyval_name(event.keyval) if keyname == 'Escape': self.emit('response', Gtk.ResponseType.DELETE_EVENT) def __close_button_clicked_cb(self, button): self.emit('response', Gtk.ResponseType.DELETE_EVENT) def get_selected_object_id(self): return self._selected_object_id def __query_changed_cb(self, toolbar, query): if 'query' in query and len(query['query']) < 3: logging.error('Don\'t query with a filter of less than 3 letters' 'to avoid big querys, slow in the XO-1') return if query['mountpoints'][0] == self._main_path and 'query' not in query: self.show_categories_buttons() return if self._icon_view is None: self.show_icon_view(self._main_path) self._icon_view.update_with_query(query) def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug('Selected volume: %r.', mount_point) self._toolbar.set_mount_point(mount_point) def __visibility_notify_event_cb(self, window, event): logging.debug('visibility_notify_event_cb %r', self) visible = event.get_state() == Gdk.VisibilityState.FULLY_OBSCURED if self._icon_view: self._icon_view.set_is_visible(visible) def __clear_clicked_cb(self, list_view): self._toolbar.clear_query()