Use dropdown for attachments

issue7659
review50551002
This commit is contained in:
Cédric Krier committed 2018-09-02 10:44:38 +02:00
1 parent 3978849e3a
commit f717b64540
7 files changed
+119 -35

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Use dropdown for attachment
* Apply factor on domain parser
* Use tab name in CSV Export/Import
* Add bus management
+3 -11
View File
@@ -1,13 +1,11 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import gettext
import tempfile
import os
import webbrowser
import tryton.rpc as rpc
from tryton.common import RPCProgress, RPCExecute, RPCException, slugify
from tryton.common import message, selection, file_open, mailto
from tryton.common import RPCProgress, RPCExecute, RPCException
from tryton.common import message, selection, file_write, file_open, mailto
from tryton.config import CONFIG
from tryton.pyson import PYSONDecoder
@@ -39,14 +37,8 @@ class Action(object):
(type, data, print_p, name) = res
if not print_p and direct_print:
print_p = True
dtemp = tempfile.mkdtemp(prefix='tryton_')
fp_name = os.path.join(dtemp,
slugify(name) + os.extsep + slugify(type))
if isinstance(data, str):
data = data.encode('utf-8')
with open(fp_name, 'wb') as file_d:
file_d.write(data)
fp_name = file_write((name, type), data)
if email_print:
mailto(to=email.get('to'), cc=email.get('cc'),
subject=email.get('subject'), body=email.get('body'),
+17 -1
View File
@@ -8,6 +8,7 @@ import pango
import gettext
import os
import subprocess
import tempfile
import re
import logging
import unicodedata
@@ -426,7 +427,22 @@ def slugify(value):
return _slugify_hyphenate_re.sub('-', value)
def file_open(filename, type, print_p=False):
def file_write(filename, data):
if isinstance(data, str):
data = data.encode('utf-8')
dtemp = tempfile.mkdtemp(prefix='tryton_')
if not isinstance(filename, str):
name, ext = filename
else:
name, ext = os.path.splitext(filename)
filename = ''.join([slugify(name), os.extsep, slugify(ext)])
filepath = os.path.join(dtemp, filename)
with open(filepath, 'wb') as fp:
fp.write(data)
return filepath
def file_open(filename, type=None, print_p=False):
def save():
save_name = file_selection(_('Save As...'),
action=gtk.FILE_CHOOSER_ACTION_SAVE)
+43
View File
@@ -5,7 +5,10 @@ import os
from urllib.request import urlopen
from urllib.parse import urlparse, unquote
import gettext
import webbrowser
from functools import partial
from tryton.common import RPCExecute, RPCException, file_write, file_open
from tryton.gui.window.view_form.screen import Screen
from tryton.gui.window.win_form import WinForm
@@ -46,3 +49,43 @@ class Attachment(WinForm):
name_field.set_client(new_record, file_name)
data_field.set_client(new_record, urlopen(uri).read())
self.screen.display()
def add_file(self, filename):
self.add_uri('file:///' + filename)
@staticmethod
def get_attachments(record):
attachments = []
context = {}
if record and record.id >= 0:
context = record.get_context()
try:
attachments = RPCExecute('model', 'ir.attachment',
'search_read', [
('resource', '=', '%s,%s' % (
record.model_name, record.id)),
], 0, 20, None, ['rec_name', 'name', 'type', 'link'],
context=context)
except RPCException:
pass
for attachment in attachments:
name = attachment['rec_name']
callback = getattr(
Attachment, 'open_' + attachment['type'], Attachment.open_data)
yield name, partial(
callback, attachment=attachment, context=context)
@staticmethod
def open_link(attachment, context):
if attachment['link']:
webbrowser.open(attachment['link'], new=2)
@staticmethod
def open_data(attachment, context):
try:
value, = RPCExecute('model', 'ir.attachment', 'read',
[attachment['id']], ['data'], context=context)
except RPCException:
return
filepath = file_write(attachment['name'], value['data'])
file_open(filepath)
+35 -4
View File
@@ -106,11 +106,42 @@ class Form(SignalEvent, TabContent):
self.screen.destroy()
def sig_attach(self, widget=None):
record = self.screen.current_record
if not record or record.id < 0:
def window(widget):
return Attachment(
record, lambda: self.update_attachment_count(reload=True))
def add_file(widget):
filename = common.file_selection(_("Select"))
if filename:
window(widget).add_file(filename)
def activate(widget, callback):
callback()
button = self.buttons['attach']
if widget != button:
if button.props.sensitive:
button.props.active = True
return
Attachment(record,
lambda: self.update_attachment_count(reload=True))
record = self.screen.current_record
menu = button._menu = Gtk.Menu()
for name, callback in Attachment.get_attachments(record):
item = Gtk.MenuItem()
item.set_label(name)
item.connect('activate', activate, callback)
menu.add(item)
menu.add(Gtk.SeparatorMenuItem())
add_item = Gtk.MenuItem()
add_item.set_label(_("Add..."))
add_item.connect('activate', add_file)
menu.add(add_item)
manage_item = Gtk.MenuItem()
manage_item.set_label(_("Manage..."))
manage_item.connect('activate', window)
menu.add(manage_item)
menu.show_all()
menu.connect('deactivate', self._popup_menu_hide, button)
self.action_popup(button)
def update_attachment_count(self, reload=False):
record = self.screen.current_record
+10 -4
View File
@@ -16,12 +16,13 @@ _ = gettext.gettext
class ToolbarItem(object):
def __init__(self, id, label,
tooltip=None, icon_name=None, accel_path=None):
tooltip=None, icon_name=None, accel_path=None, toggle=False):
self.id = id
self.label = label
self.tooltip = tooltip
self.icon_name = icon_name
self.accel_path = accel_path
self.toggle = toggle
@property
def menu(self):
@@ -104,7 +105,8 @@ class TabContent(InfoBar):
label=_("A_ttachments..."),
tooltip=_("Add an attachment to the record"),
icon_name='tryton-attach',
accel_path='<tryton>/Form/Attachments'),
accel_path='<tryton>/Form/Attachments',
toggle=True),
ToolbarItem(
id='note',
label=_("_Notes..."),
@@ -248,13 +250,17 @@ class TabContent(InfoBar):
callback = getattr(self, 'sig_%s' % item.id, None)
if not callback:
continue
toolitem = gtk.ToolButton()
if item.toggle:
toolitem = gtk.ToggleToolButton()
toolitem.connect('toggled', callback)
else:
toolitem = gtk.ToolButton()
toolitem.connect('clicked', callback)
toolitem.set_icon_widget(
common.IconFactory.get_image(
item.icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR))
toolitem.set_label(item.label)
toolitem.set_use_underline(True)
toolitem.connect('clicked', callback)
self.tooltips.set_tip(toolitem, item.tooltip)
self.buttons[item.id] = toolitem
elif not item and previous:
@@ -3,9 +3,8 @@
import gtk
import gettext
import os
import tempfile
from tryton.common import common
from tryton.common import file_selection, Tooltips, file_open, slugify
from tryton.common import file_selection, Tooltips, file_open, file_write
from tryton.common.entry_position import reset_position
from tryton.config import CONFIG
from .widget import Widget
@@ -89,21 +88,20 @@ class BinaryMixin(Widget):
self.filename_field.set_client(self.record,
os.path.basename(filename))
def get_data(self):
if hasattr(self.field, 'get_data'):
data = self.field.get_data(self.record)
else:
data = self.field.get(self.record)
return data
def open_(self, widget=None):
if not self.filename_field:
return
filename = self.filename_field.get(self.record)
if not filename:
return
dtemp = tempfile.mkdtemp(prefix='tryton_')
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))
file_path = file_write(filename, self.get_data())
root, type_ = os.path.splitext(filename)
if type_:
type_ = type_[1:]
@@ -117,10 +115,7 @@ class BinaryMixin(Widget):
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))
fp.write(self.get_data())
def clear(self, widget=None):
if self.filename_field: