def format_row(cls, line, indent=0, locale_format=True): row = [] for i, val in enumerate(line): if locale_format: if isinstance(val, Number): val = locale.str(val) elif isinstance(val, datetime.datetime): val = val.strftime(common.date_format() + ' %X') elif isinstance(val, datetime.date): val = val.strftime(common.date_format()) elif isinstance(val, datetime.timedelta): val = common.timedelta.format(val, { 's': 1, 'm': 60, 'h': 60 * 60 }) elif isinstance(val, datetime.timedelta): val = val.total_seconds() elif isinstance(val, bool): val = int(val) if i == 0 and indent and isinstance(val, str): val = ' ' * indent + val if isinstance(val, bytes): val = base64.b64encode(val).decode('utf-8') row.append(val) return row
def format_row(cls, line, locale_format=True): row = [] for val in line: if locale_format: if isinstance(val, Number): val = locale.str(val) elif isinstance(val, datetime.datetime): val = val.strftime(common.date_format() + ' %X') elif isinstance(val, datetime.date): val = val.strftime(common.date_format()) elif isinstance(val, bool): val = int(val) row.append(val) return row
def set_format(self): if self.field and self.record: format_ = self.field.date_format(self.record) else: format_ = common.date_format( self.view.screen.context.get('date_format')) self.entry.props.format = format_
def set_format(self, record, field): if field and record: format_ = field.date_format(record) else: format_ = common.date_format( self.view.screen.context.get('date_format')) self.entry.props.format = format_
def convert_date(): if not value: return format_ = date_format(context.get('date_format')) try: return date_parse(value, format_).date() except (ValueError, TypeError): return
def convert_datetime(): if not value: return format_ = (date_format(context.get('date_format')) + ' ' + time_format(field)) try: dt = date_parse(value, format_) return untimezoned_date(dt) except ValueError: return
def set_format(self): if self.field and self.record: date_format = self.field.date_format(self.record) time_format = self.field.time_format(self.record) else: date_format = common.date_format( self.view.screen.context.get('date_format')) time_format = '%X' self.entry.props.date_format = date_format self.entry.props.time_format = time_format
def format_datetime(): if not value: return '' if not isinstance(value, datetime.datetime): time = datetime.datetime.combine(value, datetime.time.min) else: time = timezoned_date(value) format_ = date_format(context.get('date_format')) if time.time() != datetime.time.min: format_ += ' ' + time_format(field) return time.strftime(format_)
def export_csv(self, fname, fields, data, popup=True): encoding = self.csv_enc.get_active_text() or 'UTF-8' locale_format = self.csv_locale.get_active() try: writer = csv.writer(open(fname, 'w', encoding=encoding, newline=''), quotechar=self.get_quotechar(), delimiter=self.get_delimiter()) if self.add_field_names.get_active(): writer.writerow(fields) for line in data: row = [] for val in line: if locale_format: if isinstance(val, Number): val = locale.str(val) elif isinstance(val, datetime.datetime): val = val.strftime(common.date_format() + ' %X') elif isinstance(val, datetime.date): val = val.strftime(common.date_format()) elif isinstance(val, bool): val = int(val) row.append(val) writer.writerow(row) if popup: if len(data) == 1: common.message(_('%d record saved.') % len(data)) else: common.message(_('%d records saved.') % len(data)) return True except IOError as exception: common.warning( _("Operation failed.\nError message:\n%s") % exception, _('Error')) return False
def import_csv(self, fname, fields): # TODO: make it works with references skip = self.csv_skip.get_value_as_int() encoding = self.get_encoding() locale_format = self.csv_locale.get_active() try: reader = csv.reader(open(fname, 'r', encoding=encoding), quotechar=self.get_quotechar(), delimiter=self.get_delimiter()) data = [] for i, line in enumerate(reader): if i < skip or not line: continue row = [] for field, val in zip(fields, line): if locale_format and val: type_ = self.fields_data[field]['type'] if type_ in ['integer', 'biginteger']: val = locale.atoi(val) elif type_ == 'float': val = locale.atof(val) elif type_ == 'numeric': val = Decimal(locale.delocalize(val)) elif type_ in ['date', 'datetime']: val = date_parse(val, common.date_format()) elif type_ == 'binary': val = base64.b64decode(val) row.append(val) data.append(row) except (IOError, UnicodeDecodeError, csv.Error) as exception: common.warning(str(exception), _("Import failed")) return try: count = RPCExecute('model', self.model, 'import_data', fields, data, context=self.context) except RPCException: return if count == 1: common.message(_('%d record imported.') % count) else: common.message(_('%d records imported.') % count)
def format_date(): if not value: return '' format_ = date_format(context.get('date_format')) return value.strftime(format_)
def search_box(self, widget): def window_hide(window, *args): window.hide() self.search_entry.grab_focus() def key_press(widget, event): if event.keyval == gtk.keysyms.Escape: window_hide(widget) return True return False def search(): self.search_window.hide() text = '' for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Dates, Selection)): value = entry.get_value() else: value = quote(entry.get_text()) or None if value is not None: text += quote(label) + ': ' + value + ' ' self.set_text(text) self.do_search() # Store text after doing the search # because domain parser could simplify the text self.last_search_text = self.get_text() if not self.search_window: self.search_window = gtk.Window() Main().add_window(self.search_window) self.search_window.set_transient_for(widget.get_toplevel()) self.search_window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU) self.search_window.set_destroy_with_parent(True) self.search_window.set_decorated(False) self.search_window.set_deletable(False) self.search_window.connect('delete-event', window_hide) self.search_window.connect('key-press-event', key_press) self.search_window.connect('focus-out-event', window_hide) def toggle_window_hide(combobox, shown): if combobox.props.popup_shown: self.search_window.handler_block_by_func(window_hide) else: self.search_window.handler_unblock_by_func(window_hide) vbox = gtk.VBox() fields = [ f for f in self.screen.domain_parser.fields.values() if f.get('searchable', True) ] self.search_table = gtk.Table(rows=len(fields), columns=2) self.search_table.set_homogeneous(False) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) self.search_table.set_col_spacings(2) # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): label = gtk.Label(field['string']) label.set_alignment(0.0, 0.0) self.search_table.attach(label, 0, 1, i, i + 1, yoptions=gtk.FILL) yoptions = False if field['type'] == 'boolean': if hasattr(gtk, 'ComboBoxText'): entry = gtk.ComboBoxText() else: entry = gtk.combo_box_new_text() entry.connect('notify::popup-shown', toggle_window_hide) entry.append_text('') selections = (_('True'), _('False')) for selection in selections: entry.append_text(selection) elif field['type'] == 'selection': selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) yoptions = gtk.FILL | gtk.EXPAND elif field['type'] in ('date', 'datetime', 'time'): date_format = common.date_format( self.screen.context.get('date_format')) if field['type'] == 'date': entry = Dates(date_format) elif field['type'] in ('datetime', 'time'): time_format = PYSONDecoder({}).decode(field['format']) if field['type'] == 'time': entry = Times(time_format) elif field['type'] == 'datetime': entry = DateTimes(date_format, time_format) entry.connect_activate(lambda *a: search()) entry.connect_combo(toggle_window_hide) else: entry = gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions) self.search_table.fields.append((field['string'], entry)) scrolled = gtk.ScrolledWindow() scrolled.add_with_viewport(self.search_table) scrolled.set_shadow_type(gtk.SHADOW_NONE) scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) vbox.pack_start(scrolled, expand=True, fill=True) find_button = gtk.Button(_('Find')) find_button.connect('clicked', lambda *a: search()) find_button.set_image( common.IconFactory.get_image('tryton-search', gtk.ICON_SIZE_SMALL_TOOLBAR)) hbuttonbox = gtk.HButtonBox() hbuttonbox.set_spacing(5) hbuttonbox.pack_start(find_button) hbuttonbox.set_layout(gtk.BUTTONBOX_END) vbox.pack_start(hbuttonbox, expand=False, fill=True) self.search_window.add(vbox) vbox.show_all() new_size = list( map( sum, list( zip(self.search_table.size_request(), scrolled.size_request())))) self.search_window.set_default_size(*new_size) parent = widget.get_toplevel() widget_x, widget_y = widget.translate_coordinates(parent, 0, 0) widget_allocation = widget.get_allocation() # Resize the window to not be out of the parent width, height = self.search_window.get_default_size() allocation = parent.get_allocation() delta_width = allocation.width - (widget_x + width) delta_height = allocation.height - (widget_y + widget_allocation.height + height) if delta_width < 0: width += delta_width if delta_height < 0: height += delta_height self.search_window.resize(width, height) # Move the window under the button if hasattr(widget.window, 'get_root_coords'): x, y = widget.window.get_root_coords(widget_allocation.x, widget_allocation.y) else: x, y = widget.window.get_origin() self.search_window.move(x, y + widget_allocation.height) self.search_window.show() self.search_window.grab_focus() if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): entry.set_active(-1) elif isinstance(entry, Dates): entry.set_values(None, None) elif isinstance(entry, Selection): entry.treeview.get_selection().unselect_all() else: entry.set_text('') if self.search_table.fields: self.search_table.fields[0][1].grab_focus()
def date_format(self, record): context = self.get_context(record) return common.date_format(context.get('date_format'))
def search_box(self, widget): def window_hide(window, *args): window.hide() self.search_entry.grab_focus() def search(): self.search_popover.popdown() text = '' for label, entry in self.search_grid.fields: if isinstance(entry, Gtk.ComboBoxText): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Between, Selection)): value = entry.get_value() else: value = quote(entry.get_text()) or None if value is not None: text += quote(label) + ': ' + value + ' ' self.set_text(text) self.do_search() # Store text after doing the search # because domain parser could simplify the text self.last_search_text = self.get_text() if not self.search_popover: self.search_popover = Gtk.Popover() self.search_popover.set_relative_to(widget) vbox = Gtk.VBox() fields = [ f for f in self.screen.domain_parser.fields.values() if f.get('searchable', True) and '.' not in f['name'] ] self.search_grid = Gtk.Grid(column_spacing=3, row_spacing=3) # Fill table with fields self.search_grid.fields = [] for i, field in enumerate(fields): label = Gtk.Label(label=field['string'], halign=Gtk.Align.START, valign=Gtk.Align.START) self.search_grid.attach(label, 0, i, 1, 1) if field['type'] == 'boolean': entry = Gtk.ComboBoxText() entry.append_text('') selections = (_('True'), _('False')) for selection in selections: entry.append_text(selection) elif field['type'] in ['selection', 'multiselection']: selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) entry.set_vexpand(True) elif field['type'] in ('date', 'datetime', 'time'): date_format = common.date_format( self.screen.context.get('date_format')) if field['type'] == 'date': entry = Dates(date_format) elif field['type'] in ('datetime', 'time'): time_format = PYSONDecoder({}).decode(field['format']) if field['type'] == 'time': entry = Times(time_format) elif field['type'] == 'datetime': entry = DateTimes(date_format, time_format) entry.connect('activate', lambda *a: search()) elif field['type'] in ['integer', 'float', 'numeric']: entry = Numbers() entry.connect('activate', lambda *a: search()) else: entry = Gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_grid.attach(entry, 1, i, 1, 1) self.search_grid.fields.append((field['string'], entry)) scrolled = Gtk.ScrolledWindow() scrolled.add(self.search_grid) scrolled.set_shadow_type(Gtk.ShadowType.NONE) scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) vbox.pack_start(scrolled, expand=True, fill=True, padding=0) find_button = Gtk.Button(label=_('Find')) find_button.connect('clicked', lambda *a: search()) find_button.set_image( common.IconFactory.get_image('tryton-search', Gtk.IconSize.SMALL_TOOLBAR)) find_button.set_can_default(True) self.search_popover.set_default_widget(find_button) hbuttonbox = Gtk.HButtonBox() hbuttonbox.pack_start(find_button, expand=False, fill=False, padding=0) hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END) vbox.pack_start(hbuttonbox, expand=False, fill=True, padding=0) self.search_popover.add(vbox) vbox.show_all() scrolled.set_size_request( -1, min(self.search_grid.get_preferred_height()[1], 400)) self.search_popover.set_pointing_to( widget.get_icon_area(Gtk.EntryIconPosition.PRIMARY)) self.search_popover.popup() if self.search_grid.fields: self.search_grid.fields[0][1].grab_focus() if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_grid.fields: if isinstance(entry, Gtk.ComboBoxText): entry.set_active(-1) elif isinstance(entry, Between): entry.set_value(None, None) elif isinstance(entry, Selection): entry.treeview.get_selection().unselect_all() else: entry.set_text('')