Cédric Krier has proposed merging lp:~pcsol/openobject-client/print_5_0 into lp:openobject-client/5.0.
Requested reviews: OpenERP sa GTK client R&D (openerp-dev-gtk) Improve report printing - Allow to directly print report - Allow to send report as attachment -- https://code.launchpad.net/~pcsol/openobject-client/print_5_0/+merge/29061 Your team OpenERP sa GTK client R&D is requested to review the proposed merge of lp:~pcsol/openobject-client/print_5_0 into lp:openobject-client/5.0.
=== modified file 'bin/common/common.py' --- bin/common/common.py 2010-03-23 23:37:45 +0000 +++ bin/common/common.py 2010-07-02 09:58:23 +0000 @@ -3,6 +3,10 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved +# Copyright (C) 2007-2010 Cédric Krier. +# Copyright (C) 2007-2010 Bertrand Chenal. +# Copyright (C) 2008-2010 B2CK SPRL. +# Copyright (C) 2010 PCSol. # $Id$ # # This program is free software: you can redistribute it and/or modify @@ -26,6 +30,10 @@ from cgi import escape import tools import gettext +import shlex +import urllib +import webbrowser +from string import Template import os import sys @@ -584,41 +592,178 @@ obj.create(False, resource, id, [], 'form', None, context,'form,tree') return False -def open_file(value, parent): - filetype = {} - if options['client.filetype']: - if isinstance(options['client.filetype'], str): - filetype = eval(options['client.filetype']) +def find_in_path(name): + if os.name == "nt": + sep = ';' + else: + sep = ':' + path = [directory for directory in os.environ['PATH'].split(sep) + if os.path.isdir(directory)] + for directory in path: + val = os.path.join(directory, name) + if os.path.isfile(val) or os.path.islink(val): + return val + return name + +def file_open(filename, type, parent, print_p=False, number=1): + + if print_p: + win = gtk.Dialog(_('Print Number'), parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT + | gtk.WIN_POS_CENTER_ON_PARENT) + win.set_icon(OPENERP_ICON) + hbox = gtk.HBox(homogeneous=True) + hbox.pack_start(gtk.Label(_('Number')), expand=False, fill=False) + adj = gtk.Adjustment(0.0, -sys.maxint, sys.maxint, 1.0, 5.0) + widget = gtk.SpinButton(adj, 1, digits=0) + widget.set_numeric(True) + widget.set_width_chars(5) + widget.set_activates_default(True) + widget.set_value(number) + hbox.pack_start(widget, expand=True, fill=False) + win.vbox.add(hbox) + win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) + win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + win.resize(200, 200) + win.show_all() + res = win.run() + number = widget.get_value_as_int() + if parent: + parent.present() + win.destroy() + if res != gtk.RESPONSE_OK: + return False + else: + number = 1 + + if os.name == 'nt': + operation = 'open' + if print_p: + operation = 'print' + try: + for i in xrange(number): + os.startfile(os.path.normpath(filename), operation) + except: + # Try without operation, it is not supported on version < 2.5 + try: + os.startfile(os.path.normpath(filename)) + except: + save_name = file_selection(_('Save As...'), parent=parent, + action=gtk.FILE_CHOOSER_ACTION_SAVE) + if save_name: + file_p = open(filename, 'rb') + save_p = open(save_name, 'wb+') + save_p.write(file_p.read()) + save_p.close() + file_p.close() + return + elif os.name == 'mac' or \ + (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + pid = os.fork() + if not pid: + pid = os.fork() + if not pid: + try: + os.execv('/usr/bin/open', ['/usr/bin/open', filename]) + except: + sys.exit(0) + time.sleep(0.1) + sys.exit(0) + os.waitpid(pid, 0) + return + cmd = '' + if isinstance(options['extensions.filetype'], basestring): + extensions_filetype = eval(options['extensions.filetype']) + if type in extensions_filetype: + if print_p: + cmd = extensions_filetype[type][1] else: - filetype = options['client.filetype'] - root, ext = os.path.splitext(value) - cmd = False - if ext[1:] in filetype: - cmd = filetype[ext[1:]] % (value) - if not cmd: - cmd = file_selection(_('Open with...'), - parent=parent) - if cmd: - cmd = cmd + ' %s' - filetype[ext[1:]] = cmd - options['client.filetype'] = filetype - options.save() - cmd = cmd % (value) - if cmd: + cmd = extensions_filetype[type][0] + if not cmd: + #TODO add dialog box + pass + if not cmd: + save_name = file_selection(_('Save As...'), parent=parent, + action=gtk.FILE_CHOOSER_ACTION_SAVE) + if save_name: + file_p = open(filename, 'rb') + save_p = open(save_name, 'wb+') + save_p.write(file_p.read()) + save_p.close() + file_p.close() + return + cmd = cmd % filename + args = shlex.split(str(cmd)) + prog = find_in_path(args[0]) + args[0] = os.path.basename(args[0]) + if print_p: + for i in xrange(number): + os.spawnv(os.P_WAIT, prog, args) + return + pid = os.fork() + if not pid: + pid = os.fork() + if not pid: + try: + os.execv(prog, args) + except: + sys.exit(0) + time.sleep(0.1) + sys.exit(0) + os.waitpid(pid, 0) + +def mailto(to=None, cc=None, subject=None, body=None, attachment=None): + if options['client.email']: + cmd = Template(options['client.email']).substitute( + to=to or '', + cc=cc or '', + subject=subject or '', + body=body or '', + attachment=attachment or '', + ) + args = shlex.split(str(cmd)) + prog = find_in_path(args[0]) + args[0] = os.path.basename(args[0]) + if os.name == 'nt': + os.spawnv(os.P_NOWAIT, prog, args) + return pid = os.fork() if not pid: pid = os.fork() if not pid: - prog, args = cmd.split(' ', 1) - args = [os.path.basename(prog)] + args.split(' ') try: - os.execvp(prog, args) + os.execv(prog, args) except: - pass + sys.exit(0) time.sleep(0.1) sys.exit(0) os.waitpid(pid, 0) - + return + #http://www.faqs.org/rfcs/rfc2368.html + url = "mailto:" + if to: + if isinstance(to, unicode): + to = to.encode('utf-8') + url += urllib.quote(to.strip(), "@,") + url += '?' + if cc: + if isinstance(cc, unicode): + cc = cc.encode('utf-8') + url += "&cc=" + urllib.quote(cc, "@,") + if subject: + if isinstance(subject, unicode): + subject = subject.encode('utf-8') + url += "&subject=" + urllib.quote(subject, "") + if body: + if isinstance(body, unicode): + body = body.encode('utf-8') + body = "\r\n".join(body.splitlines()) + url += "&body=" + urllib.quote(body, "") + if attachment: + if isinstance(attachment, unicode): + attachment = attachment.encode('utf-8') + url += "&attachment=" + urllib.quote(attachment, "") + webbrowser.open(url, new=1) # Color set === modified file 'bin/modules/action/main.py' --- bin/modules/action/main.py 2010-06-18 13:52:51 +0000 +++ bin/modules/action/main.py 2010-07-02 09:58:23 +0000 @@ -3,6 +3,10 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved +# Copyright (C) 2007-2010 Cédric Krier. +# Copyright (C) 2007-2010 Bertrand Chenal. +# Copyright (C) 2008-2010 B2CK SPRL. +# Copyright (C) 2010 PCSol. # $Id$ # # This program is free software: you can redistribute it and/or modify @@ -24,10 +28,10 @@ import time import base64 import datetime +import tempfile import service import rpc import wizard -import printer import common import tools import options @@ -37,7 +41,10 @@ def __init__(self, name='action.main'): service.Service.__init__(self, name) - def exec_report(self, name, data, context={}): + def exec_report(self, name, data, direct_print=False, + email_print=False, email=None, context=None): + if context is None: + context = {} datas = data.copy() ids = datas['ids'] del datas['ids'] @@ -64,7 +71,26 @@ if attempt>max_attemps: common.message(_('Printing aborted, too long delay !')) return False - printer.print_data(val) + print_p = direct_print + if 'print_p' in val: + print_p = True + type = val['format'] + name = val.get('name', name) + data = val['result'] + number = val.get('number', 1) + dtemp = tempfile.mkdtemp(prefix='openerp_') + fp_name = os.path.join(dtemp, + name.replace(os.sep, ' ').replace(os.altsep or os.sep, '_') \ + + os.extsep + type) + file_d = open(fp_name, 'wb') + file_d.write(base64.decodestring(data)) + file_d.close() + if email_print: + common.mailto(to=email.get('to'), cc=email.get('cc'), + subject=email.get('subject'), body=email.get('body'), + attachment=fp_name) + else: + common.file_open(fp_name, type, None, print_p=print_p, number=number) return True def execute(self, act_id, datas, type=None, context={}): @@ -154,14 +180,20 @@ del datas['window'] datas.update(action.get('datas',{})) datas['report_id'] = action['report_id'] - self.exec_report('custom', datas, context) + self.exec_report('custom', datas, + direct_print=action.get('direct_print', False), + email_print=action.get('email_print', False), + email=action.get('email'), context=context) elif action['type']=='ir.actions.report.xml': if 'window' in datas: win=datas['window'] del datas['window'] datas.update(action.get('datas',{})) - self.exec_report(action['report_name'], datas, context) + self.exec_report(action['report_name'], datas, + direct_print=action.get('direct_print', False), + email_print=action.get('email_print', False), + email=action.get('email'), context=context) elif action['type']=='ir.actions.act_url': tools.launch_browser(action.get('url','')) === modified file 'bin/modules/gui/main.py' --- bin/modules/gui/main.py 2010-02-26 11:48:01 +0000 +++ bin/modules/gui/main.py 2010-07-02 09:58:23 +0000 @@ -897,7 +897,6 @@ def fnc_menuitem(menuitem, opt_name): options.options[opt_name] = menuitem.get_active() dict = { - 'on_opt_print_preview_activate': (fnc_menuitem, 'printer.preview', 'opt_print_preview'), 'on_opt_form_toolbar_activate': (fnc_menuitem, 'form.toolbar', 'opt_form_toolbar'), } self.glade.get_widget('menubar_'+(options.options['client.toolbar'] or 'both')).set_active(True) === modified file 'bin/openerp.glade' --- bin/openerp.glade 2010-03-23 23:43:06 +0000 +++ bin/openerp.glade 2010-07-02 09:58:23 +0000 @@ -1033,32 +1033,6 @@ </widget> </child> <child> - <widget class="GtkImageMenuItem" id="printer"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Print</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="printer_menu"> - <child> - <widget class="GtkCheckMenuItem" id="opt_print_preview"> - <property name="visible">True</property> - <property name="label" translatable="yes">Previe_w before print</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_opt_print_preview_activate"/> - </widget> - </child> - </widget> - </child> - <child internal-child="image"> - <widget class="GtkImage" id="image4238"> - <property name="visible">True</property> - <property name="stock">gtk-print</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> <widget class="GtkSeparatorMenuItem" id="separator5"> <property name="visible">True</property> </widget> @@ -1868,7 +1842,12 @@ The whole source code is distributed under the terms of the GNU Public Licence. -(c) 2003-TODAY, Tiny sprl +Copyright (C) 2003-TODAY, Tiny sprl +Copyright (C) 2007-2010 Cédric Krier. +Copyright (C) 2007-2010 Bertrand Chenal. +Copyright (C) 2008-2010 B2CK SPRL. +Copyright (C) 2010 PCSol. + More Info on www.openerp.com !</property> </widget> === modified file 'bin/options.py' --- bin/options.py 2009-12-03 13:00:26 +0000 +++ bin/options.py 2010-07-02 09:58:23 +0000 @@ -3,6 +3,9 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved +# Copyright (C) 2007-2010 Cédric Krier. +# Copyright (C) 2008-2010 B2CK SPRL. +# Copyright (C) 2010 PCSol # $Id$ # # This program is free software: you can redistribute it and/or modify @@ -53,6 +56,22 @@ else: return '.' +def find_path(progs, args): + if os.name == 'nt': + return '' + if os.name == 'mac' or \ + (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + return '' + paths = [x for x in os.environ['PATH'].split(':') + if os.path.isdir(x)] + for dir in paths: + for prog in progs: + val = os.path.join(dir, prog) + if os.path.isfile(val) or os.path.islink(val): + return val + ' ' + args + return '' + + class configmanager(object): def __get_prefix(self): @@ -86,10 +105,6 @@ 'tip.position': 0, 'survey.position': 0, 'form.autosave': False, - 'printer.preview': True, - 'printer.softpath': 'none', - 'printer.softpath_html': 'none', - 'printer.path': 'none', 'logging.level': 'INFO', 'logging.output': 'stdout', 'client.default_path': os.path.expanduser('~'), @@ -103,6 +118,21 @@ 'help.index': 'http://doc.openerp.com/', 'help.context': 'http://doc.openerp.com/index.php?model=%(model)s&lang=%(lang)s', 'client.timeout': 300, + 'extensions.filetype': repr({ + 'odt': (find_path(['ooffice', 'ooffice2'], '"%s"'), + find_path(['ooffice', 'ooffice2'], '-p "%s"')), + 'txt': (find_path(['ooffice', 'ooffice2'], '"%s"'), + find_path(['ooffice', 'ooffice2'], '-p "%s"')), + 'pdf': (find_path(['evince', 'xpdf', 'gpdf', 'kpdf', + 'epdfview', 'acroread'], '"%s"'), ''), + 'png': (find_path(['feh', 'display', 'qiv', 'eye'], '"%s"'), + ''), + 'csv': (find_path(['ooffice', 'ooffice2'], '"%s"'), + find_path(['ooffice', 'ooffice2'], '-p "%s"')), + }), + 'client.email': find_path(['thunderbird'], '-compose "to=\'$to\',' + 'cc=\'$cc\',subject=\'$subject\',body=\'$body\',' + 'attachment=\'$attachment\'"'), } loglevels = ('critical', 'error', 'warning', 'info', 'debug', 'debug_rpc', 'debug_rpc_answer', 'notset') parser = optparse.OptionParser(version=_("OpenERP Client %s" % openerp_version)) === removed directory 'bin/printer' === removed file 'bin/printer/__init__.py' --- bin/printer/__init__.py 2009-01-04 22:13:17 +0000 +++ bin/printer/__init__.py 1970-01-01 00:00:00 +0000 @@ -1,26 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved -# $Id$ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -############################################################################## - -from printer import * - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - === removed file 'bin/printer/printer.py' --- bin/printer/printer.py 2009-12-07 10:44:05 +0000 +++ bin/printer/printer.py 1970-01-01 00:00:00 +0000 @@ -1,229 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved -# $Id$ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -############################################################################## - -# ------------------------------------------------------------------- # -# Module printer -# ------------------------------------------------------------------- # -# -# Supported formats: pdf -# -# Print or open a previewer -# - -import os -import base64 -import options -import sys -import gc -import common -import time -import gtk - -class Printer(object): - - def __init__(self): - self.openers = { - 'pdf': self._findPDFOpener, - 'html': self._findHTMLOpener, - 'doc': self._findHTMLOpener, - 'xls': self._findHTMLOpener, - 'sxw': self._findSXWOpener, - 'odt': self._findSXWOpener, - 'tiff': self._findPDFOpener, - } - - def _findInPath(self, progs): - lstprogs = progs[:] - found = {} - path = [dir for dir in os.environ['PATH'].split(':') - if os.path.isdir(dir)] - for dir in path: - content = os.listdir(dir) - for prog in progs[:]: - if prog in content: - return os.path.join(dir, prog)#prog - - progs.remove(prog) - found[prog] = os.path.join(dir, prog) - for prog in lstprogs: - if prog in found: - return found[prog] - return '' - - def _findHTMLOpener(self): - import webbrowser - def opener(fn): - webbrowser.open('file://'+fn) - return opener - - def __opener(self, fnct): - pid = os.fork() - if not pid: - pid = os.fork() - if not pid: - fnct() - time.sleep(0.1) - sys.exit(0) - os.waitpid(pid, 0) - - def _findPDFOpener(self): - if os.name != 'nt' and os.uname()[0] == 'Darwin' : - def opener(fn): - self.__opener( lambda: os.system('/usr/bin/open -a Preview ' + fn) ) - return opener - if os.name == 'nt': - if options.options['printer.preview']: - if options.options['printer.softpath'] is None: - return lambda fn: os.startfile(fn) - else: - return lambda fn: os.system(options.options['printer.softpath'] + ' ' + fn) - else: - return lambda fn: print_w32_filename(fn) - else: - if options.options['printer.preview']: - if options.options['printer.softpath'] is None: - prog = self._findInPath(['xdg-open', 'evince', 'xpdf', 'gpdf', 'kpdf', 'epdfview', 'acroread', 'open']) - def opener(fn): - self.__opener( lambda: os.execv(prog, (os.path.basename(prog), fn) )) - return opener - else: - def opener(fn): - self.__opener( lambda: os.execv(options.options['printer.softpath'], (os.path.basename(options.options['printer.softpath']), fn)) ) - return opener - else: - return lambda fn: print_linux_filename(fn) - - def _findSXWOpener(self): - if os.name == 'nt': - return lambda fn: os.startfile(fn) - else: - if options.options['printer.softpath_html'] is None: - prog = self._findInPath(['ooffice', 'ooffice2', 'openoffice', 'soffice']) - def opener(fn): - pid = os.fork() - if not pid: - pid = os.fork() - if not pid: - os.execv(prog, (os.path.basename(prog),fn)) - time.sleep(0.1) - sys.exit(0) - os.waitpid(pid, 0) - return opener - else: - def opener(fn): - pid = os.fork() - if not pid: - pid = os.fork() - if not pid: - os.execv(options.options['printer.softpath_html'], (os.path.basename(options.options['printer.softpath_html']),fn)) - time.sleep(0.1) - sys.exit(0) - os.waitpid(pid, 0) - return opener - def print_file(self, fname, ftype, preview=False): - app_to_run = None - try: - filetypes = eval( options.options['extensions.filetype'] ) - (app, app_print) = filetypes[ftype] - if options.options['printer.preview'] or preview: - app_to_run = app - else: - app_to_run = app_print - except: - pass - - if app_to_run: - def open_file(cmd, filename): - cmd = cmd.split() - found = False - for i, v in enumerate(cmd): - if v == '%s': - cmd[i] = filename - found = True - break - if not found: - cmd.append(filename) - - import subprocess - subprocess.Popen(cmd) - open_file(app_to_run, fname) - - else: - try: - finderfunc = self.openers.get(ftype,False) - if not finderfunc: - if sys.platform in ['win32', 'nt']: - os.startfile(fname) - else: - finderfunc = self.openers['html'] - opener = finderfunc() - opener(fname) - else: - opener = finderfunc() - opener(fname) - gc.collect() - except Exception,e: - raise Exception(_('Unable to handle %s filetype') % ftype) - -printer = Printer() - -def print_linux_filename(filename): - common.message(_('Linux Automatic Printing not implemented.\nUse preview option !')) - -def print_w32_filename(filename): - import win32api - win32api.ShellExecute (0, "print", filename, None, ".", 0) - -def print_data(data): - if 'result' not in data: - common.message(_('Error no report')) - return - if data.get('code','normal')=='zlib': - import zlib - content = zlib.decompress(base64.decodestring(data['result'])) - else: - content = base64.decodestring(data['result']) - - if data['format'] in printer.openers.keys(): - import tempfile - if data['format']=='html' and os.name=='nt': - data['format']='doc' - (fileno, fp_name) = tempfile.mkstemp('.'+data['format'], 'openerp_') - fp = file(fp_name, 'wb+') - fp.write(content) - fp.close() - os.close(fileno) - printer.print_file(fp_name, data['format']) - else: - fname = common.file_selection(_('Save As...'), filename='report.' + data['format'], - action=gtk.FILE_CHOOSER_ACTION_SAVE) - if fname: - try: - fp = file(fname,'wb+') - fp.write(content) - fp.close() - except: - common.message(_('Error writing the file!')) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - === modified file 'bin/widget/view/form.py' --- bin/widget/view/form.py 2010-01-05 12:27:50 +0000 +++ bin/widget/view/form.py 2010-07-02 09:58:23 +0000 @@ -3,6 +3,10 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved +# Copyright (C) 2008-2010 Bertrand Chenal. +# Copyright (C) 2008-2010 Cedric Krier. +# Copyright (C) 2008-2010 B2CK. +# Copyright (C) 2010 PCSol. # $Id$ # # This program is free software: you can redistribute it and/or modify @@ -91,224 +95,169 @@ self.widgets = dict([(name, ViewWidget(self, widget, name)) for name, widget in children.items()]) if toolbar: - hb = gtk.HBox() + hb = gtk.VBox() hb.pack_start(self.widget) -# self.hpaned = gtk.HPaned() -# self.hpaned.pack1(self.widget,True,False) - - #tb = gtk.Toolbar() - #tb.set_orientation(gtk.ORIENTATION_VERTICAL) - #tb.set_style(gtk.TOOLBAR_BOTH_HORIZ) - #tb.set_icon_size(gtk.ICON_SIZE_MENU) - tb = gtk.VBox() - - eb = gtk.EventBox() - eb.add(tb) - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("lightgrey")) - - - hb.pack_start(eb, False, False) + + gtktoolbar = gtk.Toolbar() + gtktoolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) + gtktoolbar.set_style(gtk.TOOLBAR_BOTH) + gtktoolbar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("lightgrey")) + + hb.pack_start(gtktoolbar, False, False) self.widget = hb -# self.hpaned.pack2(eb,False,True) -# self.hpaned.connect("button-press-event",self.move_paned_press) -# self.hpaned.connect("button-release-event",self.move_paned_release,window) -# window.connect("window-state-event",self.move_paned_window,window) -# self.widget = self.hpaned - - - sep = False - #setLabel={'print':'Reports','action':'Wizards','relate':'Direct Links'} - + for icontype in ('print', 'action', 'relate'): - - if icontype in ('action','relate') and sep: - #tb.insert(gtk.SeparatorToolItem(), -1) - tb.pack_start(gtk.HSeparator(), False, False, 2) - sep = False - - #list_done = [] for tool in toolbar[icontype]: - #if icontype not in list_done: - # l = gtk.Label('<b>' + setLabel[icontype] + '</b>') - # l.set_use_markup(True) -# # l.set_alignment(0.0, 0.5) # If Labels want to be Left-aligned - # tb.pack_start(l, False, False, 3) - # tb.pack_start(gtk.HSeparator(), False, False, 2) - # list_done.append(icontype) iconstock = { 'print': gtk.STOCK_PRINT, 'action': gtk.STOCK_EXECUTE, 'relate': gtk.STOCK_JUMP_TO, }.get(icontype, gtk.STOCK_ABOUT) - icon = gtk.Image() - icon.set_from_stock(iconstock, gtk.ICON_SIZE_BUTTON) - lbl = gtk.Label(tool['string']) - lbl.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) - hb = gtk.HBox(False, 5) - hb.pack_start(icon, False, False) - hb.pack_start(lbl, False, False) - - tbutton = gtk.Button() - tbutton.add(hb) - tbutton.set_relief(gtk.RELIEF_NONE) - tb.pack_start(tbutton, False, False, 2) - - #tbutton = gtk.ToolButton() - #tbutton.set_label_widget(hb) #tool['string']) - #tbutton.set_stock_id(iconstock) - #tb.insert(tbutton,-1) - - def _action(button, action, type): - data={} - context=self.screen.context - act=action.copy() - if type in ('print', 'action'): - self.screen.save_current() - id = self.screen.current_model and self.screen.current_model.id - if not (id): - common.message(_('You must save this record to use the relate button !')) - return False - self.screen.display() - data = { - 'model': self.screen.name, - 'id': id, - 'ids': [id], - 'report_type': act.get('report_type', 'pdf'), - } - if type == 'relate': - id = self.screen.current_model and self.screen.current_model.id - if not (id): - common.message(_('You must select a record to use the relate button !')) - return False - act['domain'] = self.screen.current_model.expr_eval(act['domain'], check_load=False) - act['context'] = str(self.screen.current_model.expr_eval(act['context'], check_load=False)) - obj = service.LocalService('action.main') - value = obj._exec_action(act, data, context) - if type in ('print', 'action'): - self.screen.reload() - return value - - def _translate_label(self, event, tool, window): - if event.button != 3: - return False - def callback(self, tool, window): - lang_ids = rpc.session.rpc_exec_auth('/object', - 'execute', 'res.lang', 'search', - [('translatable', '=', '1')]) - if not lang_ids: - common.message(_('No other language available!'), - parent=window) - return False - langs = rpc.session.rpc_exec_auth('/object', - 'execute', 'res.lang', 'read', lang_ids, - ['code', 'name']) - - win = gtk.Dialog(_('Add Translation'), window, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - win.vbox.set_spacing(5) - win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) - win.set_icon(common.OPENERP_ICON) - vbox = gtk.VBox(spacing=5) - - entries_list = [] - for lang in langs: - code = lang['code'] - val = rpc.session.rpc_exec_auth('/object', - 'execute', tool['type'], 'read', - [tool['id']], ['name'], {'lang': code}) - val = val[0] - - label = gtk.Label(lang['name']) - entry = gtk.Entry() - entry.set_text(val['name']) - entries_list.append((code, entry)) - hbox = gtk.HBox(homogeneous=True) - hbox.pack_start(label, expand=False, fill=False) - hbox.pack_start(entry, expand=True, fill=True) - vbox.pack_start(hbox, expand=False, fill=True) - - vp = gtk.Viewport() - vp.set_shadow_type(gtk.SHADOW_NONE) - vp.add(vbox) - sv = gtk.ScrolledWindow() - sv.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - sv.set_shadow_type(gtk.SHADOW_NONE) - sv.add(vp) - win.vbox.add(sv) - win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) - win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) - win.resize(400,200) - win.show_all() - res = win.run() - if res == gtk.RESPONSE_OK: - to_save = map(lambda x: (x[0], - x[1].get_text()), entries_list) - while to_save: - code, val = to_save.pop() - rpc.session.rpc_exec_auth('/object', - 'execute', tool['type'], - 'write', [tool['id']], - {'name': val}, {'lang': code}) - window.present() - win.destroy() - return res - + if hasattr(gtk, 'MenuToolButton'): + tbutton = gtk.MenuToolButton(iconstock) + else: + tbutton = gtk.ToolButton(iconstock) + tbutton.set_use_underline(True) + + text = tool['string'] + if '_' not in text: + text = '_' + text + tbutton.set_label(text) + gtktoolbar.insert(tbutton, -1) + + tbutton.connect('clicked', self._sig_clicked, tool, + icontype) + + if hasattr(gtk, 'MenuToolButton'): menu = gtk.Menu() - item = gtk.ImageMenuItem(_('Translate label')) - item.connect("activate", callback, tool, window) - item.set_sensitive(1) - item.show() - menu.append(item) - menu.popup(None,None,None,event.button,event.time) - return True - - tbutton.connect('clicked', _action, tool, icontype) - - tbutton.connect('button_press_event', _translate_label, - tool, self.window) - - sep = True - -# def move_paned_press(self, widget, event): -# if not self.prev: -# self.prev = self.hpaned.get_position() -# return False -# if self.prev and not self.flag: -# self.prev = self.hpaned.get_position() -# return False -# -# def move_paned_release(self, widget, event, w): -# if self.hpaned.get_position()<self.current and self.hpaned.get_position()!=self.prev: -# self.prev = self.hpaned.get_position() -# else: -# self.current= self.hpaned.get_position() -# if not self.flag and self.current == self.prev: -# self.flag=True -# self.hpaned.set_position(w.get_size()[0]) -# elif not self.flag and self.current>self.prev: -# if self.hpaned.get_position()<self.current: -# self.hpaned.set_position(self.prev) -# else: -# self.hpaned.set_position(self.current) -# elif self.flag: -# if self.current<self.prev: -# self.hpaned.set_position(self.current) -# elif self.current>self.prev: -# self.hpaned.set_position(self.prev) -# self.flag=False -# self.current = self.hpaned.get_position() - 7 -# return False -# -# def move_paned_window(self, widget, event, w): -# if not self.prev: -# self.prev=self.hpaned.get_position() -# self.hpaned.set_position(self.prev) -# self.prev = 0 -# self.current = 0 -# self.flag = False -# return False - + if icontype == 'print': + for mtype, text in (('print', _('_Direct Print')), + ('email', _('_Email as Attachment'))): + menuitem = gtk.MenuItem(text) + tool = tool.copy() + if mtype == 'print': + tool['direct_print'] = True + tool['email_print'] = False + else: + tool['direct_print'] = False + tool['email_print'] = True + menuitem.connect('activate', self._sig_clicked, + tool, icontype) + menu.add(menuitem) + menuitem.show() + menuitem = gtk.MenuItem(_('Translate Label')) + menuitem.connect('activate', self._translate_label, tool) + menu.add(menuitem) + menuitem.show() + tbutton.set_menu(menu) + + def _sig_clicked(self, widget, action, atype): + return self._action(action, atype) + + def _action(self, action, atype): + data={} + context=self.screen.context + act=action.copy() + if atype in ('print', 'action'): + self.screen.save_current() + obj_id = self.screen.current_model and self.screen.current_model.id + if not (obj_id): + if atype in ('print'): + common.message(_('You must save this record ' + 'to be able to use the print button!')) + if atype in ('action'): + common.message(_('You must save this record ' + 'to be able to use the action button!')) + return False + email = {} + if 'email' in action: + email = self.screen.current_model.expr_eval(action['email']) + if not email: + email = {} + email['subject'] = action['name'].replace('_', '') + act['email'] = email + self.screen.display() + if atype == 'relate': + obj_id = self.screen.current_model and self.screen.current_model.id + if not obj_id: + common.message(_('You must select a record to use the relate button !')) + return False + act['domain'] = self.screen.current_model.expr_eval(act['domain'], check_load=False) + act['context'] = str(self.screen.current_model.expr_eval(act['context'], check_load=False)) + + data = { + 'model': self.screen.name, + 'id': obj_id, + 'ids': [obj_id], + } + + obj = service.LocalService('action.main') + value = obj._exec_action(act, data, context) + self.screen.reload() + return value + + def _translate_label(self, widget, tool): + lang_ids = rpc.session.rpc_exec_auth('/object', + 'execute', 'res.lang', 'search', + [('translatable', '=', '1')]) + if not lang_ids: + common.message(_('No other language available!'), + parent=self.window) + return False + langs = rpc.session.rpc_exec_auth('/object', + 'execute', 'res.lang', 'read', lang_ids, + ['code', 'name']) + + win = gtk.Dialog(_('Add Translation'), self.window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + win.vbox.set_spacing(5) + win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + win.set_icon(common.OPENERP_ICON) + vbox = gtk.VBox(spacing=5) + + entries_list = [] + for lang in langs: + code = lang['code'] + val = rpc.session.rpc_exec_auth('/object', + 'execute', tool['type'], 'read', + [tool['id']], ['name'], {'lang': code}) + val = val[0] + + label = gtk.Label(lang['name']) + entry = gtk.Entry() + entry.set_text(val['name']) + entries_list.append((code, entry)) + hbox = gtk.HBox(homogeneous=True) + hbox.pack_start(label, expand=False, fill=False) + hbox.pack_start(entry, expand=True, fill=True) + vbox.pack_start(hbox, expand=False, fill=True) + + vp = gtk.Viewport() + vp.set_shadow_type(gtk.SHADOW_NONE) + vp.add(vbox) + sv = gtk.ScrolledWindow() + sv.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sv.set_shadow_type(gtk.SHADOW_NONE) + sv.add(vp) + win.vbox.add(sv) + win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) + win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + win.resize(400,200) + win.show_all() + res = win.run() + if res == gtk.RESPONSE_OK: + to_save = map(lambda x: (x[0], + x[1].get_text()), entries_list) + while to_save: + code, val = to_save.pop() + rpc.session.rpc_exec_auth('/object', + 'execute', tool['type'], + 'write', [tool['id']], + {'name': val}, {'lang': code}) + self.window.present() + win.destroy() + return res def __getitem__(self, name): return self.widgets[name] === modified file 'bin/widget/view/form_gtk/binary.py' --- bin/widget/view/form_gtk/binary.py 2009-02-03 21:58:37 +0000 +++ bin/widget/view/form_gtk/binary.py 2010-07-02 09:58:23 +0000 @@ -34,7 +34,6 @@ import interface import common import options -import printer class wid_binary(interface.widget_interface): @@ -119,7 +118,7 @@ os.write(fileno, base64.decodestring(data)) os.close(fileno) - printer.printer.print_file(fp_name, ext, preview=True) + common.file_open(fp_name, ext, self.parent) except Exception, ex: common.message(_('Error reading the file: %s') % str(ex)) raise === modified file 'bin/widget/view/form_gtk/url.py' --- bin/widget/view/form_gtk/url.py 2009-01-04 22:13:17 +0000 +++ bin/widget/view/form_gtk/url.py 2010-07-02 09:58:23 +0000 @@ -22,6 +22,7 @@ import gettext import gtk +import os.path import common import interface @@ -120,7 +121,8 @@ def button_clicked(self, widget): value = self.entry.get_text() - common.open_file(value, self._window) + _, type = os.path.splitext(value) + common.file_open(value, type, self._window) === modified file 'bin/widget/view/list.py' --- bin/widget/view/list.py 2009-04-27 07:12:26 +0000 +++ bin/widget/view/list.py 2010-07-02 09:58:23 +0000 @@ -3,7 +3,10 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved -# Copyright (c) 2008-2009 B2CK, Bertrand Chenal, Cedric Krier (D&D in lists) +# Copyright (C) 2008-2010 Bertrand Chenal. +# Copyright (C) 2008-2010 Cedric Krier. +# Copyright (C) 2008-2010 B2CK. +# Copyright (C) 2010 PCSol. # $Id$ # # This program is free software: you can redistribute it and/or modify @@ -29,6 +32,7 @@ import service import locale from interface import parser_view +import options class AdaptModelGroup(gtk.GenericTreeModel): @@ -172,6 +176,59 @@ hbox.pack_start(hbox2, expand=False, fill=False, padding=12) hbox.show_all() + if toolbar and (toolbar['print'] or toolbar['action']): + hbox = gtk.HBox() + self.widget.pack_start(hbox, expand=False, fill=False) + + gtktoolbar = gtk.Toolbar() + gtktoolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) + gtktoolbar.set_style(gtk.TOOLBAR_BOTH) + gtktoolbar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("lightgrey")) + hbox.pack_start(gtktoolbar, True, True) + + for icontype in ('print', 'action'): + if not toolbar[icontype]: + continue + + for tool in toolbar[icontype]: + iconstock = { + 'print': gtk.STOCK_PRINT, + 'action': gtk.STOCK_EXECUTE, + }.get(icontype) + + if hasattr(gtk, 'MenuToolButton') and icontype == 'print': + tbutton = gtk.MenuToolButton(iconstock) + else: + tbutton = gtk.ToolButton(iconstock) + tbutton.set_use_underline(True) + text = tool['string'] + if '_' not in text: + text = '_' + text + tbutton.set_label(text) + gtktoolbar.insert(tbutton, -1) + + tbutton.connect('clicked', self._sig_clicked, tool, icontype) + + if hasattr(gtk, 'MenuToolButton') and icontype == 'print': + menu = gtk.Menu() + for mtype, text in (('print', _('_Direct Print')), + ('email', _('Email as Attachment'))): + menuitem = gtk.MenuItem(text) + tool2 = tool.copy() + if mtype == 'print': + tool2['direct_print'] = True + tool2['email_print'] = False + else: + tool2['direct_print'] = False + tool2['email_print'] = True + menuitem.connect('activate', self._sig_clicked, tool2, + icontype) + menu.add(menuitem) + menuitem.show() + tbutton.set_menu(menu) + + hbox.show_all() + self.display() self.widget_tree.connect('button-press-event', self.__hello) @@ -196,6 +253,34 @@ self.widget_tree.connect('drag-data-received', self.drag_data_received) self.widget_tree.connect('drag-data-delete', self.drag_data_delete) + def _sig_clicked(self, widget, action, atype): + return self._action(action, atype) + + def _action(self, action, atype): + context = self.screen.context.copy() + act = action.copy() + obj_ids = self.screen.current_view.sel_ids_get() + obj_id = self.screen.current_model.id + if not obj_ids and not obj_id: + common.message(_('No record selected!'), self.window) + return False + email = {} + if action.get('email'): + email = self.screen.current_model.expr_eval(action['email']) + if not email: + email = {} + email['subject'] = action['name'].replace('_', '') + act['email'] = email + data = { + 'model': self.screen.name, + 'id': obj_id, + 'ids': obj_ids, + } + obj = service.LocalService('action.main') + value = obj._exec_action(act, data, context) + self.screen.reload() + return value + def drag_drop(self, treeview, context, x, y, time): treeview.emit_stop_by_name('drag-drop') treeview.drag_get_data(context, context.targets[-1], time)
_______________________________________________ Mailing list: https://launchpad.net/~openerp-dev-gtk Post to : [email protected] Unsubscribe : https://launchpad.net/~openerp-dev-gtk More help : https://help.launchpad.net/ListHelp

