class _Container(object): def __init__(self, col=4, homogeneous=False): super().__init__() if col < 0: col = 0 self.col = col self.tooltips = Tooltips() self.tooltips.enable() def add_row(self): raise NotImplementedError def add_col(self): raise NotImplementedError def add(self, widget, attributes): if widget and attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) @staticmethod def constructor(col=4, homogeneous=False): if CONFIG['client.modepda']: col = 1 if col <= 0: return HContainer(col, homogeneous) elif col == 1: return VContainer(col, homogeneous) else: return Container(col, homogeneous)
def toolbar(self): 'Return HBox with the toolbar' hbox = gtk.HBox(spacing=0) tooltips = Tooltips() self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.save_as) tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_select = gtk.Button() img_select = gtk.Image() img_select.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_select.set_image(img_select) self.but_select.set_relief(gtk.RELIEF_NONE) self.but_select.connect('clicked', self.select) tooltips.set_tip(self.but_select, _('Select...')) hbox.pack_start(self.but_select, expand=False, fill=False) self.but_clear = gtk.Button() img_clear = gtk.Image() img_clear.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_clear.set_image(img_clear) self.but_clear.set_relief(gtk.RELIEF_NONE) self.but_clear.connect('clicked', self.clear) tooltips.set_tip(self.but_clear, _('Clear')) hbox.pack_start(self.but_clear, expand=False, fill=False) tooltips.enable() return hbox
def __init__(self, field_name, model_name, attrs=None, format=None): super(Calendar, self).__init__(field_name, model_name, attrs=attrs) if format is None: format = date_format() self.widget = date_widget.ComplexEntry(format, spacing=0) self.entry = self.widget.widget self.entry.set_property('activates_default', True) self.entry.connect('key_press_event', self.sig_key_press) self.entry.connect('activate', self.sig_activate) self.entry.connect('focus-in-event', lambda x, y: self._focus_in()) self.entry.connect('focus-out-event', lambda x, y: self._focus_out()) self.but_open = gtk.Button() img_find = gtk.Image() img_find.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_find) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.cal_open) self.but_open.set_alignment(0.5, 0.5) self.widget.pack_start(self.but_open, expand=False, fill=False) self.widget.set_focus_chain([self.entry]) tooltips = Tooltips() tooltips.set_tip(self.but_open, _('Open the calendar')) tooltips.enable()
def __init__(self, col=4, homogeneous=False): super().__init__() if col < 0: col = 0 self.col = col self.tooltips = Tooltips() self.tooltips.enable()
class Container(object): def __init__(self, col=4): if CONFIG['client.modepda']: col = 1 self.col = col self.table = gtk.Table(1, col) self.table.set_homogeneous(False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable() def add_row(self): height, width = self.last self.table.resize(height + 1, self.col) self.last = (height + 1, 0) def add(self, widget, attributes): height, width = self.last colspan = attributes.get('colspan', 1) if colspan > self.col: colspan = self.col if width + colspan > self.col: self.add_row() height, width = self.last self.last = height, width + colspan if not widget: return yopt = 0 if attributes.get('yexpand'): yopt |= gtk.EXPAND if attributes.get('yfill'): yopt |= gtk.FILL xopt = 0 if attributes.get('xexpand', True): xopt |= gtk.EXPAND if attributes.get('xfill', True): xopt |= gtk.FILL if attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) widget.show_all() self.table.attach(widget, width, width + colspan, height, height + 1, yoptions=yopt, xoptions=xopt, ypadding=1, xpadding=2)
def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame() self.widget.set_label(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) if not attrs.get('no_command', 0.0): hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None
class Container(object): @staticmethod def constructor(col=4, homogeneous=False): if CONFIG['client.modepda']: col = 1 if col <= 0: return HContainer(col, homogeneous) elif col == 1: return VContainer(col, homogeneous) else: return Container(col, homogeneous) def __init__(self, col=4, homogeneous=False): if col < 0: col = 0 self.col = col self.container = Gtk.Grid( column_spacing=3, row_spacing=3, column_homogeneous=homogeneous, row_homogeneous=homogeneous, border_width=3) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable() def add_row(self): height, width = self.last self.last = (height + 1, 0) def add_col(self): height, width = self.last self.last = (height, width + 1) def add(self, widget, attributes): colspan = attributes.get('colspan', 1) if self.col > 0: height, width = self.last if colspan > self.col: colspan = self.col if width + colspan > self.col: self.add_row() else: self.add_col() height, width = self.last self.last = height, width + colspan if not widget: return widget.set_vexpand(bool(attributes.get('yexpand'))) widget.set_hexpand(bool(attributes.get('xexpand', True))) if attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) widget.show_all() self.container.attach(widget, width, height, colspan, 1)
def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.fields = {} self.buttons = {} self.rows = {} self.widget = Gtk.Frame() # FEA#5633 Allow to not display label on group if not attrs.get('no_label', 0.0): label = Gtk.Label(label=set_underline(attrs.get('string', ''))) label.set_use_underline(True) self.widget.set_label_widget(label) self.widget.set_shadow_type(Gtk.ShadowType.OUT) vbox = Gtk.VBox() self.widget.add(vbox) self.grid = Gtk.Grid(column_spacing=3, row_spacing=3) vbox.pack_start(self.grid, expand=True, fill=True, padding=0) hbox = Gtk.HBox() hbox.set_border_width(2) self.wid_text = Gtk.Entry() # JCA: specific no_command = attrs.get('no_command', 0.0) if not no_command: self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0) label.set_mnemonic_widget(self.wid_text) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion( search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = Gtk.Button(can_focus=False) self.but_add.connect('clicked', self._sig_add) self.but_add.add( IconFactory.get_image( 'tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) self.but_add.set_relief(Gtk.ReliefStyle.NONE) hbox.pack_start(self.but_add, expand=False, fill=False, padding=0) vbox.pack_start(hbox, expand=True, fill=True, padding=0) self.tooltips = Tooltips() if not no_command: self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None
def __init__(self, col=4, homogeneous=False): if col < 0: col = 0 self.col = col self.container = Gtk.Grid( column_spacing=3, row_spacing=3, column_homogeneous=homogeneous, row_homogeneous=homogeneous, border_width=3) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable()
def __init__(self, col=4): if CONFIG['client.modepda']: col = 1 self.col = col self.table = gtk.Table(1, col) self.table.set_homogeneous(False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable()
def __init__(self, col=4, homogeneous=False): if col < 0: col = 0 self.col = col self.table = gtk.Table(1, col) self.table.set_homogeneous(homogeneous) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable()
def _add_file_button(self): tooltips = Tooltips() box = Gtk.HBox(spacing=3) self.files.pack_start(box, expand=False, fill=True, padding=0) file_ = Gtk.FileChooserButton(title=_("Select File")) box.pack_start(file_, expand=True, fill=True, padding=0) button = Gtk.Button() button.set_image( IconFactory.get_image('tryton-remove', Gtk.IconSize.BUTTON)) tooltips.set_tip(button, _("Remove File")) button.set_sensitive(False) box.pack_start(button, expand=False, fill=True, padding=0) box.show_all() file_.connect('file-set', self._file_set, button) button.connect('clicked', self._file_remove)
def __init__(self, field_name, model_name, attrs=None): super(Sha, self).__init__(field_name, model_name, attrs=attrs) self.entry.props.visibility = False self.visibility_checkbox = gtk.CheckButton() self.visibility_checkbox.connect('toggled', self.toggle_visibility) Tooltips().set_tip(self.visibility_checkbox, _('Show plain text')) self.widget.pack_start(self.visibility_checkbox, expand=False)
def __init__(self, view, attrs): super(Password, self).__init__(view, attrs) self.entry.props.visibility = False self.visibility_checkbox = gtk.CheckButton() self.visibility_checkbox.connect('toggled', self.toggle_visibility) Tooltips().set_tip(self.visibility_checkbox, _('Show plain text')) self.widget.pack_start(self.visibility_checkbox, expand=False)
def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) if not attrs.get('no_command', 0.0): hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock( 'tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None
def toolbar(self): 'Return HBox with the toolbar' hbox = gtk.HBox(spacing=0) tooltips = Tooltips() self.but_save_as = gtk.Button() self.but_save_as.set_image( common.IconFactory.get_image('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR)) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.save_as) tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_select = gtk.Button() self.but_select.set_image( common.IconFactory.get_image('tryton-search', gtk.ICON_SIZE_SMALL_TOOLBAR)) self.but_select.set_relief(gtk.RELIEF_NONE) self.but_select.connect('clicked', self.select) target_entry = gtk.TargetEntry.new('text/uri-list', 0, 0) self.but_select.drag_dest_set( gtk.DEST_DEFAULT_ALL, [ target_entry, ], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY) self.but_select.connect('drag-data-received', self.select_drag_data_received) tooltips.set_tip(self.but_select, _('Select...')) hbox.pack_start(self.but_select, expand=False, fill=False) self.but_clear = gtk.Button() self.but_clear.set_image( common.IconFactory.get_image('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR)) self.but_clear.set_relief(gtk.RELIEF_NONE) self.but_clear.connect('clicked', self.clear) tooltips.set_tip(self.but_clear, _('Clear')) hbox.pack_start(self.but_clear, expand=False, fill=False) tooltips.enable() return hbox
def toolbar(self): 'Return HBox with the toolbar' hbox = Gtk.HBox(spacing=0) tooltips = Tooltips() self.but_save_as = Gtk.Button() self.but_save_as.set_image( common.IconFactory.get_image('tryton-save', Gtk.IconSize.SMALL_TOOLBAR)) self.but_save_as.set_relief(Gtk.ReliefStyle.NONE) self.but_save_as.connect('clicked', self.save_as) tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False, padding=0) self.but_select = Gtk.Button() self.but_select.set_image( common.IconFactory.get_image('tryton-search', Gtk.IconSize.SMALL_TOOLBAR)) self.but_select.set_relief(Gtk.ReliefStyle.NONE) self.but_select.connect('clicked', self.select) target_entry = Gtk.TargetEntry.new('text/uri-list', 0, 0) self.but_select.drag_dest_set( Gtk.DestDefaults.ALL, [ target_entry, ], Gdk.DragAction.MOVE | Gdk.DragAction.COPY) self.but_select.connect('drag-data-received', self.select_drag_data_received) tooltips.set_tip(self.but_select, _('Select...')) hbox.pack_start(self.but_select, expand=False, fill=False, padding=0) self.but_clear = Gtk.Button() self.but_clear.set_image( common.IconFactory.get_image('tryton-clear', Gtk.IconSize.SMALL_TOOLBAR)) self.but_clear.set_relief(Gtk.ReliefStyle.NONE) self.but_clear.connect('clicked', self.clear) tooltips.set_tip(self.but_clear, _('Clear')) hbox.pack_start(self.but_clear, expand=False, fill=False, padding=0) tooltips.enable() return hbox
def set_column_widget(self, column, field, attributes, arrow=True, align=0.5): hbox = gtk.HBox(False, 2) label = gtk.Label(attributes['string']) if field and self.editable: required = field.attrs.get('required') readonly = field.attrs.get('readonly') common.apply_label_attributes(label, readonly, required) label.show() help = None if field and field.attrs.get('help'): help = field.attrs['help'] elif attributes.get('help'): help = attributes['help'] if help: tooltips = Tooltips() tooltips.set_tip(label, help) tooltips.enable() if arrow: arrow_widget = gtk.Arrow(gtk.ARROW_NONE, gtk.SHADOW_NONE) arrow_widget.show() column.arrow = arrow_widget hbox.pack_start(label, True, True, 0) if arrow: hbox.pack_start(arrow_widget, False, False, 0) column.set_clickable(True) hbox.show() column.set_widget(hbox) column.set_alignment(align)
def set_column_widget(self, column, field, attributes, arrow=True): tooltips = Tooltips() hbox = gtk.HBox(False, 2) label = gtk.Label(attributes['string']) if field and self.editable: required = field.attrs.get('required') readonly = field.attrs.get('readonly') if required or not readonly: attrlist = pango.AttrList() if required: attrlist.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1)) if not readonly: attrlist.change(pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)) label.set_attributes(attrlist) label.show() help = attributes['string'] if field and field.attrs.get('help'): help += '\n' + field.attrs['help'] elif attributes.get('help'): help += '\n' + attributes['help'] tooltips.set_tip(label, help) tooltips.enable() if arrow: arrow_widget = gtk.Arrow(gtk.ARROW_NONE, gtk.SHADOW_NONE) arrow_widget.show() column.arrow = arrow_widget hbox.pack_start(label, True, True, 0) if arrow: hbox.pack_start(arrow_widget, False, False, 0) column.set_clickable(True) hbox.show() column.set_widget(hbox) column.set_alignment(0.5)
def _set_column_widget(self, column, attributes, arrow=True, align=0.5): hbox = Gtk.HBox(homogeneous=False, spacing=2) label = Gtk.Label(label=attributes['string']) field = self.field_attrs.get(attributes['name'], {}) if field and self.view.editable: required = field.get('required') readonly = field.get('readonly') common.apply_label_attributes(label, readonly, required) attrlist = Pango.AttrList() self._format_set(attributes, attrlist) label.set_attributes(attrlist) label.show() help = attributes.get('help') if help: tooltips = Tooltips() tooltips.set_tip(label, help) tooltips.enable() if arrow: arrow_widget = Gtk.Image() arrow_widget.show() column.arrow = arrow_widget hbox.pack_start(label, expand=True, fill=True, padding=0) if arrow: hbox.pack_start(arrow_widget, expand=False, fill=False, padding=0) column.set_clickable(True) hbox.show() column.set_widget(hbox) column.set_alignment(align)
def set_column_widget(column, field, attributes, arrow=True): tooltips = Tooltips() hbox = gtk.HBox(False, 2) label = gtk.Label(attributes['string']) label.show() help = attributes['string'] if field and field.attrs.get('help'): help += '\n' + field.attrs['help'] elif attributes.get('help'): help += '\n' + attributes['help'] tooltips.set_tip(label, help) tooltips.enable() arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_IN) column.arrow = arrow column.arrow_show = False hbox.pack_start(label, True, True, 0) if arrow: hbox.pack_start(arrow, False, False, 0) column.set_clickable(True) hbox.show() column.set_widget(hbox)
class DictWidget(WidgetInterface): def __init__(self, field_name, model_name, attrs=None): super(DictWidget, self).__init__(field_name, model_name, attrs=attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None def _new_remove_btn(self): but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) but_remove.add(img_remove) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.context_get(self.record) value = self.wid_text.get_text() domain = self.field.domain_get(self.record) dom = [('rec_name', 'ilike', '%%%s%%' % value)] if value else [] dom.append(('id', 'not in', [self.keys[f]['id'] for f in self.fields])) try: ids = RPCExecute('model', self.schema_model, 'search', domain + dom, 0, CONFIG['client.limit'], None, context=context) except RPCException: return False def callback(result): if result: self.send_modified() try: new_fields = RPCExecute('model', self.schema_model, 'get_keys', [r[0] for r in result], context=context) except RPCException: new_fields = [] for new_field in new_fields: if new_field['name'] not in self.fields: self.keys[new_field['name']] = new_field self.add_line(new_field['name']) self.wid_text.set_text('') if len(ids) != 1: WinSearch(self.schema_model, callback, sel_multi=True, ids=ids, context=context, domain=domain, new=False) else: callback([(id, None) for id in ids]) def _sig_remove(self, button, key, modified=True): del self.fields[key] del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict( (key, widget.get_value()) for key, widget in self.fields.items()) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any( widget.modified(value) for widget in self.fields.itervalues()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in self.fields.values(): widget.set_readonly(readonly) self.wid_text.set_editable(not readonly) def _set_button_sensitive(self): self.but_add.set_sensitive( bool(not self._readonly and self.attrs.get('create', True))) for button in self.buttons.itervalues(): button.set_sensitive( bool(not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): self.fields[key] = DICT_ENTRIES[self.keys[key]['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment(float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + self.keys[key]['string'] else: text = self.keys[key]['string'] + _(':') label = gtk.Label(text) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % self.keys[key]['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] self.buttons[key] = remove_but def add_key(self, key): context = self.field.context_get(self.record) try: key_ids = RPCExecute('model', self.schema_model, 'search', [('name', '=', key)], 0, CONFIG['client.limit'], None, context=context) self.keys[key] = RPCExecute('model', self.schema_model, 'get_keys', key_ids, context=context)[0] except RPCException: pass def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in self.fields.keys(): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} for key in sorted(value.iterkeys()): val = value[key] if key not in self.keys: self.add_key(key) if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive()
class DictWidget(WidgetInterface): def __init__(self, field_name, model_name, attrs=None): super(DictWidget, self).__init__(field_name, model_name, attrs=attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None def _new_remove_btn(self): but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) but_remove.add(img_remove) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.context_get(self.record) value = self.wid_text.get_text() domain = self.field.domain_get(self.record) dom = [('rec_name', 'ilike', '%%%s%%' % value)] if value else [] dom.append(('id', 'not in', [self.keys[f]['id'] for f in self.fields])) try: ids = RPCExecute('model', self.schema_model, 'search', domain + dom, 0, CONFIG['client.limit'], None, context=context) except RPCException: return False def callback(result): if result: self.send_modified() try: new_fields = RPCExecute('model', self.schema_model, 'get_keys', [r[0] for r in result], context=context) except RPCException: new_fields = [] for new_field in new_fields: if new_field['name'] not in self.fields: self.keys[new_field['name']] = new_field self.add_line(new_field['name']) self.wid_text.set_text('') if len(ids) != 1: WinSearch(self.schema_model, callback, sel_multi=True, ids=ids, context=context, domain=domain, new=False) else: callback([(id, None) for id in ids]) def _sig_remove(self, button, key, modified=True): del self.fields[key] del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict((key, widget.get_value()) for key, widget in self.fields.items()) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any(widget.modified(value) for widget in self.fields.itervalues()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in self.fields.values(): widget.set_readonly(readonly) self.wid_text.set_editable(not readonly) def _set_button_sensitive(self): self.but_add.set_sensitive(bool( not self._readonly and self.attrs.get('create', True))) for button in self.buttons.itervalues(): button.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): self.fields[key] = DICT_ENTRIES[self.keys[key]['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment( float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + self.keys[key]['string'] else: text = self.keys[key]['string'] + _(':') label = gtk.Label(text) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % self.keys[key]['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] self.buttons[key] = remove_but def add_key(self, key): context = self.field.context_get(self.record) try: key_ids = RPCExecute('model', self.schema_model, 'search', [('name', '=', key)], 0, CONFIG['client.limit'], None, context=context) self.keys[key] = RPCExecute('model', self.schema_model, 'get_keys', key_ids, context=context)[0] except RPCException: pass def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in self.fields.keys(): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} for key in sorted(value.iterkeys()): val = value[key] if key not in self.keys: self.add_key(key) if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive()
class Binary(WidgetInterface): "Binary" def __init__(self, field_name, model_name, attrs=None): super(Binary, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.tooltips = Tooltips() self.widget = gtk.HBox(spacing=0) self.wid_size = gtk.Entry() self.wid_size.set_width_chars(10) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): self.wid_text = gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.widget.pack_start(self.wid_text, expand=True, fill=True) else: self.wid_text = None self.widget.pack_start(self.wid_size, expand=not self.filename, fill=True) self.but_new = gtk.Button() img_new = gtk.Image() img_new.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_new.set_image(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) self.but_new.connect('clicked', self.sig_new) self.tooltips.set_tip(self.but_new, _('Select a File...')) self.widget.pack_start(self.but_new, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) self.widget.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) self.widget.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) self.widget.pack_start(self.but_remove, expand=False, fill=False) self.tooltips.enable() @property def filename_field(self): return self.record.group.fields.get(self.filename) def _readonly_set(self, value): if value: self.but_new.hide() self.but_remove.hide() self.widget.set_focus_chain([]) else: self.but_new.show() self.but_remove.show() if self.wid_text: focus_chain = [self.wid_text] elif self.filename: focus_chain = [self.but_new, self.but_open, self.but_save_as, self.but_remove] else: focus_chain = [self.but_new, self.but_save_as, self.but_remove] self.widget.set_focus_chain(focus_chain) def grab_focus(self): if self.wid_text: return self.wid_text.grab_focus() else: return self.wid_size.grab_focus() def sig_new(self, widget=None): filename = file_selection(_('Open...')) if filename and self.field: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) def sig_open(self, widget=None): if not self.filename_field: return dtemp = tempfile.mkdtemp(prefix='tryton_') filename = self.filename_field.get(self.record).replace( os.sep, '_').replace(os.altsep or os.sep, '_') if not filename: return file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: fp.write(self.field.get_data(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def sig_save_as(self, widget=None): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.field.get_data(self.record)) def sig_remove(self, widget=None): self.field.set_client(self.record, False) def sig_key_press(self, widget, event, *args): editable = self.wid_text and self.wid_text.get_editable() if event.keyval == gtk.keysyms.F3 and editable: self.sig_new(widget) return True elif event.keyval == gtk.keysyms.F2: if self.filename: self.sig_open(widget) else: self.sig_save_as(widget) return True return False def display(self, record, field): super(Binary, self).display(record, field) if not field: if self.wid_text: self.wid_text.set_text('') self.wid_size.set_text('') if self.but_open: self.but_open.set_sensitive(False) self.but_save_as.set_sensitive(False) return False if self.wid_text: self.wid_text.set_text(self.filename_field.get(record) or '') self.wid_size.set_text(common.humanize(field.get_size(record) or 0)) if self.but_open: self.but_open.set_sensitive(bool(field.get_size(record))) self.but_save_as.set_sensitive(bool(field.get_size(record))) return True def set_value(self, record, field): if self.wid_text: self.filename_field.set_client(self.record, self.wid_text.get_text() or False) return def _color_widget(self): if self.wid_text: return self.wid_text else: return self.wid_size
def __init__(self, field_name, model_name, attrs=None): super(Binary, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.tooltips = Tooltips() self.widget = gtk.HBox(spacing=0) self.wid_size = gtk.Entry() self.wid_size.set_width_chars(10) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): self.wid_text = gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.widget.pack_start(self.wid_text, expand=True, fill=True) else: self.wid_text = None self.widget.pack_start(self.wid_size, expand=not self.filename, fill=True) self.but_new = gtk.Button() img_new = gtk.Image() img_new.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_new.set_image(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) self.but_new.connect('clicked', self.sig_new) self.tooltips.set_tip(self.but_new, _('Select a File...')) self.widget.pack_start(self.but_new, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) self.widget.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) self.widget.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) self.widget.pack_start(self.but_remove, expand=False, fill=False) self.tooltips.enable()
class DictWidget(Widget): def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None def _new_remove_btn(self): but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) but_remove.add(img_remove) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.context_get(self.record) value = self.wid_text.get_text().decode('utf-8') domain = self.field.domain_get(self.record) def callback(result): if result: self.add_new_keys([r[0] for r in result]) self.wid_text.set_text('') win = WinSearch(self.schema_model, callback, sel_multi=True, context=context, domain=domain, new=False) win.screen.search_filter(quote(value)) win.show() def add_new_keys(self, ids): context = self.field.context_get(self.record) self.send_modified() try: new_fields = RPCExecute('model', self.schema_model, 'get_keys', ids, context=context) except RPCException: new_fields = [] focus = False for new_field in new_fields: if new_field['name'] not in self.fields: self.keys[new_field['name']] = new_field self.add_line(new_field['name']) if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there gobject.idle_add( self.fields[new_field['name']].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): del self.fields[key] del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict((key, widget.get_value()) for key, widget in self.fields.items()) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any(widget.modified(value) for widget in self.fields.itervalues()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in self.fields.values(): widget.set_readonly(readonly) self.wid_text.set_sensitive(not readonly) def _set_button_sensitive(self): self.but_add.set_sensitive(bool( not self._readonly and self.attrs.get('create', True))) for button in self.buttons.itervalues(): button.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): self.fields[key] = DICT_ENTRIES[self.keys[key]['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment( float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + self.keys[key]['string'] else: text = self.keys[key]['string'] + _(':') label = gtk.Label(text) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) label.set_mnemonic_widget(field.widget) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % self.keys[key]['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] self.buttons[key] = remove_but def add_keys(self, keys): context = self.field.context_get(self.record) domain = self.field.domain_get(self.record) batchlen = min(10, CONFIG['client.limit']) for i in xrange(0, len(keys), batchlen): sub_keys = keys[i:i + batchlen] try: key_ids = RPCExecute('model', self.schema_model, 'search', [('name', 'in', sub_keys), domain], 0, CONFIG['client.limit'], None, context=context) if not key_ids: continue values = RPCExecute('model', self.schema_model, 'get_keys', key_ids, context=context) if not values: continue except RPCException: pass self.keys.update({k['name']: k for k in values}) def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in self.fields.keys(): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} new_key_names = set(value.iterkeys()) - set(self.keys) if new_key_names: self.add_keys(list(new_key_names)) for key, val in sorted(value.iteritems()): if key not in self.keys: continue if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive() def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.add_new_keys([record_id]) self.wid_text.set_text('') completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if not self.wid_text.get_editable(): return if not self.record: return update_completion(self.wid_text, self.record, self.field, self.schema_model)
class DictWidget(Widget): def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame() type_ = gtk.SHADOW_NONE # FEA#5633 Allow to not display label on group if not attrs.get('no_label', 0.0): label = gtk.Label(set_underline(attrs.get('string', ''))) label.set_use_underline(True) self.widget.set_label_widget(label) type_ = gtk.SHADOW_OUT self.widget.set_shadow_type(type_) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) no_command = attrs.get('no_command', 0.0) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = gtk.Entry() # JCA: specific if not no_command: self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) label.set_mnemonic_widget(self.wid_text) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) self.but_add.add( IconFactory.get_image('tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() if not no_command: self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None @property def _invalid_widget(self): return self.wid_text def _new_remove_btn(self): but_remove = gtk.Button() but_remove.add( IconFactory.get_image('tryton-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.get_context(self.record) value = self.wid_text.get_text() domain = self.field.domain_get(self.record) def callback(result): if result: self.add_new_keys([r[0] for r in result]) self.wid_text.set_text('') win = WinSearch(self.schema_model, callback, sel_multi=True, context=context, domain=domain, new=False) win.screen.search_filter(quote(value)) win.show() def add_new_keys(self, ids): new_keys = self.field.add_new_keys(ids, self.record) self.send_modified() focus = False for key_name in new_keys: if key_name not in self.fields: self.add_line(key_name) if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there gobject.idle_add(self.fields[key_name].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): del self.fields[key] if not self.attrs.get('no_command', 0.0) and self.buttons.get(key): del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict((key, widget.get_value()) for key, widget in list(self.fields.items())) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any( widget.modified(value) for widget in self.fields.values()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in list(self.fields.values()): widget.set_readonly(readonly) # JCA: Specific if not self.attrs.get('no_command', 0.0): self.wid_text.set_sensitive(not readonly) self.wid_text.set_editable(not readonly) def _set_button_sensitive(self): if not self.attrs.get('no_command', 0.0): self.but_add.set_sensitive( bool(not self._readonly and self.attrs.get('create', True))) for button in self.buttons.values(): button.set_sensitive( bool(not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): key_schema = self.field.keys[key] self.fields[key] = DICT_ENTRIES[key_schema['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment(float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + key_schema['string'] else: text = key_schema['string'] + _(':') label = gtk.Label(set_underline(text)) label.set_use_underline(True) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=4, ypadding=4) label.set_mnemonic_widget(field.widget) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=4, ypadding=3) alignment.show_all() if not self.attrs.get('no_command', 0.0): remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % key_schema['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] else: self.rows[key] = [label, alignment] def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in list(self.fields.keys()): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} new_key_names = set(value.keys()) - set(field.keys) if new_key_names: field.add_keys(list(new_key_names), self.record) decoder = PYSONDecoder() # ABDC: Allow dictschema to be ordered by a sequence value_ordered = OrderedDict() use_sequence = any(x[1].get('sequence_order', None) for x in field.keys.items()) if use_sequence: for skey, svalues in sorted(field.keys.items(), key=lambda x: x[1]['sequence_order']): if skey not in value: continue value_ordered[skey] = value[skey] def _loop_order_hook(): if use_sequence: return value_ordered.items() else: return ((key, val) for key, val in sorted(value.items())) for key, val in _loop_order_hook(): if key not in field.keys: continue if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) key_domain = decoder.decode(self.field.keys[key].get('domain') or '[]') widget_class(widget.widget, 'invalid', not eval_domain(key_domain, value)) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive() def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.add_new_keys([record_id]) self.wid_text.set_text('') completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if not self.wid_text.get_editable(): return if not self.record: return update_completion(self.wid_text, self.record, self.field, self.schema_model)
def __init__(self, field_name, model_name, attrs=None): super(Image, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.height = int(attrs.get('img_height', 100)) self.width = int(attrs.get('img_width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/plain', 0, 0), ('text/uri-list', 0, 1), ("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.tooltips = Tooltips() self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) hbox = gtk.HBox(spacing=0) self.but_add = gtk.Button() img_add = gtk.Image() img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_add.set_image(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) self.but_add.connect('clicked', self.sig_add) self.tooltips.set_tip(self.but_add, _('Select an Image...')) hbox.pack_start(self.but_add, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) hbox.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) hbox.pack_start(self.but_remove, expand=False, fill=False) alignment.add(hbox) self.widget.pack_start(alignment, expand=False, fill=False) else: self.but_add = None self.but_open = None self.but_save_as = None self.but_remove = None self.tooltips.enable() self._readonly = False self.update_img()
def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame() type_ = gtk.SHADOW_NONE # FEA#5633 Allow to not display label on group if not attrs.get('no_label', 0.0): label = gtk.Label(set_underline(attrs.get('string', ''))) label.set_use_underline(True) self.widget.set_label_widget(label) type_ = gtk.SHADOW_OUT self.widget.set_shadow_type(type_) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) no_command = attrs.get('no_command', 0.0) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = gtk.Entry() # JCA: specific if not no_command: self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) label.set_mnemonic_widget(self.wid_text) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) self.but_add.add( IconFactory.get_image('tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() if not no_command: self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None
class Image(Widget): def __init__(self, view, attrs): super(Image, self).__init__(view, attrs) self.filename = attrs.get('filename') self.height = int(attrs.get('height', 100)) self.width = int(attrs.get('width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/plain', 0, 0), ('text/uri-list', 0, 1), ("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.tooltips = Tooltips() self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) hbox = gtk.HBox(spacing=0) self.but_add = gtk.Button() img_add = gtk.Image() img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_add.set_image(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) self.but_add.connect('clicked', self.sig_add) self.tooltips.set_tip(self.but_add, _('Select an Image...')) hbox.pack_start(self.but_add, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) hbox.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) hbox.pack_start(self.but_remove, expand=False, fill=False) alignment.add(hbox) self.widget.pack_start(alignment, expand=False, fill=False) else: self.but_add = None self.but_open = None self.but_save_as = None self.but_remove = None self.tooltips.enable() self._readonly = False self.update_img() @property def filename_field(self): return self.record.group.fields.get(self.filename) def _readonly_set(self, value): self._readonly = value if self.but_add: self.but_add.set_sensitive(not value) if self.but_open: self.but_open.set_sensitive(not value) if self.but_save_as: self.but_save_as.set_sensitive(not value) if self.but_remove: self.but_remove.set_sensitive(not value) def sig_add(self, widget): filter_all = gtk.FileFilter() filter_all.set_name(_('All files')) filter_all.add_pattern("*") filter_image = gtk.FileFilter() filter_image.set_name(_('Images')) for mime in ("image/png", "image/jpeg", "image/gif"): filter_image.add_mime_type(mime) for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"): filter_image.add_pattern(pat) filename = file_selection(_('Open...'), preview=True, filters=[filter_image, filter_all]) if filename: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) self.update_img() def sig_open(self, widget=None): if not self.filename_field: return dtemp = tempfile.mkdtemp(prefix='tryton_') filename = self.filename_field.get(self.record) if not filename: return root, ext = os.path.splitext(filename) filename = ''.join([slugify(root), os.extsep, slugify(ext)]) file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: fp.write(self.field.get_data(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def sig_save_as(self, widget): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.field.get_data(self.record)) def sig_remove(self, widget): self.field.set_client(self.record, False) self.update_img() def drag_motion(self, widget, context, x, y, timestamp): if self._readonly: return False context.drag_status(gtk.gdk.ACTION_COPY, timestamp) return True def drag_data_received(self, widget, context, x, y, selection, info, timestamp): if self._readonly: return if info == 0: uri = selection.get_text().split('\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 1: uri = selection.data.split('\r\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 2: data = selection.get_pixbuf() if data: self.field.set_client(self.record, data) self.update_img() def update_img(self): value = None if self.field: value = self.field.get_client(self.record) if isinstance(value, (int, long)): if value > BIG_IMAGE_SIZE: value = False else: value = self.field.get_data(self.record) pixbuf = resize_pixbuf(data2pixbuf(value), self.width, self.height) self.image.set_from_pixbuf(pixbuf) def display(self, record, field): if not field: return False super(Image, self).display(record, field) self.update_img()
def __init__(self, field_name, model_name, attrs=None): super(Image, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.height = int(attrs.get('img_height', 100)) self.width = int(attrs.get('img_width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ ('text/plain', 0, 0), ('text/uri-list', 0, 1), ("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.tooltips = Tooltips() self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) hbox = gtk.HBox(spacing=0) self.but_add = gtk.Button() # img_add = gtk.Image() # img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) # self.but_add.set_image(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) self.but_add.connect('clicked', self.sig_add) self.tooltips.set_tip(self.but_add, _('Select an Image...')) hbox.pack_start(self.but_add, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) hbox.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) hbox.pack_start(self.but_remove, expand=False, fill=False) alignment.add(hbox) self.widget.pack_start(alignment, expand=False, fill=False) else: self.but_add = None self.but_open = None self.but_save_as = None self.but_remove = None self.tooltips.enable() self._readonly = False self.update_img()
class Image(WidgetInterface): def __init__(self, field_name, model_name, attrs=None): super(Image, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.height = int(attrs.get('img_height', 100)) self.width = int(attrs.get('img_width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ ('text/plain', 0, 0), ('text/uri-list', 0, 1), ("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.tooltips = Tooltips() self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) hbox = gtk.HBox(spacing=0) self.but_add = gtk.Button() # img_add = gtk.Image() # img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) # self.but_add.set_image(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) self.but_add.connect('clicked', self.sig_add) self.tooltips.set_tip(self.but_add, _('Select an Image...')) hbox.pack_start(self.but_add, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) hbox.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) hbox.pack_start(self.but_remove, expand=False, fill=False) alignment.add(hbox) self.widget.pack_start(alignment, expand=False, fill=False) else: self.but_add = None self.but_open = None self.but_save_as = None self.but_remove = None self.tooltips.enable() self._readonly = False self.update_img() @property def filename_field(self): return self.record.group.fields.get(self.filename) def grab_focus(self): return self.image.grab_focus() def _readonly_set(self, value): self._readonly = value if self.but_add: self.but_add.set_sensitive(not value) if self.but_open: self.but_open.set_sensitive(not value) if self.but_save_as: self.but_save_as.set_sensitive(not value) if self.but_remove: self.but_remove.set_sensitive(not value) def sig_add(self, widget): filter_all = gtk.FileFilter() filter_all.set_name(_('All files')) filter_all.add_pattern("*") filter_image = gtk.FileFilter() filter_image.set_name(_('Images')) for mime in ("image/png", "image/jpeg", "image/gif"): filter_image.add_mime_type(mime) for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"): filter_image.add_pattern(pat) filename = file_selection(_('Open...'), preview=True, filters=[filter_image, filter_all]) if filename: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) self.update_img() def sig_open(self, widget=None): if not self.filename_field: return dtemp = tempfile.mkdtemp(prefix='tryton_') filename = self.filename_field.get(self.record).replace( os.sep, '_').replace(os.altsep or os.sep, '_') file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: fp.write(self.field.get_data(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def sig_save_as(self, widget): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.field.get_data(self.record)) def sig_remove(self, widget): self.field.set_client(self.record, False) self.update_img() def drag_motion(self, widget, context, x, y, timestamp): if self._readonly: return False context.drag_status(gtk.gdk.ACTION_COPY, timestamp) return True def drag_data_received(self, widget, context, x, y, selection, info, timestamp): if self._readonly: return if info == 0: uri = selection.get_text().split('\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 1: uri = selection.data.split('\r\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 2: data = selection.get_pixbuf() if data: self.field.set_client(self.record, data) self.update_img() def update_img(self): value = None if self.field: value = self.field.get_client(self.record) if isinstance(value, (int, long)): if value > 10 ** 6: value = False else: value = self.field.get_data(self.record) if not value: data = NOIMAGE else: data = value pixbuf = None for ftype in ('jpeg', 'gif', 'png', 'bmp', 'svg'): try: loader = gtk.gdk.PixbufLoader(ftype) loader.write(data, len(data)) loader.close() pixbuf = loader.get_pixbuf() except glib.GError: continue if pixbuf: break if not pixbuf: loader = gtk.gdk.PixbufLoader('png') loader.write(NOIMAGE, len(NOIMAGE)) loader.close() pixbuf = loader.get_pixbuf() img_height = pixbuf.get_height() if img_height > self.height: height = self.height else: height = img_height img_width = pixbuf.get_width() if img_width > self.width: width = self.width else: width = img_width if (img_width / width) < (img_height / height): width = float(img_width) / float(img_height) * float(height) else: height = float(img_height) / float(img_width) * float(width) scaled = pixbuf.scale_simple(int(width), int(height), gtk.gdk.INTERP_BILINEAR) self.image.set_from_pixbuf(scaled) def display(self, record, field): if not field: return False super(Image, self).display(record, field) self.update_img()
class Image(WidgetInterface): def __init__(self, field_name, model_name, attrs=None): super(Image, self).__init__(field_name, model_name, attrs=attrs) self.filename = attrs.get('filename') self.height = int(attrs.get('img_height', 100)) self.width = int(attrs.get('img_width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/plain', 0, 0), ('text/uri-list', 0, 1), ("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.tooltips = Tooltips() self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) hbox = gtk.HBox(spacing=0) self.but_add = gtk.Button() img_add = gtk.Image() img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_add.set_image(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) self.but_add.connect('clicked', self.sig_add) self.tooltips.set_tip(self.but_add, _('Select an Image...')) hbox.pack_start(self.but_add, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) hbox.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) hbox.pack_start(self.but_remove, expand=False, fill=False) alignment.add(hbox) self.widget.pack_start(alignment, expand=False, fill=False) else: self.but_add = None self.but_open = None self.but_save_as = None self.but_remove = None self.tooltips.enable() self._readonly = False self.update_img() @property def filename_field(self): return self.record.group.fields.get(self.filename) def grab_focus(self): return self.image.grab_focus() def _readonly_set(self, value): self._readonly = value if self.but_add: self.but_add.set_sensitive(not value) if self.but_open: self.but_open.set_sensitive(not value) if self.but_save_as: self.but_save_as.set_sensitive(not value) if self.but_remove: self.but_remove.set_sensitive(not value) def sig_add(self, widget): filter_all = gtk.FileFilter() filter_all.set_name(_('All files')) filter_all.add_pattern("*") filter_image = gtk.FileFilter() filter_image.set_name(_('Images')) for mime in ("image/png", "image/jpeg", "image/gif"): filter_image.add_mime_type(mime) for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"): filter_image.add_pattern(pat) filename = file_selection(_('Open...'), preview=True, filters=[filter_image, filter_all]) if filename: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) self.update_img() def sig_open(self, widget=None): if not self.filename_field: return dtemp = tempfile.mkdtemp(prefix='tryton_') filename = self.filename_field.get(self.record).replace( os.sep, '_').replace(os.altsep or os.sep, '_') file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: fp.write(self.field.get_data(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def sig_save_as(self, widget): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.field.get_data(self.record)) def sig_remove(self, widget): self.field.set_client(self.record, False) self.update_img() def drag_motion(self, widget, context, x, y, timestamp): if self._readonly: return False context.drag_status(gtk.gdk.ACTION_COPY, timestamp) return True def drag_data_received(self, widget, context, x, y, selection, info, timestamp): if self._readonly: return if info == 0: uri = selection.get_text().split('\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 1: uri = selection.data.split('\r\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 2: data = selection.get_pixbuf() if data: self.field.set_client(self.record, data) self.update_img() def update_img(self): value = None if self.field: value = self.field.get_client(self.record) if isinstance(value, (int, long)): if value > 10**6: value = False else: value = self.field.get_data(self.record) if not value: data = NOIMAGE else: data = value pixbuf = None for ftype in ('jpeg', 'gif', 'png', 'bmp', 'svg'): try: loader = gtk.gdk.PixbufLoader(ftype) loader.write(data, len(data)) loader.close() pixbuf = loader.get_pixbuf() except glib.GError: continue if pixbuf: break if not pixbuf: loader = gtk.gdk.PixbufLoader('png') loader.write(NOIMAGE, len(NOIMAGE)) loader.close() pixbuf = loader.get_pixbuf() img_height = pixbuf.get_height() if img_height > self.height: height = self.height else: height = img_height img_width = pixbuf.get_width() if img_width > self.width: width = self.width else: width = img_width if (img_width / width) < (img_height / height): width = float(img_width) / float(img_height) * float(height) else: height = float(img_height) / float(img_width) * float(width) scaled = pixbuf.scale_simple(int(width), int(height), gtk.gdk.INTERP_BILINEAR) self.image.set_from_pixbuf(scaled) def display(self, record, field): if not field: return False super(Image, self).display(record, field) self.update_img()
class Binary(Widget): "Binary" def __init__(self, view, attrs): super(Binary, self).__init__(view, attrs) self.filename = attrs.get('filename') self.tooltips = Tooltips() self.widget = gtk.HBox(spacing=0) self.wid_size = gtk.Entry() self.wid_size.set_width_chars(10) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): self.wid_text = gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.widget.pack_start(self.wid_text, expand=True, fill=True) else: self.wid_text = None self.widget.pack_start(self.wid_size, expand=not self.filename, fill=True) self.but_new = gtk.Button() img_new = gtk.Image() img_new.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_new.set_image(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) self.but_new.connect('clicked', self.sig_new) self.tooltips.set_tip(self.but_new, _('Select a File...')) self.widget.pack_start(self.but_new, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) self.widget.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) self.widget.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) self.widget.pack_start(self.but_remove, expand=False, fill=False) self.last_open_file = None self.tooltips.enable() @property def filename_field(self): return self.record.group.fields.get(self.filename) def _readonly_set(self, value): if value: self.but_new.hide() self.but_remove.hide() self.widget.set_focus_chain([]) else: self.but_new.show() self.but_remove.show() if self.wid_text: focus_chain = [self.wid_text] elif self.filename: focus_chain = [ self.but_new, self.but_open, self.but_save_as, self.but_remove ] else: focus_chain = [self.but_new, self.but_save_as, self.but_remove] self.widget.set_focus_chain(focus_chain) def sig_new(self, widget=None): filename = '' if self.last_open_file: last_id, last_filename = self.last_open_file if last_id == self.record.id: filename = last_filename filename = file_selection(_('Open...'), filename=filename) if filename and self.field: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) def sig_open(self, widget=None): if not self.filename_field: return dtemp = tempfile.mkdtemp(prefix='tryton_') filename = self.filename_field.get(self.record) if not filename: return root, ext = os.path.splitext(filename) filename = ''.join([slugify(root), os.extsep, slugify(ext)]) file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: if hasattr(self.field, 'get_data'): fp.write(self.field.get_data(self.record)) else: fp.write(self.field.get(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) self.last_open_file = (self.record.id, file_path) def sig_save_as(self, widget=None): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: if hasattr(self.field, 'get_data'): fp.write(self.field.get_data(self.record)) else: fp.write(self.field.get(self.record)) def sig_remove(self, widget=None): self.field.set_client(self.record, False) def sig_key_press(self, widget, event, *args): editable = self.wid_text and self.wid_text.get_editable() if event.keyval == gtk.keysyms.F3 and editable: self.sig_new(widget) return True elif event.keyval == gtk.keysyms.F2: if self.filename: self.sig_open(widget) else: self.sig_save_as(widget) return True return False def display(self, record, field): super(Binary, self).display(record, field) if not field: if self.wid_text: self.wid_text.set_text('') self.wid_size.set_text('') if self.but_open: self.but_open.set_sensitive(False) self.but_save_as.set_sensitive(False) return False if self.wid_text: self.wid_text.set_text(self.filename_field.get(record) or '') if hasattr(field, 'get_size'): size = field.get_size(record) else: size = len(field.get(record)) self.wid_size.set_text(common.humanize(size or 0)) if self.but_open: self.but_open.set_sensitive(bool(size)) self.but_save_as.set_sensitive(bool(size)) return True def set_value(self, record, field): if self.wid_text: self.filename_field.set_client(self.record, self.wid_text.get_text() or False) return def _color_widget(self): if self.wid_text: return self.wid_text else: return self.wid_size
class DictWidget(Widget): def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.fields = {} self.buttons = {} self.rows = {} self.widget = Gtk.Frame() # FEA#5633 Allow to not display label on group if not attrs.get('no_label', 0.0): label = Gtk.Label(label=set_underline(attrs.get('string', ''))) label.set_use_underline(True) self.widget.set_label_widget(label) self.widget.set_shadow_type(Gtk.ShadowType.OUT) vbox = Gtk.VBox() self.widget.add(vbox) self.grid = Gtk.Grid(column_spacing=3, row_spacing=3) vbox.pack_start(self.grid, expand=True, fill=True, padding=0) hbox = Gtk.HBox() hbox.set_border_width(2) self.wid_text = Gtk.Entry() # JCA: specific no_command = attrs.get('no_command', 0.0) if not no_command: self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0) label.set_mnemonic_widget(self.wid_text) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion( search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = Gtk.Button(can_focus=False) self.but_add.connect('clicked', self._sig_add) self.but_add.add( IconFactory.get_image( 'tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) self.but_add.set_relief(Gtk.ReliefStyle.NONE) hbox.pack_start(self.but_add, expand=False, fill=False, padding=0) vbox.pack_start(hbox, expand=True, fill=True, padding=0) self.tooltips = Tooltips() if not no_command: self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None @property def _invalid_widget(self): return self.wid_text def _new_remove_btn(self): but_remove = Gtk.Button() but_remove.add( IconFactory.get_image('tryton-remove', Gtk.IconSize.SMALL_TOOLBAR)) but_remove.set_relief(Gtk.ReliefStyle.NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.get_context(self.record) value = self.wid_text.get_text() domain = self.field.domain_get(self.record) def callback(result): if result: self.add_new_keys([r[0] for r in result]) self.wid_text.set_text('') win = WinSearch(self.schema_model, callback, sel_multi=True, context=context, domain=domain, new=False) win.screen.search_filter(quote(value)) win.show() def add_new_keys(self, ids): new_keys = self.field.add_new_keys(ids, self.record) self.send_modified() focus = False for key_name in new_keys: if key_name not in self.fields: self.add_line(key_name) if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there GLib.idle_add(self.fields[key_name].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): del self.fields[key] if not self.attrs.get('no_command', 0.0) and self.buttons.get(key): del self.buttons[key] for widget in self.rows[key]: self.grid.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value() def set_value(self): self.field.set_client(self.record, self.get_value()) def get_value(self): return dict((key, widget.get_value()) for key, widget in list(self.fields.items())) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any(widget.modified(value) for widget in self.fields.values()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in list(self.fields.values()): widget.set_readonly(readonly) # JCA: Specific if not self.attrs.get('no_command', 0.0): self.wid_text.set_sensitive(not readonly) self.wid_text.set_editable(not readonly) def _set_button_sensitive(self): if not self.attrs.get('no_command', 0.0): self.but_add.set_sensitive(bool( not self._readonly and self.attrs.get('create', True))) for button in self.buttons.values(): button.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): key_schema = self.field.keys[key] self.fields[key] = DICT_ENTRIES[key_schema['type_']](key, self) field = self.fields[key] text = key_schema['string'] + _(':') label = Gtk.Label( label=set_underline(text), use_underline=True, halign=Gtk.Align.END) self.grid.attach_next_to( label, None, Gtk.PositionType.BOTTOM, 1, 1) label.set_mnemonic_widget(field.widget) label.show() hbox = Gtk.HBox(hexpand=True) hbox.pack_start( field.widget, expand=field.expand, fill=field.fill, padding=0) self.grid.attach_next_to( hbox, label, Gtk.PositionType.RIGHT, 1, 1) hbox.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % key_schema['string']) self.grid.attach_next_to( remove_but, hbox, Gtk.PositionType.RIGHT, 1, 1) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, hbox, remove_but] self.buttons[key] = remove_but def display(self): super(DictWidget, self).display() if not self.field: return record_id = self.record.id if self.record else None if record_id != self._record_id: for key in list(self.fields.keys()): self._sig_remove(None, key, modified=False) self._record_id = record_id value = self.field.get_client(self.record) if self.field else {} new_key_names = set(value.keys()) - set(self.field.keys) if new_key_names: self.field.add_keys(list(new_key_names), self.record) decoder = PYSONDecoder() # ABDC: Allow dictschema to be ordered by a sequence value_ordered = OrderedDict() use_sequence = any( x[1].get('sequence_order', None) for x in self.field.keys.items()) if use_sequence: for skey, svalues in sorted(self.field.keys.items(), key=lambda x: x[1]['sequence_order']): if skey not in value: continue value_ordered[skey] = value[skey] def _loop_order_hook(): if use_sequence: return value_ordered.items() else: return ((key, val) for key, val in sorted(value.items())) for key, val in _loop_order_hook(): if key not in self.field.keys: continue if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) key_domain = decoder.decode( self.field.keys[key].get('domain') or '[]') widget_class( widget.widget, 'invalid', not eval_domain(key_domain, value)) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive() def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.add_new_keys([record_id]) self.wid_text.set_text('') completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if not self.wid_text.get_editable(): return if not self.record: return update_completion(self.wid_text, self.record, self.field, self.schema_model)
def __init__(self, view, attrs): super(Binary, self).__init__(view, attrs) self.filename = attrs.get('filename') self.tooltips = Tooltips() self.widget = gtk.HBox(spacing=0) self.wid_size = gtk.Entry() self.wid_size.set_width_chars(10) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): self.wid_text = gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.widget.pack_start(self.wid_text, expand=True, fill=True) else: self.wid_text = None self.widget.pack_start(self.wid_size, expand=not self.filename, fill=True) self.but_new = gtk.Button() img_new = gtk.Image() img_new.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_new.set_image(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) self.but_new.connect('clicked', self.sig_new) self.tooltips.set_tip(self.but_new, _('Select a File...')) self.widget.pack_start(self.but_new, expand=False, fill=False) if self.filename: self.but_open = gtk.Button() img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_open.set_image(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) self.but_open.connect('clicked', self.sig_open) self.tooltips.set_tip(self.but_open, _('Open...')) self.widget.pack_start(self.but_open, expand=False, fill=False) else: self.but_open = None self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.sig_save_as) self.tooltips.set_tip(self.but_save_as, _('Save As...')) self.widget.pack_start(self.but_save_as, expand=False, fill=False) self.but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_remove.set_image(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) self.but_remove.connect('clicked', self.sig_remove) self.tooltips.set_tip(self.but_remove, _('Clear')) self.widget.pack_start(self.but_remove, expand=False, fill=False) self.last_open_file = None self.tooltips.enable()
class DictWidget(Widget): def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame() self.widget.set_label(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None def _new_remove_btn(self): but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) but_remove.add(img_remove) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.get_context(self.record) value = self.wid_text.get_text().decode('utf-8') domain = self.field.domain_get(self.record) def callback(result): if result: self.add_new_keys([r[0] for r in result]) self.wid_text.set_text('') win = WinSearch(self.schema_model, callback, sel_multi=True, context=context, domain=domain, new=False) win.screen.search_filter(quote(value)) win.show() def add_new_keys(self, ids): context = self.field.get_context(self.record) self.send_modified() try: new_fields = RPCExecute('model', self.schema_model, 'get_keys', ids, context=context) except RPCException: new_fields = [] focus = False for new_field in new_fields: if new_field['name'] not in self.fields: self.keys[new_field['name']] = new_field self.add_line(new_field['name']) if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there gobject.idle_add( self.fields[new_field['name']].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): del self.fields[key] del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict( (key, widget.get_value()) for key, widget in self.fields.items()) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any( widget.modified(value) for widget in self.fields.itervalues()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in self.fields.values(): widget.set_readonly(readonly) self.wid_text.set_sensitive(not readonly) def _set_button_sensitive(self): self.but_add.set_sensitive( bool(not self._readonly and self.attrs.get('create', True))) for button in self.buttons.itervalues(): button.set_sensitive( bool(not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): self.fields[key] = DICT_ENTRIES[self.keys[key]['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment(float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + self.keys[key]['string'] else: text = self.keys[key]['string'] + _(':') label = gtk.Label(text) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) label.set_mnemonic_widget(field.widget) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % self.keys[key]['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] self.buttons[key] = remove_but def add_keys(self, keys): context = self.field.get_context(self.record) domain = self.field.domain_get(self.record) batchlen = min(10, CONFIG['client.limit']) for i in xrange(0, len(keys), batchlen): sub_keys = keys[i:i + batchlen] try: key_ids = RPCExecute('model', self.schema_model, 'search', [('name', 'in', sub_keys), domain], 0, CONFIG['client.limit'], None, context=context) except RPCException: key_ids = [] if not key_ids: continue try: values = RPCExecute('model', self.schema_model, 'get_keys', key_ids, context=context) except RPCException: values = [] if not values: continue self.keys.update({k['name']: k for k in values}) def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in self.fields.keys(): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} new_key_names = set(value.iterkeys()) - set(self.keys) if new_key_names: self.add_keys(list(new_key_names)) for key, val in sorted(value.iteritems()): if key not in self.keys: continue if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive() def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.add_new_keys([record_id]) self.wid_text.set_text('') completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if not self.wid_text.get_editable(): return if not self.record: return update_completion(self.wid_text, self.record, self.field, self.schema_model)
class Container(object): @staticmethod def constructor(col=4, homogeneous=False): if CONFIG['client.modepda']: col = 1 if col <= 0: return HContainer(col, homogeneous) elif col == 1: return VContainer(col, homogeneous) else: return Container(col, homogeneous) def __init__(self, col=4, homogeneous=False): if col < 0: col = 0 self.col = col self.table = gtk.Table(1, col) self.table.set_homogeneous(homogeneous) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable() def add_row(self): height, width = self.last self.table.resize(height + 1, self.col or width) self.last = (height + 1, 0) def add_col(self): height, width = self.last self.table.resize(height or 1, width + 1) self.last = (height, width + 1) def add(self, widget, attributes): colspan = attributes.get('colspan', 1) if self.col > 0: height, width = self.last if colspan > self.col: colspan = self.col if width + colspan > self.col: self.add_row() else: self.add_col() height, width = self.last self.last = height, width + colspan if not widget: return yopt = 0 if attributes.get('yexpand'): yopt = gtk.EXPAND if attributes.get('yfill'): if yopt: yopt |= gtk.FILL else: yopt = gtk.FILL xopt = 0 if attributes.get('xexpand', True): xopt = gtk.EXPAND if attributes.get('xfill', True): if xopt: xopt |= gtk.FILL else: xopt = gtk.FILL if attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) widget.show_all() self.table.attach(widget, width, width + colspan, height, height + 1, yoptions=yopt, xoptions=xopt, ypadding=1, xpadding=2)