From c7dbcbf40d42e962e187f3dbd52c257c99ab5131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 23 Mar 2010 11:00:40 +0100 Subject: [PATCH] Use ir.attachment view instead of a custom one Update to use the new resource field on ir.attachment --- CHANGELOG | 1 + tryton/gui/window/attachment.py | 417 +------------------- tryton/gui/window/view_form/model/record.py | 3 +- 3 files changed, 16 insertions(+), 405 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8a744f68e0..6145f76039 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use ir.attachment view instead of a custom one * Add fingerprint and CA check for SSL connection * Use lazy load in Import/Export windows * Validate record before switching view diff --git a/tryton/gui/window/attachment.py b/tryton/gui/window/attachment.py index 55652350b8..86cdc3566d 100644 --- a/tryton/gui/window/attachment.py +++ b/tryton/gui/window/attachment.py @@ -1,415 +1,26 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. "Attachment" -import gtk -import gobject -import gettext -import copy -import os -import base64 -import urllib -import tempfile -from tryton.gui.window.view_tree.parse import Parse -import tryton.rpc as rpc -import tryton.common as common -from tryton.config import TRYTON_ICON - -_ = gettext.gettext +from tryton.gui.window.view_form.screen import Screen +from tryton.gui.window.win_form import WinForm class Attachment(object): "Attachment window" - def __init__(self, model, obj_id, parent): - self.dialog = gtk.Dialog( - title= _("Attachment"), - parent=parent, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT - | gtk.WIN_POS_CENTER_ON_PARENT - | gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - dialog_vbox = gtk.VBox() - dialog_vbox.set_size_request(700, 600) - vpaned = gtk.VPaned() - vpaned.set_position(450) - dialog_vbox.pack_start(vpaned, True, True, 0) - hpaned2 = gtk.HPaned() - hpaned2.set_position(400) - vpaned.pack1(hpaned2, False, True) - vbox_preview = gtk.VBox(False, 0) - hpaned2.pack1(vbox_preview, False, True) - self.attach_filename = gtk.Label(_("Preview:")) - vbox_preview.pack_start(self.attach_filename, False, False, 0) - - scrolledwindow_preview = gtk.ScrolledWindow() - scrolledwindow_preview.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - scrolledwindow_preview.set_shadow_type(gtk.SHADOW_NONE) - viewport_preview = gtk.Viewport() - scrolledwindow_preview.add(viewport_preview) - vbox_preview.pack_start(scrolledwindow_preview, True, True, 0) - - self.image_preview = gtk.Image() - self.image_preview.set_from_stock("tryton-image-missing", - gtk.ICON_SIZE_DIALOG) - viewport_preview.add(self.image_preview) - - vbox_descr = gtk.VBox(False, 0) - hpaned2.pack2(vbox_descr, True, True) - self.label_descr = gtk.Label(_("Description:")) - vbox_descr.pack_start(self.label_descr, False, False, 0) - scrolledwindow_descr = gtk.ScrolledWindow() - scrolledwindow_descr.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - scrolledwindow_descr.set_shadow_type(gtk.SHADOW_IN) - self.text_descr = gtk.TextView() - scrolledwindow_descr.add(self.text_descr) - vbox_descr.pack_start(scrolledwindow_descr, True, True, 0) - - button_save_descr = gtk.Button(_("Save _Text"), stock=None, - use_underline=True) - img_button = gtk.Image() - img_button.set_from_stock('tryton-save', gtk.ICON_SIZE_BUTTON) - button_save_descr.set_image(img_button) - button_save_descr.connect_after('clicked', self._sig_comment) - vbox_descr.pack_start(button_save_descr, False, False, 0) - hbox = gtk.HBox(False, 0) - vpaned.pack2(hbox, True, True) - vbox_buttons = gtk.VBox(False, 0) - hbox.pack_start(vbox_buttons, False, False, 0) - - button_add_file = gtk.Button(_("Add _File..."), stock=None, - use_underline=True) - button_add_file.set_focus_on_click(False) - button_add_file.set_alignment(0.0,0.0) - img_button = gtk.Image() - img_button.set_from_stock('tryton-list-add', gtk.ICON_SIZE_BUTTON) - button_add_file.set_image(img_button) - button_add_file.connect_after('clicked', self._sig_add) - vbox_buttons.pack_start(button_add_file, False, False, 0) - - button_add_link = gtk.Button(_("Add _Link..."), stock=None, - use_underline=True) - button_add_link.set_alignment(0.0,0.0) - img_button = gtk.Image() - img_button.set_from_stock('tryton-list-add', gtk.ICON_SIZE_BUTTON) - button_add_link.set_image(img_button) - button_add_link.connect_after('clicked', self._sig_link) - vbox_buttons.pack_start(button_add_link, False, False, 0) - - button_save = gtk.Button(_("_Save as..."), stock=None, - use_underline=True) - button_save.set_alignment(0.0,0.0) - img_button = gtk.Image() - img_button.set_from_stock('tryton-save-as', gtk.ICON_SIZE_BUTTON) - button_save.set_image(img_button) - button_save.connect_after('clicked', self._sig_save) - vbox_buttons.pack_start(button_save, False, False, 0) - - button_delete = gtk.Button(_("_Delete..."), stock=None, - use_underline=True) - button_delete.set_alignment(0.0,0.0) - img_button = gtk.Image() - img_button.set_from_stock('tryton-delete', gtk.ICON_SIZE_BUTTON) - button_delete.set_image(img_button) - button_delete.connect_after('clicked', self._sig_del) - vbox_buttons.pack_start(button_delete, False, False, 0) - - button_close = gtk.Button("gtk-close", stock="gtk-close") - self.dialog.add_action_widget(button_close, gtk.RESPONSE_CLOSE) - button_close.set_flags(gtk.CAN_DEFAULT) - - scrol_win_all_attachments = gtk.ScrolledWindow() - scrol_win_all_attachments.set_policy( gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - scrol_win_all_attachments.set_shadow_type(gtk.SHADOW_NONE) - viewport_all_attachments = gtk.Viewport() - scrol_win_all_attachments.add(viewport_all_attachments) - hbox.pack_start(scrol_win_all_attachments, True, True) - + def __init__(self, model_name, record_id, parent): + self.resource = '%s,%s' % (model_name, record_id) self.parent = parent - self.resource = (model, obj_id) - - self.view = gtk.TreeView() - viewport = viewport_all_attachments - viewport.add(self.view) - - selection = self.view.get_selection() - selection.set_mode(gtk.SELECTION_SINGLE) - selection.connect('changed', self._sig_changed) - - args = ('model', 'ir.attachment', 'fields_view_get', False, 'tree', - rpc.CONTEXT) - try: - view = rpc.execute(*args) - except Exception, exception: - view = common.process_exception(exception, parent, *args) - if not view: - self.dialog = None - return - - parse = Parse(view['fields']) - parse.parse(view['arch'], self.view) - self.view.set_headers_visible(True) - self.fields_order = parse.fields_order - - types = [gobject.TYPE_STRING] - for i in self.fields_order: - types.append(gobject.TYPE_STRING) - self.model_name = model - self.model = gtk.ListStore(*types) - - self.view.set_model(self.model) - self.view.connect('row-activated', self.sig_activate) - self.view.show_all() - self.reload(preview=False) - self.dialog.vbox.pack_start(dialog_vbox) - self.dialog.show_all() - - def _sig_comment(self, widget): - textview = self.text_descr - start = textview.get_buffer().get_start_iter() - end = textview.get_buffer().get_end_iter() - comment = textview.get_buffer().get_text(start, end) - model, iter = self.view.get_selection().get_selected() - context = copy.copy(rpc.CONTEXT) - if not iter: - common.warning(_('You must put a text comment to an ' - 'attachement.'), self.dialog, _('Text not saved!')) - return None - obj_id = model.get_value(iter, 0) - if obj_id: - args = ('model', 'ir.attachment', 'write', - [int(obj_id)], {'description': comment}, context) - try: - rpc.execute(*args) - except Exception, exception: - common.process_exception(exception, self.dialog, *args) - else: - common.warning(_('You must put a text comment to an ' - 'attachement.'), self.dialog, _('Text not saved!')) - - def _sig_del(self, widget): - model, iter = self.view.get_selection().get_selected() - if not iter: - return None - obj_id = model.get_value(iter, 0) - if obj_id: - if common.sur(_('Are you sure you want to remove this ' - 'attachment?'), self.dialog): - try: - rpc.execute('model', 'ir.attachment', 'delete', - [int(obj_id)]) - except Exception, exception: - common.process_exception(exception, self.dialog, *args) - self.reload() - - def _sig_link(self, widget): - filename = common.file_selection(_('Select file'), parent=self.dialog) - if not filename: - return - try: - if filename: - fname = os.path.basename(filename) - args = ('model', 'ir.attachment', 'create', { - 'name': fname, - 'res_model': self.resource[0], - 'res_id': self.resource[1], - 'link': filename,}) - try: - obj_id = rpc.execute(*args) - except Exception, exception: - obj_id = common.process_exception(exception, self.dialog, - *args) - if not obj_id: - return - self.reload(preview=False) - self.preview(int(obj_id)) - except IOError: - common.message(_('Can not open file!'), self.dialog, - gtk.MESSAGE_ERROR) - - def _sig_save(self, widget): - model, iter = self.view.get_selection().get_selected() - if not iter: - return None - obj_id = model.get_value(iter, 0) - if obj_id: - rpcprogress = common.RPCProgress('execute', ('model', - 'ir.attachment', 'read', int(obj_id)), self.dialog) - try: - data = rpcprogress.run() - except Exception, exception: - common.process_exception(exception, self.dialog) - return None - if not data: - return None - filename = common.file_selection(_('Save As...'), - filename=data['name'], parent=self.dialog, - action=gtk.FILE_CHOOSER_ACTION_SAVE) - if not filename: - return None - try: - if not data['link']: - open(filename, 'wb+').write( - base64.decodestring(data['datas'])) - else: - open(filename, 'wb+').write( - urllib.urlopen(data['link']).read()) - except IOError: - common.message(_('Can not write file!'), self.dialog, - gtk.MESSAGE_ERROR) - - 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) - - filenames = common.file_selection(_('Open...'), preview=True, - multi=True, parent=self.dialog, - filters=[filter_all, filter_image]) - if not filenames: - return - for filename in filenames: - value = open(filename, 'rb').read() - name = os.path.basename(filename) - args = ('model', 'ir.attachment', 'create', { - 'name': name, - 'datas': base64.encodestring(value), - 'res_model': self.resource[0], - 'res_id': self.resource[1],}) - rpcprogress = common.RPCProgress('execute', args, self.dialog) - try: - obj_id = rpcprogress.run() - except Exception, exception: - common.process_exception(exception, self.dialog) - return - self.reload(preview=False) - self.preview(int(obj_id)) - - def _sig_changed(self, widget): - model, iters = self.view.get_selection().get_selected_rows() - if not iters: - return None - obj_id = model.get_value(model.get_iter(iters[0]), 0) - self.preview(int(obj_id)) - - def sig_activate(self, widget, path, view_column): - iter = self.model.get_iter(path) - obj_id = self.model.get_value(iter, 0) - if obj_id: - rpcprogress = common.RPCProgress('execute', ('model', - 'ir.attachment', 'read', int(obj_id)), self.dialog) - try: - data = rpcprogress.run() - except Exception, exception: - common.process_exception(exception, self.dialog) - return None - if not data: - return None - file_name = data['link'] - if not data['link']: - (fileno, file_name) = tempfile.mkstemp( - data['name'], 'tryton_') - file_p = open(file_name, 'wb+') - if data['datas']: - file_p.write(base64.decodestring(data['datas'])) - file_p.close() - os.close(fileno) - ext = file_name.split('.')[-1].lower() - common.file_open(file_name, ext, self.parent) - - def preview(self, obj_id): - rpcprogress = common.RPCProgress('execute', ('model', - 'ir.attachment', 'read', obj_id), self.dialog) - try: - data = rpcprogress.run() - except Exception, exception: - common.process_exception(exception, self.dialog) - return None - if not data: - return None - - buf = self.text_descr.get_buffer() - buf.delete(buf.get_start_iter(), buf.get_end_iter()) - iter_start = buf.get_start_iter() - buf.insert(iter_start, data['description'] or '') - - fname = str(data['name']) - - decoder = {'jpg': 'jpeg', - 'jpeg': 'jpeg', - 'gif': 'gif', - 'png': 'png', - 'bmp': 'bmp',} - ext = fname.split('.')[-1].lower() - img = self.image_preview - img.clear() - if ext in decoder.iterkeys(): - try: - if not data['link']: - value = base64.decodestring(data['datas']) - else: - value = urllib.urlopen(data['link']).read() - - def set_size(widget, width, height): - allocation = self.dialog.get_allocation() - scale1 = 0.3 * float(allocation.width) / float(width) - scale2 = 0.3 * float(allocation.height) / float(height) - scale = min(scale1, scale2) - if int(scale * width) > 0 and int(scale * height) > 0: - widget.set_size(int(scale * width), - int(scale * height)) - - loader = gtk.gdk.PixbufLoader(decoder[ext]) - loader.connect_after('size-prepared', set_size) - - loader.write(value, len(value)) - pixbuf = loader.get_pixbuf() - loader.close() - - img.set_from_pixbuf(pixbuf) - except: - img.set_from_icon_name('gtk-cancel', gtk.ICON_SIZE_DIALOG) - - def reload(self, preview=True): - self.model.clear() - try: - ids = rpc.execute('model', 'ir.attachment', 'search', [ - ('res_model', '=', self.resource[0]), - ('res_id', '=', self.resource[1]), - ]) - except Exception, exception: - common.process_exception(exception, self.dialog) - return - try: - res_ids = rpc.execute('model', 'ir.attachment', 'read', ids, - self.fields_order + ['link']) - except Exception, exception: - common.process_exception(exception, self.dialog) - return - for res in res_ids: - num = self.model.append() - args = [] - for i in range(len(self.fields_order)): - args.append(i + 1) - if res['link']: - args.append(_('link: ') + str(res[self.fields_order[i]])) - else: - args.append(str(res[self.fields_order[i]])) - self.model.set(num, 0, res['id'], *args) - if preview and len(res_ids): - self.preview(int(res_ids[0]['id'])) def run(self): - if not self.dialog: - return - self.dialog.run() + screen = Screen('ir.attachment', self.parent, domain=[ + ('resource', '=', self.resource), + ], view_type=['tree', 'form'], context={ + 'resource': self.resource, + }, exclude_field='resource') + screen.search_filter() + win = WinForm(screen, self.parent, view_type='tree') + if win.run(): + screen.group.save() self.parent.present() - self.dialog.destroy() + win.destroy() diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index 712581f6ff..1c22746883 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -458,8 +458,7 @@ class Record(SignalEvent): return 0 if self.attachment_count < 0 or reload: args = ('model', 'ir.attachment', 'search_count', [ - ('res_model', '=', self.model_name), - ('res_id', '=', self.id), + ('resource', '=', '%s,%s' % (self.model_name, self.id)), ]) try: self.attachment_count = rpc.execute(*args)