class IconEntry(BaseEntry): class Item(SimpleEnum): priority = 0 # (value, just_label) => (label, tooltip) update = None # (old_value) => str or None ask = None # Associated menu item menuitem = None def __init__(self, widgets): super().__init__(widgets) self._value = None self._image = widgets['image'] self._button = widgets['button'] self._button.props.popup = Gtk.Menu() self._widgets_to_disable.append(self._button) self._icon_dialog = None self._path_dialog = None self._current_item = None self._items = [] for priority, (update, ask) in self._get_items(): item = self.Item(priority=priority, update=update, ask=ask) item.menuitem = Gtk.MenuItem() item.menuitem.props.visible = True item.menuitem.props.label = item.update(None, True)[0] item.menuitem.connect('activate', self._on_item_clicked, item) self._button.props.popup.append(item.menuitem) self._items.append(item) self._items.sort(key=lambda i: i.priority) def _get_value(self): return self._value def _set_value(self, value): applied_item = None tooltip = None for item in self._items: if applied_item: label, __ = item.update(None, True) else: label, tooltip = item.update(value, False) if tooltip: applied_item = item item.menuitem.get_child().set_markup(label) if not applied_item: tooltip = C_('option-entry|icon', 'Unrecognized value: {value}').format(value=value) self._button.set_tooltip_markup(tooltip) self._value = value self._current_item = applied_item self._emit_changed() def _get_items(self): return ((0, (self._update_icon, self._ask_icon)), (100, (self._update_image, self._ask_image))) def _on_item_clicked(self, menuitem, item): value = item.ask(self._value if item == self._current_item else None) if value is not None: self._set_value(value) def _update_icon(self, value, just_label=False): if just_label or value is None or not value.startswith('#'): return C_('option-entry|icon', 'Select icon name...'), None name = value[1:] label = C_('option-entry|icon', '<b>Icon: {icon}</b>').format(icon=name) tooltip = label self._image.set_from_icon_name(name, Gtk.IconSize.DIALOG) return label, tooltip def _ask_icon(self, oldvalue): if not self._icon_dialog: self._icon_dialog = IconChooserDialog() self._icon_dialog.props.transient_for = self._image.get_toplevel() if oldvalue: self._icon_dialog.select_icon(oldvalue[1:]) value = None if self._icon_dialog.run() == Gtk.ResponseType.OK: value = '#' + self._icon_dialog.get_selected_icon() self._icon_dialog.hide() return value def _update_image(self, value, just_label=False): if just_label or value is None: return C_('option-entry|icon', 'Select file...'), None if set_image_from_path(self._image, value): label = C_('option-entry|icon', '<b>File: {path}</b>') else: label = C_('option-entry|icon', '<b>File: {path}</b> (failed to load)') return (label.format(path=os.path.basename(value)), label.format(path=value)) def _ask_image(self, oldvalue): if not self._path_dialog: builder = Gtk.Builder() builder.add_from_file(get_data_path('ImageChooserDialog.ui')) self._path_dialog = builder.get_object('dialog') self._path_dialog.props.transient_for = self._image.get_toplevel() self._path_dialog.connect('update-preview', self._on_update_path_preview) preview_size = self._image.props.pixel_size preview = self._path_dialog.props.preview_widget preview.props.pixel_size = preview_size preview.set_size_request(preview_size, preview_size) if oldvalue is not None: self._path_dialog.select_filename(self._value) value = None if self._path_dialog.run() == Gtk.ResponseType.OK: value = self._path_dialog.get_filename() self._path_dialog.hide() return value def _on_update_path_preview(self, chooser): set_image_from_path(chooser.props.preview_widget, chooser.get_filename())
class IconEntry(BaseEntry): def __init__(self, widgets): super(IconEntry, self).__init__(widgets) self._value = None self._image = widgets['image'] self._button = widgets['button'] self._menu = widgets['menu'] self._icon_item = widgets['icon_item'] self._path_item = widgets['path_item'] self._path_dialog = widgets['path_dialog'] self._path_dialog_preview = widgets['path_dialog_preview'] self._icon_dialog = None self._button.connect('toggled', self._on_button_toggled) self._menu.connect('hide', self._on_menu_hide) self._icon_item.connect('activate', self._on_select_icon) self._path_item.connect('activate', self._on_select_path) self._path_dialog.connect( 'update-preview', self._on_update_path_preview) def _get_value(self): return self._value def _set_value(self, value): if value.startswith('#'): self._set_icon(value[1:]) else: self._set_path(value) def _set_icon(self, icon): self._value = '#' + icon self._image.set_from_icon_name(icon, Gtk.IconSize.DIALOG) self._update_menu_items(icon=icon) self._emit_changed() def _set_path(self, path): self._value = path self._image.set_from_file(path) self._update_menu_items(path=path) self._emit_changed() def _update_menu_items(self, icon=None, path=None): if icon: self._icon_item.get_child().set_markup(C_('option-entry|icon', '<b>Icon: {icon}</b>') .format(icon=icon)) else: self._icon_item.get_child().set_markup( C_('option-entry|icon', 'Select icon name...')) if path: self._path_item.get_child()\ .set_markup(C_('option-entry|icon', '<b>File: {path}</b>') .format(path=os.path.basename(path))) else: self._path_item.get_child().set_markup( C_('option-entry|icon', 'Select file...')) def _get_menu_position(self, menu, widget): allocation = widget.get_allocation() x, y = widget.get_window().get_position() x += allocation.x y += allocation.y + allocation.height return (x, y, False) def _on_button_toggled(self, toggle): if toggle.props.active: self._menu.popup(None, None, self._get_menu_position, self._button, 3, Gtk.get_current_event_time()) def _on_menu_hide(self, toggle): self._button.props.active = False def _on_select_icon(self, item): if not self._icon_dialog: self._icon_dialog = IconChooserDialog() self._icon_dialog.props.transient_for = self._image.get_toplevel() if self._value.startswith('#'): self._icon_dialog.select_icon(self._value[1:]) if self._icon_dialog.run() == Gtk.ResponseType.OK: self._set_icon(self._icon_dialog.get_iconname()) self._icon_dialog.hide() def _on_select_path(self, item): self._path_dialog.select_filename(self._value) if self._path_dialog.run() == Gtk.ResponseType.OK: self._set_path(self._path_dialog.get_filename()) self._path_dialog.hide() def _on_update_path_preview(self, chooser): path = chooser.get_filename() if not path or not os.path.isfile(path): self._path_dialog_preview.props.icon_name = 'unknown' return self._path_dialog_preview.set_from_file(path)
class IconEntry(BaseEntry): class Item(SimpleEnum): priority = 0 # (value, just_label) => (label, tooltip) update = None # (old_value) => str or None ask = None # Associated menu item menuitem = None def __init__(self, widgets): super().__init__(widgets) self._value = None self._image = widgets['image'] self._button = widgets['button'] self._button.props.popup = Gtk.Menu() self._icon_dialog = None self._path_dialog = None self._current_item = None self._add_controlled_by_state_widget(self._button) self._items = [] for priority, (update, ask) in self._get_items(): item = self.Item(priority=priority, update=update, ask=ask) item.menuitem = Gtk.MenuItem() item.menuitem.props.visible = True item.menuitem.props.label = item.update(None, True)[0] item.menuitem.connect('activate', self._on_item_clicked, item) self._button.props.popup.append(item.menuitem) self._items.append(item) self._items.sort(key=lambda i: i.priority) def _get_value(self): return self._value def _set_value(self, value): applied_item = None tooltip = None for item in self._items: if applied_item: label, __ = item.update(None, True) else: label, tooltip = item.update(value, False) if tooltip: applied_item = item item.menuitem.get_child().set_markup(label) if not applied_item: tooltip = C_('option-entry|icon', 'Unrecognized value: {value}').format(value=value) self._button.set_tooltip_markup(tooltip) self._value = value self._current_item = applied_item self._emit_changed() def _get_items(self): return ((0, (self._update_icon, self._ask_icon)), (100, (self._update_image, self._ask_image))) def _on_item_clicked(self, menuitem, item): value = item.ask(self._value if item == self._current_item else None) if value is not None: self._set_value(value) def _update_icon(self, value, just_label=False): if just_label or value is None or not value.startswith('#'): return C_('option-entry|icon', 'Select icon name...'), None name = value[1:] label = C_('option-entry|icon', '<b>Icon: {icon}</b>').format(icon=name) tooltip = label self._image.set_from_icon_name(name, Gtk.IconSize.DIALOG) return label, tooltip def _ask_icon(self, oldvalue): if not self._icon_dialog: self._icon_dialog = IconChooserDialog() self._icon_dialog.props.transient_for = self._image.get_toplevel() if oldvalue: self._icon_dialog.select_icon(oldvalue[1:]) value = None if self._icon_dialog.run() == Gtk.ResponseType.OK: value = '#' + self._icon_dialog.get_selected_icon() self._icon_dialog.hide() return value def _update_image(self, value, just_label=False): if just_label or value is None: return C_('option-entry|icon', 'Select file...'), None if set_image_from_path(self._image, value): label = C_('option-entry|icon', '<b>File: {path}</b>') else: label = C_('option-entry|icon', '<b>File: {path}</b> (failed to load)') return (label.format(path=os.path.basename(value)), label.format(path=value)) def _ask_image(self, oldvalue): if not self._path_dialog: builder = Gtk.Builder() builder.add_from_file(get_data_path('ImageChooserDialog.ui')) self._path_dialog = builder.get_object('dialog') self._path_dialog.props.transient_for = self._image.get_toplevel() self._path_dialog.connect('update-preview', self._on_update_path_preview) preview_size = self._image.props.pixel_size preview = self._path_dialog.props.preview_widget preview.props.pixel_size = preview_size preview.set_size_request(preview_size, preview_size) if oldvalue is not None: self._path_dialog.select_filename(self._value) value = None if self._path_dialog.run() == Gtk.ResponseType.OK: value = self._path_dialog.get_filename() self._path_dialog.hide() return value def _on_update_path_preview(self, chooser): set_image_from_path(chooser.props.preview_widget, chooser.get_filename())