diff options
| author | Harry (OpenERP) <hmo@tinyerp.com> | 2010-07-13 20:01:41 +0530 |
|---|---|---|
| committer | Harry (OpenERP) <hmo@tinyerp.com> | 2010-07-13 20:01:41 +0530 |
| commit | 72c068a75e0811fc0aaaeb8622afab2b1f1c3ede (patch) | |
| tree | 1741d7aad768d613d970a30d54a4c0af2cc87ed7 /addons/document | |
| parent | 506b249a0fc32f5c6dad50ae85c39c45b0a4f9c2 (diff) | |
| parent | bbbf42c6ba0f5aa05a53c5b31f909432cbd5f708 (diff) | |
[MERGE]
bzr revid: hmo@tinyerp.com-20100713143141-wozs7fnurj8ckblw
Diffstat (limited to 'addons/document')
| -rw-r--r-- | addons/document/directory_content.py | 21 | ||||
| -rw-r--r-- | addons/document/document.py | 9 | ||||
| -rw-r--r-- | addons/document/document_directory.py | 4 | ||||
| -rw-r--r-- | addons/document/document_view.xml | 3 | ||||
| -rw-r--r-- | addons/document/nodes.py | 114 |
5 files changed, 130 insertions, 21 deletions
diff --git a/addons/document/directory_content.py b/addons/document/directory_content.py index 2d434712f56..bec4f25e45d 100644 --- a/addons/document/directory_content.py +++ b/addons/document/directory_content.py @@ -58,7 +58,9 @@ class document_directory_content(osv.osv): 'suffix': fields.char('Suffix', size=16), 'report_id': fields.many2one('ir.actions.report.xml', 'Report'), 'extension': fields.selection(_extension_get, 'Document Type', required=True, size=4), - 'include_name': fields.boolean('Include Record Name', help="Check this field if you want that the name of the file start by the record name."), + 'include_name': fields.boolean('Include Record Name', + help="Check this field if you want that the name of the file to contain the record name." \ + "\nIf set, the directory will have to be a resource one."), 'directory_id': fields.many2one('document.directory', 'Directory'), } _defaults = { @@ -88,12 +90,19 @@ class document_directory_content(osv.osv): tname = (content.prefix or '') + (content.suffix or '') + (content.extension or '') if tname.find('/'): tname=tname.replace('/', '_') + act_id = False + if 'dctx_res_id' in node.dctx: + act_id = node.dctx['dctx_res_id'] + elif hasattr(node, 'res_id'): + act_id = node.res_id + else: + act_id = node.context.context.get('res_id',False) if not nodename: - n = nodes.node_content(tname, node, node.context,content) + n = nodes.node_content(tname, node, node.context,content, act_id=act_id) res2.append( n) else: if nodename == tname: - n = nodes.node_content(tname, node, node.context,content) + n = nodes.node_content(tname, node, node.context,content, act_id=act_id) n.fill_fields(cr) res2.append(n) return res2 @@ -108,6 +117,10 @@ class document_directory_content(osv.osv): raise Exception("Invalid content: %s" % node.extension) report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.report_id) srv = netsvc.Service._services['report.'+report.report_name] - pdf,pdftype = srv.create(cr, uid, [node.context.context['res_id']], {}, {}) + ctx = node.context.context.copy() + ctx.update(node.dctx) + pdf,pdftype = srv.create(cr, uid, [node.act_id,], {}, context=ctx) return pdf document_directory_content() + +#eof
\ No newline at end of file diff --git a/addons/document/document.py b/addons/document/document.py index 6ab6cae5281..ac3d7b9187d 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -47,7 +47,10 @@ class document_file(osv.osv): def _data_get(self, cr, uid, ids, name, arg, context): fbrl = self.browse(cr, uid, ids, context=context) - nctx = nodes.get_node_context(cr, uid, context) + nctx = nodes.get_node_context(cr, uid, context={}) + # nctx will /not/ inherit the caller's context. Most of + # it would be useless, anyway (like active_id, active_model, + # bin_size etc.) result = {} bin_size = context.get('bin_size', False) for fbro in fbrl: @@ -67,7 +70,7 @@ class document_file(osv.osv): if not value: return True fbro = self.browse(cr, uid, id, context=context) - nctx = nodes.get_node_context(cr, uid, context) + nctx = nodes.get_node_context(cr, uid, context={}) fnode = nodes.node_file(None, None, nctx, fbro) res = fnode.set_data(cr, base64.decodestring(value), fbro) return res @@ -156,7 +159,7 @@ class document_file(osv.osv): raise osv.except_osv(_('ValidateError'), _('File name must be unique!')) if ('parent_id' in vals) or ('name' in vals): # perhaps this file is renaming or changing directory - nctx = nodes.get_node_context(cr,uid,context) + nctx = nodes.get_node_context(cr,uid,context={}) dirobj = self.pool.get('document.directory') if 'parent_id' in vals: dbro = dirobj.browse(cr, uid, vals['parent_id'], context=context) diff --git a/addons/document/document_directory.py b/addons/document/document_directory.py index 0685f5c08ff..f5b9202fc8e 100644 --- a/addons/document/document_directory.py +++ b/addons/document/document_directory.py @@ -57,6 +57,9 @@ class document_directory(osv.osv): 'ressource_type_id': fields.many2one('ir.model', 'Resource model', help="Select an object here and there will be one folder per record of that resource."), 'resource_field': fields.many2one('ir.model.fields', 'Name field', help='Field to be used as name on resource directories. If empty, the "name" will be used.'), + 'resource_find_all': fields.boolean('Find all resources', required=True, + help="If true, all attachments that match this resource will " \ + " be located. If false, only ones that have this as parent." ), 'ressource_parent_type_id': fields.many2one('ir.model', 'Parent Model', help="If you put an object here, this directory template will appear bellow all of these objects. " \ "Don't put a parent directory if you select a parent model."), @@ -103,6 +106,7 @@ class document_directory(osv.osv): 'type': lambda *args: 'directory', 'ressource_id': lambda *a: 0, 'storage_id': _get_def_storage, + 'resource_find_all': True, } _sql_constraints = [ ('dirname_uniq', 'unique (name,parent_id,ressource_id,ressource_parent_type_id)', 'The directory name must be unique !'), diff --git a/addons/document/document_view.xml b/addons/document/document_view.xml index 693d7370567..998d1e93188 100644 --- a/addons/document/document_view.xml +++ b/addons/document/document_view.xml @@ -82,6 +82,7 @@ <group colspan="4" col="4" attrs="{'invisible': [('type','!=','ressource')]}"> <field name="ressource_type_id" on_change="onchange_content_id(ressource_type_id)" attrs="{'required': [('type','=','ressource')] }"/> + <field name="resource_find_all" groups="base.group_extended" /> <newline/> <field name="resource_field" domain="[('model_id','=',ressource_type_id), ('ttype', 'in', ('char', 'selection', 'date', 'datetime'))]"/> <field name="ressource_tree"/> @@ -96,7 +97,7 @@ </page> <page string="Generated Files" groups="base.group_extended"> <label colspan="4" string="For each entry here, virtual files will appear in this folder." /> - <field name="content_ids" nolabel="1" colspan="4" attrs="{'readonly': [('ressource_type_id','=',False)]}"> + <field name="content_ids" nolabel="1" colspan="4" > <form string="Contents"> <field name="name"/> <field name="sequence"/> diff --git a/addons/document/nodes.py b/addons/document/nodes.py index d710db37c15..e368c6fc5a0 100644 --- a/addons/document/nodes.py +++ b/addons/document/nodes.py @@ -31,6 +31,8 @@ import errno import os import time +from StringIO import StringIO + # # An object that represent an uri # path: the uri of the object @@ -226,7 +228,7 @@ class node_class(object): return False def get_data(self,cr): - raise IOError(errno.EINVAL, 'no data for %s' % self.type) + raise TypeError('no data for %s'% self.type) def open_data(self, cr, mode): """ Open a node_descriptor object for this node. @@ -240,7 +242,7 @@ class node_class(object): For this class, there is no data, so no implementation. Each child class that has data should override this. """ - raise IOError(errno.EINVAL, 'no data for %s' % self.type) + raise TypeError('no data for %s' % self.type) def _get_storage(self,cr): raise RuntimeError("no storage for base class") @@ -306,13 +308,23 @@ class node_class(object): Move operations, as instructed from APIs (eg. request from DAV) could use this function. """ - raise NotImplementedError + raise NotImplementedError(repr(self)) + + def create_child(self, cr, path, data=None): + """ Create a regular file under this node + """ + raise NotImplementedError(repr(self)) + + def create_child_collection(self, cr, objname): + """ Create a child collection (directory) under self + """ + raise NotImplementedError(repr(self)) def rm(self, cr): - raise RuntimeError("Not Implemented") + raise NotImplementedError(repr(self)) def rmcol(self, cr): - raise RuntimeError("Not Implemented") + raise NotImplementedError(repr(self)) def get_domain(self, cr, filters): return [] @@ -535,7 +547,7 @@ class node_dir(node_database): return dirobj.create(cr, uid, val) - def create_child(self, cr, path, data): + def create_child(self, cr, path, data=None): """ API function to create a child file object and node Return the node_* created """ @@ -647,6 +659,7 @@ class node_res_dir(node_class): self.uidperms = dirr.get_dir_permissions() self.res_model = dirr.ressource_type_id and dirr.ressource_type_id.model or False self.resm_id = dirr.ressource_id + self.res_find_all = dirr.resource_find_all self.namefield = dirr.resource_field.name or 'name' self.displayname = dirr.name # Important: the domain is evaluated using the *parent* dctx! @@ -761,16 +774,17 @@ class node_res_obj(node_class): self.write_date = parent.write_date self.content_length = 0 self.unixperms = 040750 - self.uidperms = parent.uidperms & 0x15 + self.uidperms = parent.uidperms & 15 self.uuser = parent.uuser self.ugroup = parent.ugroup self.res_model = res_model self.domain = parent.domain self.displayname = path self.dctx_dict = parent.dctx_dict + self.res_find_all = parent.res_find_all if res_bo: self.res_id = res_bo.id - dc2 = self.context.context + dc2 = self.context.context.copy() dc2.update(self.dctx) dc2['res_model'] = res_model dc2['res_id'] = res_bo.id @@ -796,6 +810,8 @@ class node_res_obj(node_class): return False if self.domain != other.domain: return False + if self.res_find_all != other.res_find_all: + return False if self.dctx != other.dctx: return False return self.dir_id == other.dir_id @@ -909,6 +925,8 @@ class node_res_obj(node_class): fil_obj = dirobj.pool.get('ir.attachment') + if self.res_find_all: + where2 = where where3 = where2 + [('res_model', '=', self.res_model), ('res_id','=',self.res_id)] # print "where clause for dir_obj", where2 ids = fil_obj.search(cr, uid, where3, context=ctx) @@ -960,7 +978,7 @@ class node_res_obj(node_class): return dirobj.create(cr, uid, val) - def create_child(self, cr, path, data): + def create_child(self, cr, path, data=None): """ API function to create a child file object and node Return the node_* created """ @@ -976,11 +994,12 @@ class node_res_obj(node_class): val = { 'name': path, 'datas_fname': path, - 'parent_id': self.dir_id, 'res_model': self.res_model, 'res_id': self.res_id, # Datas are not set here } + if not self.res_find_all: + val['parent_id'] = self.dir_id fil_id = fil_obj.create(cr, uid, val, context=ctx) fil = fil_obj.browse(cr, uid, fil_id, context=ctx) @@ -1204,9 +1223,6 @@ class node_content(node_class): self.dctx.update(dctx) self.act_id = act_id - def open(self, cr, mode=False): - raise DeprecationWarning() - def fill_fields(self, cr, dctx = None): """ Try to read the object and fill missing fields, like mimetype, dates etc. @@ -1233,7 +1249,29 @@ class node_content(node_class): self.content_length = len(data) return data + def open_data(self, cr, mode): + if mode.endswith('b'): + mode = mode[:-1] + if mode in ('r', 'w'): + cperms = mode[:1] + elif mode in ('r+', 'w+'): + cperms = 'rw' + else: + raise IOError(errno.EINVAL, "Cannot open at mode %s" % mode) + + if not self.check_perms(cperms): + raise IOError(errno.EPERM, "Permission denied") + + ctx = self.context.context.copy() + ctx.update(self.dctx) + + return nodefd_content(self, cr, mode, ctx) + def get_data_len(self, cr, fil_obj = None): + # FIXME : here, we actually generate the content twice!! + # we should have cached the generated content, but it is + # not advisable to do keep it in memory, until we have a cache + # expiration logic. if not self.content_length: self.get_data(cr,fil_obj) return self.content_length @@ -1249,3 +1287,53 @@ class node_content(node_class): def _get_ttag(self,cr): return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '') + + +class nodefd_content(StringIO, node_descriptor): + """ A descriptor to content nodes + """ + def __init__(self, parent, cr, mode, ctx): + node_descriptor.__init__(self, parent) + self._context=ctx + + if mode in ('r', 'r+'): + cntobj = parent.context._dirobj.pool.get('document.directory.content') + data = cntobj.process_read(cr, parent.context.uid, parent, ctx) + if data: + parent.content_length = len(data) + StringIO.__init__(self, data) + elif mode in ('w', 'w+'): + StringIO.__init__(self, None) + # at write, we start at 0 (= overwrite), but have the original + # data available, in case of a seek() + elif mode == 'a': + StringIO.__init__(self, None) + else: + logging.getLogger('document.content').error("Incorrect mode %s specified", mode) + raise IOError(errno.EINVAL, "Invalid file mode") + self.mode = mode + + def close(self): + # we now open a *separate* cursor, to update the data. + # FIXME: this may be improved, for concurrency handling + if self.mode == 'r': + StringIO.close(self) + return + + par = self._get_parent() + uid = par.context.uid + cr = pooler.get_db(par.context.dbname).cursor() + try: + if self.mode in ('w', 'w+', 'r+'): + data = self.getvalue() + cntobj = par.context._dirobj.pool.get('document.directory.content') + cntobj.process_write(cr, uid, parent, data, ctx) + elif self.mode == 'a': + raise NotImplementedError + cr.commit() + except Exception, e: + logging.getLogger('document.content').exception('Cannot update db content #%d for close:', par.cnt_id) + raise + finally: + cr.close() + StringIO.close(self) |
