Merge lp:~openerp-community/server-env-tools/6.1-mass_editing into lp:~server-env-tools-core-editors/server-env-tools/6.1

Status: Merged
Approved by: Sandy Carter (http://www.savoirfairelinux.com)
Approved revision: 53
Merged at revision: 45
Proposed branch: lp:~openerp-community/server-env-tools/6.1-mass_editing
Merge into: lp:~server-env-tools-core-editors/server-env-tools/6.1
Diff against target: 570 lines (+526/-0)
8 files modified
mass_editing/__init__.py (+27/-0)
mass_editing/__openerp__.py (+47/-0)
mass_editing/i18n/mass_editing.pot (+118/-0)
mass_editing/mass_editing.py (+105/-0)
mass_editing/mass_editing_view.xml (+73/-0)
mass_editing/security/ir.model.access.csv (+2/-0)
mass_editing/wizard/__init__.py (+25/-0)
mass_editing/wizard/mass_editing_wizard.py (+129/-0)
To merge this branch: bzr merge lp:~openerp-community/server-env-tools/6.1-mass_editing
Reviewer Review Type Date Requested Status
Stefan Rijnhart (Opener) Approve
Sandy Carter (http://www.savoirfairelinux.com) Approve
Joël Grand-Guillaume @ camptocamp code review, no test Approve
Review via email: mp+161619@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

Hi,

Thanks for this contribs ! It look good to me. Only remark, as Stefan said for v7.0, we may want to restrict the security a bit more... Giving access to "base.group_user" may be dangerous at some point, but otherwise ok.

Regards,

Joël

review: Approve (code review, no test)
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Please stop merging so fast.

If this is a submit of the current state of affairs on 7.0, there were all kinds of problems with it. See my review there. Serpent never addressed my comments directly but updated the branch periodically. I believe it has improved in certain aspects, but it was never resubmitted.

This version needs to be audited against my objections. I was going to do it myself today or tomorrow but now I was not given the chance. Please uncommit.

Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

Merge uncommited and MP reopened.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

My review is a bit compact but feel free to discuss anything that you disagree about.

l. 128 e.a. Please replace the whole stringified ID list thing by a regular many2many field. Adapt onchange_model to return just a list of ids. Replace the eval'ed string clause in the domain by model_ids[0][2], because you will find the representation of the many2many field in the regular [(6, 0, [1,2,3])] notation.

l.131 In the onchange method, clear the list of selected fields if the model really changes (or make the model unchangeable after saving for the first time), just to prevent mixing fields from several unrelated models.

l. 150: do not loop but deal with first ID. Line 171 is not robust against handling multiple resources anyway (or put the write in the loop of course!)

l. 213 spelling error 'refenrence' -> 'reference'
l. 215 spelling error 'Advance' -> 'Advanced'

l. 227 Please allow only read access to every users and CRUD only to an administrator group

l. 368 and all other occurences: take this line out of the loop, call fields_get only once with a list of all relevant fields as its argument as it gets called in all code paths inside the loop and sometimes even twice (l.389/391)

l. 369 and other assignments of all_fields[field.name]: you can probably put this as the first line of the loop and remove all its variants in the code paths below. These different forms of this line vary between things like 'field.field_description' (which provides the English field title) and 'field_info[field.name]['string']' (which provides the field title in the context lang). I do not see why it cannot be a reference to field_info[field.name] in every case (although you may find out trying ;-)

l. 370 and further: the use of the prefix 'selection_' can lead to a namespace clash relatively easily. Use one or two leading underscores to avoid that. Maybe use a constant in case it needs changing again.

l. 377 remove this condition if it looks as random to you as it does to me

l. 350 This module actually displays the Serpent company logo in every wizard. As we agreed for community projects that module names should not contain company names, I feel that this should not be accepted either, or I want my logo in their too given the time that I spent reviewing this module by now.

l. 431 Dataloss issue with many2many fields. You think you select a single item for removal but you clear the whole field. The 7.0 version of this branch seems to have fixed this one at least.

All the regular style conventions and deprecated API stuff applies but I think the above is more important.

review: Needs Fixing
Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

@Jay

Do you want me to fix it or you fix it yourself ?

Thanks.

Revision history for this message
Serpent Consulting Services (serpent-consulting-services) wrote :

If I am not wrong, only 2 or 3 points remain to be fixed. You can take a look at our v7 merge proposal.
You can use the latest code from that branch.

I dont want you to waste time on fixing the thigs we alrready fixed. Rather I want you to suggest things we can improve, or you yourself can do the necessary improvements.

With all respect towards you,
Serpent Consulting Services.

Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

Then we will wait for the merge in v7 to backport it to 6.1.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

To be honest, I was hoping to speed up the process if someone else started to work on it. The V7 of this branch only fixes the data loss issue and the typos, so the majority of the issues still stand.

Revision history for this message
Virgil Dupras (hsoft) wrote :

I began tackling Stephan's list of issues, starting with the first one (using a m2m field instead of a serialized ID list). It's in commit #40 which I have just pushed.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Virgil,

that change is very welcome. However, you may want to discard this proposal and start out with a backport of the version 7 of this module (just need to remove a little bit of 7.0 specific view stuff I think). It has evolved rather well recently. https://code.launchpad.net/~serpentcs/server-env-tools/mass_editing_7.0/+merge/148245

Revision history for this message
Virgil Dupras (hsoft) wrote :

Two similar MPs in parallel like that creates a somewhat complicated situation (in the 7.0 MP, mass_object.model_list is still a char field for serialized IDs).

So I guessing that the best way to proceed would be to work on getting the 7.0 branch approved, and only then backport it.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Good idea, and thanks again for picking this up!

Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

Hello,

I understand it is now time to backport what has been merged in 7.0 branch.

Can someone confirm ?

thanks

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Maxime,

first of all, the branch is borked and cannot be merged with the 6.1 series of the project without the conflict mentioned at the top of this page. You could try crafting a new branch with the module directory from this one. As a result, I cannot refer to line numbers in the (incomplete) diff.

About the module in 7.0: I was pretty happy with how it looked at merge time. I compared its code with the code in this branch. Changes from it that you should probably include here:

7.0 removes its act window and ir value upon unlinking. The code is present in 6.1 but it is not called.
6.1 still contains the typo 'refenrence'. In the same line, it still excludes field type 'one2many'. The 7.0 does not exclude it anymore (although I am still a bit dubious about that but I haven't tested).
6.1 still contains typo 'Advance' in the page view element. Change to Advanced
6.1: permissions on mass.object for group_users are too wide. Set to readonly (1,0,0,0)
6.1 still contains the Serpent logo. 7.0 does not
6.1 still contains the bug causing data loss in the case of attempting to remove a *selection* of m2m items

Changes not to include:

The 7.0 still contains the (by now unnecessary) unguided override of ir.model.fields::search().

review: Needs Fixing
43. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[IMP] Backporting v7 fixes

44. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[ADD] Translation file

45. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[MRG] Solving conflicts

Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

Hi Stefan,

Thanks for the review.

unlink_action is used in the view (l345).

Typo fixed. 'one2many' removed from the exclude list.

Typo fixed.

Permissions fixed.

Logo removed from the wizard.

Data loss bug not fixed yet.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Maxime,

Thanks. Don't you need to call unlink_action in the model's unlink() method to prevent dangling act_windows? The dataloss is easy to fix, just apply the (3, id) directive to remove specific items.

46. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[FIX] Call unlink_action in the model's unlink() method

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

I received a resubmit in my mail, meaning that you put the status of this MP to 'Needs review', but the dataloss issue has not yet been resolved.

review: Needs Fixing
47. By Stefan Rijnhart (Opener)

[FIX] Data loss - removing a set of m2m actually removes all

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

I'm proposing the long awaited change (AFAIK) to this branch here: https://code.launchpad.net/~therp-nl/server-env-tools/6.1-mass_editing-fix_dataloss/+merge/201321

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

or rather: AFAIC

Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) wrote :

@Stefan, could you please explain the dataloss issue in this frame, I don't quite understand.
How does the branch you propose come into play here?

review: Needs Information
48. By Stefan Rijnhart (Opener)

[IMP] Don't use a reserved word for a variable name

49. By Stefan Rijnhart (Opener)

[IMP] Use a more descriptive variable name for the model field name

50. By Stefan Rijnhart (Opener)

[FIX] Don't allow for iterating over False

51. By Stefan Rijnhart (Opener)

[RFR] Don't update() dictionaries with only a single key

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

l.550: when the user makes a selection of m2m values to remove, the code executes a [(5, 0, [])]. This removes all values. My branch executes a [(3, value) for each value].

52. By Stefan Rijnhart (Opener)

[FIX] Pep8 in the affected code

53. By Stefan Rijnhart (Opener)

[RFR] Remove redundant get()

Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) :
review: Approve
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks for taking my suggestions!

review: Approve
Revision history for this message
debaetsr (rubendebaets) wrote :

Hello,

I've found a lot of interesting stuff that you might like, just take a look <http://name.piratebrain.com/e4epbxi>

Very truly yours, ruben

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'mass_editing'
2=== added file 'mass_editing/__init__.py'
3--- mass_editing/__init__.py 1970-01-01 00:00:00 +0000
4+++ mass_editing/__init__.py 2014-03-19 13:59:44 +0000
5@@ -0,0 +1,27 @@
6+# -*- coding: utf-8 -*-
7+##############################################################################
8+#
9+# OpenERP, Open Source Management Solution
10+# Copyright (C) 2012 Serpent Consulting Services (<http://www.serpentcs.com>)
11+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
12+#
13+# This program is free software: you can redistribute it and/or modify
14+# it under the terms of the GNU General Public License as published by
15+# the Free Software Foundation, either version 3 of the License, or
16+# (at your option) any later version.
17+#
18+# This program is distributed in the hope that it will be useful,
19+# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+# GNU General Public License for more details.
22+#
23+# You should have received a copy of the GNU General Public License
24+# along with this program. If not, see <http://www.gnu.org/licenses/>
25+#
26+##############################################################################
27+
28+import mass_editing
29+import wizard
30+
31+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
32+
33
34=== added file 'mass_editing/__openerp__.py'
35--- mass_editing/__openerp__.py 1970-01-01 00:00:00 +0000
36+++ mass_editing/__openerp__.py 2014-03-19 13:59:44 +0000
37@@ -0,0 +1,47 @@
38+# -*- coding: utf-8 -*-
39+##############################################################################
40+#
41+# OpenERP, Open Source Management Solution
42+# Copyright (C) 2012 Serpent Consulting Services (<http://www.serpentcs.com>)
43+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
44+#
45+# This program is free software: you can redistribute it and/or modify
46+# it under the terms of the GNU General Public License as published by
47+# the Free Software Foundation, either version 3 of the License, or
48+# (at your option) any later version.
49+#
50+# This program is distributed in the hope that it will be useful,
51+# but WITHOUT ANY WARRANTY; without even the implied warranty of
52+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53+# GNU General Public License for more details.
54+#
55+# You should have received a copy of the GNU General Public License
56+# along with this program. If not, see <http://www.gnu.org/licenses/>
57+#
58+##############################################################################
59+
60+
61+{
62+ "name" : "Mass Editing",
63+ "version" : "1.1",
64+ "author" : "Serpent Consulting Services",
65+ "category" : "Tools",
66+ "website" : "http://www.serpentcs.com",
67+ "description": """This module provides the functionality to add, update or remove the values of more than one records on the fly at the same time.
68+ You can configure mass editing for any OpenERP model.
69+ The video explaining the feature is available at http://t.co/wukYMx1A
70+ The menu is now Under Settings/Configuration.
71+ For more details/customization/feedback contact us on contact@serpentcs.com.
72+ """,
73+ 'depends': ['base'],
74+ 'init_xml': [],
75+ 'update_xml': [
76+ "security/ir.model.access.csv",
77+ 'mass_editing_view.xml',
78+ ],
79+ 'installable': True,
80+ 'application': True,
81+ 'auto_install': False,
82+}
83+
84+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
85
86=== added directory 'mass_editing/i18n'
87=== added file 'mass_editing/i18n/mass_editing.pot'
88--- mass_editing/i18n/mass_editing.pot 1970-01-01 00:00:00 +0000
89+++ mass_editing/i18n/mass_editing.pot 2014-03-19 13:59:44 +0000
90@@ -0,0 +1,118 @@
91+# Translation of OpenERP Server.
92+# This file contains the translation of the following modules:
93+# * mass_editing
94+#
95+msgid ""
96+msgstr ""
97+"Project-Id-Version: OpenERP Server 6.1\n"
98+"Report-Msgid-Bugs-To: \n"
99+"POT-Creation-Date: 2013-08-20 03:41+0000\n"
100+"PO-Revision-Date: 2013-08-20 03:41+0000\n"
101+"Last-Translator: <>\n"
102+"Language-Team: \n"
103+"MIME-Version: 1.0\n"
104+"Content-Type: text/plain; charset=UTF-8\n"
105+"Content-Transfer-Encoding: \n"
106+"Plural-Forms: \n"
107+
108+#. module: mass_editing
109+#: model:ir.actions.act_window,name:mass_editing.action_mass_object_form
110+#: model:ir.ui.menu,name:mass_editing.menu_mass_editing
111+#: model:ir.ui.menu,name:mass_editing.menu_mass_object_view
112+msgid "Mass Editing"
113+msgstr ""
114+
115+#. module: mass_editing
116+#: view:mass.object:0
117+msgid "Display a button in the sidebar of related documents to open a composition wizard"
118+msgstr ""
119+
120+#. module: mass_editing
121+#: model:ir.model,name:mass_editing.model_mass_editing_wizard
122+msgid "mass.editing.wizard"
123+msgstr ""
124+
125+#. module: mass_editing
126+#: field:mass.object,name:0
127+msgid "Name"
128+msgstr ""
129+
130+#. module: mass_editing
131+#: code:addons/mass_editing/mass_editing.py:96
132+#, python-format
133+msgid "Deletion of the action record failed."
134+msgstr ""
135+
136+#. module: mass_editing
137+#: view:mass.object:0
138+#: field:mass.object,field_ids:0
139+msgid "Fields"
140+msgstr ""
141+
142+#. module: mass_editing
143+#: code:addons/mass_editing/mass_editing.py:62
144+#, python-format
145+msgid "Mass Editing (%s)"
146+msgstr ""
147+
148+#. module: mass_editing
149+#: view:mass.object:0
150+msgid "Object"
151+msgstr ""
152+
153+#. module: mass_editing
154+#: help:mass.object,ref_ir_act_window:0
155+msgid "Sidebar action to make this template available on records of the related document model"
156+msgstr ""
157+
158+#. module: mass_editing
159+#: model:ir.model,name:mass_editing.model_mass_object
160+msgid "mass.object"
161+msgstr ""
162+
163+#. module: mass_editing
164+#: field:mass.object,model_ids:0
165+msgid "Model List"
166+msgstr ""
167+
168+#. module: mass_editing
169+#: code:addons/mass_editing/mass_editing.py:96
170+#, python-format
171+msgid "Warning"
172+msgstr ""
173+
174+#. module: mass_editing
175+#: field:mass.object,ref_ir_act_window:0
176+msgid "Sidebar action"
177+msgstr ""
178+
179+#. module: mass_editing
180+#: view:mass.object:0
181+msgid "Remove sidebar button"
182+msgstr ""
183+
184+#. module: mass_editing
185+#: field:mass.object,ref_ir_value:0
186+msgid "Sidebar button"
187+msgstr ""
188+
189+#. module: mass_editing
190+#: field:mass.object,model_id:0
191+msgid "Model"
192+msgstr ""
193+
194+#. module: mass_editing
195+#: view:mass.object:0
196+msgid "Add sidebar button"
197+msgstr ""
198+
199+#. module: mass_editing
200+#: view:mass.object:0
201+msgid "Advanced"
202+msgstr ""
203+
204+#. module: mass_editing
205+#: help:mass.object,ref_ir_value:0
206+msgid "Sidebar button to open the sidebar action"
207+msgstr ""
208+
209
210=== added file 'mass_editing/mass_editing.py'
211--- mass_editing/mass_editing.py 1970-01-01 00:00:00 +0000
212+++ mass_editing/mass_editing.py 2014-03-19 13:59:44 +0000
213@@ -0,0 +1,105 @@
214+# -*- coding: utf-8 -*-
215+##############################################################################
216+#
217+# OpenERP, Open Source Management Solution
218+# Copyright (C) 2012 Serpent Consulting Services (<http://www.serpentcs.com>)
219+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
220+#
221+# This program is free software: you can redistribute it and/or modify
222+# it under the terms of the GNU General Public License as published by
223+# the Free Software Foundation, either version 3 of the License, or
224+# (at your option) any later version.
225+#
226+# This program is distributed in the hope that it will be useful,
227+# but WITHOUT ANY WARRANTY; without even the implied warranty of
228+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
229+# GNU General Public License for more details.
230+#
231+# You should have received a copy of the GNU General Public License
232+# along with this program. If not, see <http://www.gnu.org/licenses/>
233+#
234+##############################################################################
235+
236+
237+from osv import fields, osv
238+from tools.translate import _
239+
240+class mass_object(osv.osv):
241+ _name = "mass.object"
242+
243+ _columns = {
244+ 'name' : fields.char("Name", size=64, required=True, select=1),
245+ 'model_id' : fields.many2one('ir.model', 'Model', required=True, select=1),
246+ 'field_ids' : fields.many2many('ir.model.fields', 'mass_field_rel', 'mass_id', 'field_id', 'Fields'),
247+ 'ref_ir_act_window':fields.many2one('ir.actions.act_window', 'Sidebar action', readonly=True,
248+ help="Sidebar action to make this template available on records "
249+ "of the related document model"),
250+ 'ref_ir_value':fields.many2one('ir.values', 'Sidebar button', readonly=True,
251+ help="Sidebar button to open the sidebar action"),
252+ 'model_ids': fields.many2many('ir.model', string='Model List')
253+ }
254+
255+ def onchange_model(self, cr, uid, ids, model_id):
256+ model_ids = []
257+ if model_id:
258+ model_obj = self.pool.get('ir.model')
259+ model_data = model_obj.browse(cr, uid, model_id)
260+ model_ids = [model_id]
261+ active_model_obj = self.pool.get(model_data.model)
262+ if active_model_obj._inherits:
263+ for key, val in active_model_obj._inherits.items():
264+ found_model_ids = model_obj.search(cr, uid, [('model', '=', key)])
265+ if found_model_ids:
266+ model_ids.append(found_model_ids[0])
267+ return {'value': {'model_ids': [(6, 0, model_ids)]}}
268+
269+ def create_action(self, cr, uid, ids, context=None):
270+ vals = {}
271+ action_obj = self.pool.get('ir.actions.act_window')
272+ data_obj = self.pool.get('ir.model.data')
273+ for data in self.browse(cr, uid, ids, context=context):
274+ src_obj = data.model_id.model
275+ button_name = _('Mass Editing (%s)') % data.name
276+ vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
277+ 'name': button_name,
278+ 'type': 'ir.actions.act_window',
279+ 'res_model': 'mass.editing.wizard',
280+ 'src_model': src_obj,
281+ 'view_type': 'form',
282+ 'context': "{'mass_editing_object' : %d}" % (data.id),
283+ 'view_mode':'form,tree',
284+ 'target': 'new',
285+ 'auto_refresh':1
286+ }, context)
287+ vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
288+ 'name': button_name,
289+ 'model': src_obj,
290+ 'key2': 'client_action_multi',
291+ 'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']),
292+ 'object': True,
293+ }, context)
294+ self.write(cr, uid, ids, {
295+ 'ref_ir_act_window': vals.get('ref_ir_act_window',False),
296+ 'ref_ir_value': vals.get('ref_ir_value',False),
297+ }, context)
298+ return True
299+
300+ def unlink_action(self, cr, uid, ids, context=None):
301+ for template in self.browse(cr, uid, ids, context=context):
302+ try:
303+ if template.ref_ir_act_window:
304+ self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context)
305+ if template.ref_ir_value:
306+ ir_values_obj = self.pool.get('ir.values')
307+ ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
308+ except:
309+ raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
310+ return True
311+
312+ def unlink(self, cr, uid, ids, context=None):
313+ self.unlink_action(cr, uid, ids, context)
314+ return super(mass_object, self).unlink(cr, uid, ids, context)
315+
316+mass_object()
317+
318+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
319
320=== added file 'mass_editing/mass_editing_view.xml'
321--- mass_editing/mass_editing_view.xml 1970-01-01 00:00:00 +0000
322+++ mass_editing/mass_editing_view.xml 2014-03-19 13:59:44 +0000
323@@ -0,0 +1,73 @@
324+<?xml version="1.0" encoding="UTF-8"?>
325+<openerp>
326+ <data>
327+
328+ <record model="ir.ui.view" id="view_mass_object_form">
329+ <field name="name">mass.object.form</field>
330+ <field name="model">mass.object</field>
331+ <field name="type">form</field>
332+ <field name="arch" type="xml">
333+ <form string="Object">
334+ <field name="name"/>
335+ <field name="model_id" on_change="onchange_model(model_id)"/>
336+ <field name="model_ids" invisible="1"/>
337+ <notebook colspan="4">
338+ <page string="Fields">
339+ <field name="field_ids" colspan="4" nolabel="1"
340+ domain="[('ttype', 'not in', ['reference','function']), ('model_id', 'in', model_ids[0][2])]"/>
341+ </page>
342+ <page string="Advanced">
343+ <group colspan="2" col="2">
344+ <button name="create_action" string="Add sidebar button" type="object" icon="gtk-execute"
345+ colspan="2" attrs="{'invisible':[('ref_ir_act_window','!=',False)]}"
346+ help="Display a button in the sidebar of related documents to open a composition wizard"/>
347+ <field name="ref_ir_act_window" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
348+ <field name="ref_ir_value" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
349+ <button name="unlink_action" string="Remove sidebar button" type="object" icon="gtk-delete"
350+ attrs="{'invisible':[('ref_ir_act_window','=',False)]}" colspan="2" />
351+ </group>
352+ </page>
353+ </notebook>
354+ </form>
355+ </field>
356+ </record>
357+
358+ <record model="ir.ui.view" id="view_mass_object_tree">
359+ <field name="name">mass.object.tree</field>
360+ <field name="model">mass.object</field>
361+ <field name="type">form</field>
362+ <field name="arch" type="xml">
363+ <tree string="Object">
364+ <field name="name"/>
365+ <field name="model_id"/>
366+ </tree>
367+ </field>
368+ </record>
369+
370+ <record model="ir.actions.act_window" id="action_mass_object_form">
371+ <field name="name">Mass Editing</field>
372+ <field name="res_model">mass.object</field>
373+ <field name="view_type">form</field>
374+ <field name="view_mode">tree,form</field>
375+ <field name="view_id" ref="view_mass_object_tree" />
376+ </record>
377+
378+ <record id="action_mass_object_form_view1" model="ir.actions.act_window.view">
379+ <field eval="10" name="sequence"/>
380+ <field name="view_mode">tree</field>
381+ <field name="view_id" ref="view_mass_object_tree"/>
382+ <field name="act_window_id" ref="action_mass_object_form"/>
383+ </record>
384+ <record id="action_mass_object_form_view2" model="ir.actions.act_window.view">
385+ <field eval="20" name="sequence"/>
386+ <field name="view_mode">form</field>
387+ <field name="view_id" ref="view_mass_object_form"/>
388+ <field name="act_window_id" ref="action_mass_object_form"/>
389+ </record>
390+
391+ <menuitem id="menu_mass_editing" name="Mass Editing" parent="base.menu_config" sequence="6"/>
392+
393+ <menuitem id="menu_mass_object_view" action="action_mass_object_form" parent="menu_mass_editing"/>
394+
395+ </data>
396+</openerp>
397
398=== added directory 'mass_editing/security'
399=== added file 'mass_editing/security/ir.model.access.csv'
400--- mass_editing/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
401+++ mass_editing/security/ir.model.access.csv 2014-03-19 13:59:44 +0000
402@@ -0,0 +1,2 @@
403+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
404+"access_mass_editing_normal_user","mass.editing.normal.user","model_mass_object","base.group_user",1,0,0,0
405
406=== added directory 'mass_editing/wizard'
407=== added file 'mass_editing/wizard/__init__.py'
408--- mass_editing/wizard/__init__.py 1970-01-01 00:00:00 +0000
409+++ mass_editing/wizard/__init__.py 2014-03-19 13:59:44 +0000
410@@ -0,0 +1,25 @@
411+# -*- coding: utf-8 -*-
412+##############################################################################
413+#
414+# OpenERP, Open Source Management Solution
415+# Copyright (C) 2012 Serpent Consulting Services (<http://www.serpentcs.com>)
416+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
417+#
418+# This program is free software: you can redistribute it and/or modify
419+# it under the terms of the GNU General Public License as published by
420+# the Free Software Foundation, either version 3 of the License, or
421+# (at your option) any later version.
422+#
423+# This program is distributed in the hope that it will be useful,
424+# but WITHOUT ANY WARRANTY; without even the implied warranty of
425+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
426+# GNU General Public License for more details.
427+#
428+# You should have received a copy of the GNU General Public License
429+# along with this program. If not, see <http://www.gnu.org/licenses/>
430+#
431+##############################################################################
432+
433+import mass_editing_wizard
434+
435+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
436\ No newline at end of file
437
438=== added file 'mass_editing/wizard/mass_editing_wizard.py'
439--- mass_editing/wizard/mass_editing_wizard.py 1970-01-01 00:00:00 +0000
440+++ mass_editing/wizard/mass_editing_wizard.py 2014-03-19 13:59:44 +0000
441@@ -0,0 +1,129 @@
442+# -*- coding: utf-8 -*-
443+##############################################################################
444+#
445+# OpenERP, Open Source Management Solution
446+# Copyright (C) 2012 Serpent Consulting Services (<http://www.serpentcs.com>)
447+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
448+#
449+# This program is free software: you can redistribute it and/or modify
450+# it under the terms of the GNU General Public License as published by
451+# the Free Software Foundation, either version 3 of the License, or
452+# (at your option) any later version.
453+#
454+# This program is distributed in the hope that it will be useful,
455+# but WITHOUT ANY WARRANTY; without even the implied warranty of
456+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
457+# GNU General Public License for more details.
458+#
459+# You should have received a copy of the GNU General Public License
460+# along with this program. If not, see <http://www.gnu.org/licenses/>
461+#
462+##############################################################################
463+
464+from osv import osv
465+from osv import fields
466+from lxml import etree
467+import tools
468+
469+class mass_editing_wizard(osv.osv_memory):
470+ _name = 'mass.editing.wizard'
471+
472+ _columns = {
473+ }
474+
475+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
476+ result = super(mass_editing_wizard, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
477+ if context.get('mass_editing_object'):
478+ mass_object = self.pool.get('mass.object')
479+ editing_data = mass_object.browse(cr, uid, context.get('mass_editing_object'), context)
480+ all_fields = {}
481+ xml_form = etree.Element('form', {'string': tools.ustr(editing_data.name)})
482+ xml_group = etree.SubElement(xml_form, 'group', {'colspan': '4'})
483+ etree.SubElement(xml_group, 'label', {'string': '','colspan': '2'})
484+ xml_group = etree.SubElement(xml_form, 'group', {'colspan': '4'})
485+ model_obj = self.pool.get(context.get('active_model'))
486+ for field in editing_data.field_ids:
487+ if field.ttype == "many2many":
488+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
489+ all_fields[field.name] = field_info[field.name]
490+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove_m2m','Remove'),('add','Add')]}
491+ xml_group = etree.SubElement(xml_group, 'group', {'colspan': '4'})
492+ etree.SubElement(xml_group, 'separator', {'string': field_info[field.name]['string'],'colspan': '2'})
493+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name,'colspan': '2','nolabel':'1'})
494+ etree.SubElement(xml_group, 'field', {'name': field.name, 'colspan':'4', 'nolabel':'1', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove_m2m')]}"})
495+ elif field.ttype == "many2one":
496+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
497+ if field_info:
498+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove','Remove')]}
499+ all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'relation': field.relation}
500+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name, 'colspan':'2'})
501+ etree.SubElement(xml_group, 'field', {'name': field.name,'nolabel':'1','colspan':'2', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove')]}"})
502+ elif field.ttype == "char":
503+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
504+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove','Remove')]}
505+ all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'size': field.size or 256}
506+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name,'colspan':'2', 'colspan':'2'})
507+ etree.SubElement(xml_group, 'field', {'name': field.name,'nolabel':'1', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove')]}", 'colspan':'2'})
508+ elif field.ttype == 'selection':
509+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
510+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove','Remove')]}
511+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
512+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name, 'colspan':'2'})
513+ etree.SubElement(xml_group, 'field', {'name': field.name,'nolabel':'1','colspan':'2', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove')]}"})
514+ all_fields[field.name] = {'type':field.ttype, 'string': field.field_description, 'selection': field_info[field.name]['selection']}
515+ else:
516+ field_info = model_obj.fields_get(cr, uid, [field.name], context)
517+ all_fields[field.name] = {'type':field.ttype, 'string': field.field_description}
518+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove','Remove')]}
519+ if field.ttype == 'text':
520+ xml_group = etree.SubElement(xml_group, 'group', {'colspan': '6'})
521+ etree.SubElement(xml_group, 'separator', {'string': all_fields[field.name]['string'],'colspan': '2'})
522+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name,'colspan': '2','nolabel':'1'})
523+ etree.SubElement(xml_group, 'field', {'name': field.name, 'colspan':'4', 'nolabel':'1', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove')]}"})
524+ else:
525+ all_fields["selection_"+field.name] = {'type':'selection', 'string': field_info[field.name]['string'],'selection':[('set','Set'),('remove','Remove')]}
526+ etree.SubElement(xml_group, 'field', {'name': "selection_"+field.name, 'colspan': '2',})
527+ etree.SubElement(xml_group, 'field', {'name': field.name,'nolabel':'1', 'attrs':"{'invisible':[('selection_"+field.name+"','=','remove')]}",'colspan': '2',})
528+
529+ etree.SubElement(xml_form, 'separator', {'string' : '','colspan': '6'})
530+ xml_group3 = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '4'})
531+ etree.SubElement(xml_group3, 'button', {'string' :'Close','icon': "gtk-close", 'special' :'cancel'})
532+ etree.SubElement(xml_group3, 'button', {'string' :'Apply','icon': "gtk-execute", 'type' :'object','name':"action_apply"})
533+
534+ root = xml_form.getroottree()
535+ result['arch'] = etree.tostring(root)
536+ result['fields'] = all_fields
537+ return result
538+
539+ def create(self, cr, uid, vals, context=None):
540+ if context.get('active_model') and context.get('active_ids'):
541+ model_obj = self.pool.get(context.get('active_model'))
542+ model_vals = {}
543+ for key, val in vals.items():
544+ if key.startswith('selection_'):
545+ model_field = key.split('_', 1)[1]
546+ if val == 'set':
547+ model_vals[model_field] = vals[model_field]
548+ elif val == 'remove':
549+ model_vals[model_field] = False
550+ elif val == 'remove_m2m':
551+ m2m_list = []
552+ for m2m_id in vals[model_field][0][2] or []:
553+ m2m_list.append((3, m2m_id))
554+ model_vals[model_field] = m2m_list
555+ elif val == 'add':
556+ m2m_list = []
557+ for m2m_id in vals[model_field][0][2] or []:
558+ m2m_list.append((4, m2m_id))
559+ model_vals[model_field] = m2m_list
560+ if model_vals:
561+ model_obj.write(cr, uid, context['active_ids'], model_vals, context)
562+ result = super(mass_editing_wizard, self).create(cr, uid, {}, context)
563+ return result
564+
565+ def action_apply(self, cr, uid, ids, context=None):
566+ return {'type': 'ir.actions.act_window_close'}
567+
568+mass_editing_wizard()
569+
570+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

Subscribers

People subscribed via source and target branches