Yogesh(Open ERP) has proposed merging 
lp:~openerp-dev/openerp-web/export-import-ysa into lp:openerp-web.

Requested reviews:
  OpenERP R&D Web Team (openerp-dev-web)

For more details, see:
https://code.launchpad.net/~openerp-dev/openerp-web/export-import-ysa/+merge/68838


Add Export related functionality same as trunk and add some following feature.
   * The pop-up should closing after a successful export.
   * Export by double clicking on available fields. In the export pop-up, the 
user should be able to transfer a field from "available fields" to field to 
export by double clicking also add the drag and drop functionality to add field 
in export list, 
   * Top fields of o2m  mustn't be selectable.these fields become gray color 
(read only) and the user can select only their sub fields.




-- 
https://code.launchpad.net/~openerp-dev/openerp-web/export-import-ysa/+merge/68838
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openerp-web/export-import-ysa.
=== modified file 'addons/base/controllers/main.py'
--- addons/base/controllers/main.py	2011-07-18 14:29:23 +0000
+++ addons/base/controllers/main.py	2011-07-22 13:28:35 +0000
@@ -10,6 +10,8 @@
 import openerpweb.nonliterals
 
 import cherrypy
+import csv
+import xml.dom.minidom
 
 # Should move to openerpweb.Xml2Json
 class Xml2Json:
@@ -179,7 +181,7 @@
         context, domain = eval_context_and_domain(req.session,
                                                   openerpweb.nonliterals.CompoundContext(*(contexts or [])),
                                                   openerpweb.nonliterals.CompoundDomain(*(domains or [])))
-        
+
         group_by_sequence = []
         for candidate in (group_by_seq or []):
             ctx = req.session.eval_context(candidate, context)
@@ -190,7 +192,7 @@
                 group_by_sequence.append(group_by)
             else:
                 group_by_sequence.extend(group_by)
-        
+
         return {
             'context': context,
             'domain': domain,
@@ -203,7 +205,7 @@
         This method store an action object in the session object and returns an integer
         identifying that action. The method get_session_action() can be used to get
         back the action.
-        
+
         :param the_action: The action to save in the session.
         :type the_action: anything
         :return: A key identifying the saved action.
@@ -226,7 +228,7 @@
         """
         Gets back a previously saved action. This method can return None if the action
         was saved since too much time (this case should be handled in a smart way).
-        
+
         :param key: The key given by save_session_action()
         :type key: integer
         :return: The saved action or None.
@@ -361,7 +363,7 @@
         menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
         menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']}
         menu_items.append(menu_root)
-        
+
         # make a tree using parent_id
         menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
         for menu_item in menu_items:
@@ -468,7 +470,7 @@
         record_map = dict((record['id'], record) for record in records)
 
         return [record_map[id] for id in ids if record_map.get(id)]
-    
+
     @openerpweb.jsonrequest
     def load(self, req, model, id, fields):
         m = req.session.model(model)
@@ -631,7 +633,7 @@
         except ValueError:
             # not a literal
             return openerpweb.nonliterals.Domain(session, domain)
-        
+
     def parse_context(self, context, session):
         """ Parses an arbitrary string containing a context, transforms it
         to either a literal context or a :class:`openerpweb.nonliterals.Context`
@@ -832,4 +834,259 @@
         return clean_action(req.session.model('ir.actions.server').run(
             [action_id], req.session.eval_context(req.context)), req.session)
 
-#
+def export_csv(fields, result):
+    import StringIO
+    fp = StringIO.StringIO()
+    writer = csv.writer(fp, quoting=csv.QUOTE_ALL)
+
+    writer.writerow(fields)
+
+    for data in result:
+        row = []
+        for d in data:
+            if isinstance(d, basestring):
+                d = d.replace('\n',' ').replace('\t',' ')
+                try:
+                    d = d.encode('utf-8')
+                except:
+                    pass
+            if d is False: d = None
+            row.append(d)
+        writer.writerow(row)
+
+    fp.seek(0)
+    data = fp.read()
+    fp.close()
+    return data
+
+def export_xls(fieldnames, table):
+    import StringIO
+    try:
+        import xlwt
+    except ImportError:
+        common.error(_('Import Error.'), _('Please install xlwt library to export to MS Excel.'))
+
+    workbook = xlwt.Workbook()
+    worksheet = workbook.add_sheet('Sheet 1')
+
+    for i, fieldname in enumerate(fieldnames):
+        worksheet.write(0, i, str(fieldname))
+        worksheet.col(i).width = 8000 # around 220 pixels
+
+    style = xlwt.easyxf('align: wrap yes')
+
+    for row_index, row in enumerate(table):
+        for cell_index, cell_value in enumerate(row):
+            cell_value = str(cell_value)
+            cell_value = re.sub("\r", " ", cell_value)
+            worksheet.write(row_index + 1, cell_index, cell_value, style)
+
+
+    fp = StringIO.StringIO()
+    workbook.save(fp)
+    fp.seek(0)
+    data = fp.read()
+    fp.close()
+    #return data.decode('ISO-8859-1')
+    return unicode(data, 'utf-8', 'replace')
+
+def node_attributes(node):
+    attrs = node.attributes
+
+    if not attrs:
+        return {}
+    # localName can be a unicode string, we're using attribute names as
+    # **kwargs keys and python-level kwargs don't take unicode keys kindly
+    # (they blow up) so we need to ensure all keys are ``str``
+    return dict([(str(attrs.item(i).localName), attrs.item(i).nodeValue)
+                 for i in range(attrs.length)])
+
+def _fields_get_all(req, model, views, context=None):
+
+    if context is None:
+        context = {}
+
+    def parse(root, fields):
+        for node in root.childNodes:
+            if node.nodeName in ('form', 'notebook', 'page', 'group', 'tree', 'hpaned', 'vpaned'):
+                parse(node, fields)
+            elif node.nodeName=='field':
+                attrs = node_attributes(node)
+                name = attrs['name']
+                fields[name].update(attrs)
+        return fields
+
+    def get_view_fields(view):
+        return parse(
+            xml.dom.minidom.parseString(view['arch'].encode('utf-8')).documentElement,
+            view['fields'])
+
+    model_obj = req.session.model(model)
+    tree_view = model_obj.fields_view_get(views.get('tree', False), 'tree', context)
+    form_view = model_obj.fields_view_get(views.get('form', False), 'form', context)
+    fields = {}
+    fields.update(get_view_fields(tree_view))
+    fields.update(get_view_fields(form_view))
+    return fields
+
+
+class Export(View):
+    _cp_path = "/base/export"
+
+    def fields_get(self, req, model):
+        Model = req.session.model(model)
+        fields = Model.fields_get(False, req.session.eval_context(req.context))
+        return fields
+
+    @openerpweb.jsonrequest
+    def get_fields(self, req, model, prefix='', name= '', field_parent=None, params={}):
+        import_compat = params.get("import_compat", False)
+        views_id = params.get("views_id", {})
+
+        fields = _fields_get_all(req, model, views=views_id, context=req.session.eval_context(req.context))
+        field_parent_type = params.get("parent_field_type",False)
+
+        if import_compat and field_parent_type and field_parent_type == "many2one":
+            fields = {}
+
+        fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
+        records = []
+        fields_order = fields.keys()
+        fields_order.sort(lambda x,y: -cmp(fields[x].get('string', ''), fields[y].get('string', '')))
+
+        for index, field in enumerate(fields_order):
+            value = fields[field]
+            record = {}
+            if import_compat and value.get('readonly', False):
+                ok = False
+                for sl in value.get('states', {}).values():
+                    for s in sl:
+                        ok = ok or (s==['readonly',False])
+                if not ok: continue
+
+            id = prefix + (prefix and '/'or '') + field
+            nm = name + (name and '/' or '') + value['string']
+            record.update(id=id, string= nm, action='javascript: void(0)',
+                          target=None, icon=None, children=[], field_type=value.get('type',False), required=value.get('required', False))
+            records.append(record)
+
+            if len(nm.split('/')) < 3 and value.get('relation', False):
+                if import_compat:
+                    ref = value.pop('relation')
+                    cfields = self.fields_get(req, ref)
+                    if (value['type'] == 'many2many'):
+                        record['children'] = []
+                        record['params'] = {'model': ref, 'prefix': id, 'name': nm}
+
+                    elif value['type'] == 'many2one':
+                        record['children'] = [id + '/id', id + '/.id']
+                        record['params'] = {'model': ref, 'prefix': id, 'name': nm}
+
+                    else:
+                        cfields_order = cfields.keys()
+                        cfields_order.sort(lambda x,y: -cmp(cfields[x].get('string', ''), cfields[y].get('string', '')))
+                        children = []
+                        for j, fld in enumerate(cfields_order):
+                            cid = id + '/' + fld
+                            cid = cid.replace(' ', '_')
+                            children.append(cid)
+                        record['children'] = children or []
+                        record['params'] = {'model': ref, 'prefix': id, 'name': nm}
+                else:
+                    ref = value.pop('relation')
+                    cfields = self.fields_get(req, ref)
+                    cfields_order = cfields.keys()
+                    cfields_order.sort(lambda x,y: -cmp(cfields[x].get('string', ''), cfields[y].get('string', '')))
+                    children = []
+                    for j, fld in enumerate(cfields_order):
+                        cid = id + '/' + fld
+                        cid = cid.replace(' ', '_')
+                        children.append(cid)
+                    record['children'] = children or []
+                    record['params'] = {'model': ref, 'prefix': id, 'name': nm}
+
+        records.reverse()
+        return records
+
+    @openerpweb.jsonrequest
+    def save_export_lists(self, req, name, model, field_list):
+        result = {'resource':model, 'name':name, 'export_fields': []}
+        for field in field_list:
+            result['export_fields'].append((0, 0, {'name': field}))
+        return req.session.model("ir.exports").create(result, req.session.eval_context(req.context))
+
+    @openerpweb.jsonrequest
+    def exist_export_lists(self, req, model):
+        export_model = req.session.model("ir.exports")
+        return export_model.read(export_model.search([('resource', '=', model)]), ['name'])
+
+    @openerpweb.jsonrequest
+    def delete_export(self, req, export_id):
+        req.session.model("ir.exports").unlink(export_id, req.session.eval_context(req.context))
+        return True
+
+    @openerpweb.jsonrequest
+    def namelist(self,req,  model, export_id):
+
+        result = self.get_data(req, model, req.session.eval_context(req.context))
+        ir_export_obj = req.session.model("ir.exports")
+        ir_export_line_obj = req.session.model("ir.exports.line")
+
+        field = ir_export_obj.read(export_id)
+        fields = ir_export_line_obj.read(field['export_fields'])
+
+        name_list = {}
+        [name_list.update({field['name']: result.get(field['name'])}) for field in fields]
+        return name_list
+
+    def get_data(self, req, model, context=None):
+        ids = []
+        context = context or {}
+        fields_data = {}
+        proxy = req.session.model(model)
+        fields = self.fields_get(req, model)
+        if not ids:
+            f1 = proxy.fields_view_get(False, 'tree', context)['fields']
+            f2 = proxy.fields_view_get(False, 'form', context)['fields']
+
+            fields = dict(f1)
+            fields.update(f2)
+            fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
+
+        def rec(fields):
+            _fields = {'id': 'ID' , '.id': 'Database ID' }
+            def model_populate(fields, prefix_node='', prefix=None, prefix_value='', level=2):
+                fields_order = fields.keys()
+                fields_order.sort(lambda x,y: -cmp(fields[x].get('string', ''), fields[y].get('string', '')))
+
+                for field in fields_order:
+                    fields_data[prefix_node+field] = fields[field]
+                    if prefix_node:
+                        fields_data[prefix_node + field]['string'] = '%s%s' % (prefix_value, fields_data[prefix_node + field]['string'])
+                    st_name = fields[field]['string'] or field
+                    _fields[prefix_node+field] = st_name
+                    if fields[field].get('relation', False) and level>0:
+                        fields2 = self.fields_get(req,  fields[field]['relation'])
+                        fields2.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
+                        model_populate(fields2, prefix_node+field+'/', None, st_name+'/', level-1)
+            model_populate(fields)
+            return _fields
+        return rec(fields)
+
+    @openerpweb.jsonrequest
+    def export_data(self, req, model, fields, ids, domain, import_compat=False, export_format="csv", context=None):
+        context = req.session.eval_context(req.context)
+        modle_obj = req.session.model(model)
+        ids = ids or modle_obj.search(domain, context=context)
+
+        field = fields.keys()
+        result = modle_obj.export_data(ids, field , context).get('datas',[])
+
+        if not import_compat:
+            field = [val.strip() for val in fields.values()]
+
+        if export_format == 'xls':
+            return export_xls(field, result)
+        else:
+            return export_csv(field, result)
+

=== modified file 'addons/base/static/src/base.html'
--- addons/base/static/src/base.html	2011-07-19 10:27:07 +0000
+++ addons/base/static/src/base.html	2011-07-22 13:28:35 +0000
@@ -27,6 +27,7 @@
     <script type="text/javascript" src="/base/static/src/js/dates.js"></script>
     <script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
     <script type="text/javascript" src="/base/static/src/js/data.js"></script>
+    <script type="text/javascript" src="/base/static/src/js/export.js"></script>
     <script type="text/javascript" src="/base/static/src/js/views.js"></script>
     <script type="text/javascript" src="/base/static/src/js/form.js"></script>
     <script type="text/javascript" src="/base/static/src/js/list.js"></script>
@@ -39,6 +40,7 @@
     <link rel="stylesheet" type="text/css" href="/base/static/lib/jquery.superfish/css/superfish.css" media="screen">
 
     <link rel="stylesheet" href="/base/static/src/css/base.css" type="text/css"/>
+    <link rel="stylesheet" href="/base/static/src/css/export.css" type="text/css"/>
     <!--[if lte IE 7]>
     <link rel="stylesheet" href="/base/static/src/css/base-ie7.css" type="text/css"/>
     <![endif]-->

=== added file 'addons/base/static/src/css/export.css'
--- addons/base/static/src/css/export.css	1970-01-01 00:00:00 +0000
+++ addons/base/static/src/css/export.css	2011-07-22 13:28:35 +0000
@@ -0,0 +1,84 @@
+.row tr{
+    background-color: #FFFFFF;
+    font-size: 0.8em;
+    height: 22px;
+}
+
+tr.ui-selected td {
+    background-color: #CCCCCC;
+}
+
+.requiredfield {
+    background-color: #D2D2FF;
+}
+
+.readonlyfield{
+    background-color: DarkGray;
+}
+
+.row:hover{
+    background-color: #F3F3F3;
+}
+
+.fields-selector-export {
+    width: 100%;
+    height: 400px;
+}
+
+.fields-selector-left {
+    width: 50%;
+}
+
+div#left_field_panel {
+    overflow: scroll;
+    width: 100%;
+    height: 400px;
+    border: solid #999999 1px;
+}
+
+.fields-selector-center {
+    width: 102px;
+}
+
+.fields-selector-right {
+    width: 45%;
+    height: 400px;
+}
+
+.fields-selector-export select{
+    width: 100%;
+    height: 100%;
+}
+
+.tree_header{
+    border: 0.5px solid #E3E3E3;
+    text-align: left;
+    white-space: nowrap;
+    padding: 4px 5px;
+    background: url(/base/static/src/img/header.gif);
+}
+
+
+table.tree-grid{
+    border: 1px solid #E3E3E3;
+    text-align: left;
+    white-space: nowrap;
+    background-color:#E3E3E3;
+    border-collapse: collapse;
+    width: 100%;
+}
+
+table.tree-grid a:hover {
+    color: blue;
+    border: none;
+}
+
+table.tree-grid a {
+    color: #5F5C5C;
+    border: none;
+}
+
+.button-export {
+	border: 1px solid #006;
+	background-color: #F3F3F3;
+}

=== added file 'addons/base/static/src/img/collapse.gif'
Binary files addons/base/static/src/img/collapse.gif	1970-01-01 00:00:00 +0000 and addons/base/static/src/img/collapse.gif	2011-07-22 13:28:35 +0000 differ
=== added file 'addons/base/static/src/img/expand.gif'
Binary files addons/base/static/src/img/expand.gif	1970-01-01 00:00:00 +0000 and addons/base/static/src/img/expand.gif	2011-07-22 13:28:35 +0000 differ
=== added file 'addons/base/static/src/img/header.gif'
Binary files addons/base/static/src/img/header.gif	1970-01-01 00:00:00 +0000 and addons/base/static/src/img/header.gif	2011-07-22 13:28:35 +0000 differ
=== modified file 'addons/base/static/src/js/base.js'
--- addons/base/static/src/js/base.js	2011-07-19 10:27:07 +0000
+++ addons/base/static/src/js/base.js	2011-07-22 13:28:35 +0000
@@ -87,6 +87,9 @@
     if (openerp.base.view_tree) {
         openerp.base.view_tree(instance);
     }
+    if (openerp.base.export) {
+        openerp.base.export(instance);
+    }
 };
 
 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:

=== modified file 'addons/base/static/src/js/chrome.js'
--- addons/base/static/src/js/chrome.js	2011-07-22 11:21:08 +0000
+++ addons/base/static/src/js/chrome.js	2011-07-22 13:28:35 +0000
@@ -137,8 +137,17 @@
 });
 
 /**
+<<<<<<< TREE
  * OpenERP session aware controller
  * a controller takes an already existing dom element and manage it
+=======
+ * Generates an inherited class that replaces all the methods by null methods (methods
+ * that does nothing and always return undefined).
+ *
+ * @param {Class} claz
+ * @param {dict} add Additional functions to override.
+ * @return {Class}
+>>>>>>> MERGE-SOURCE
  */
 openerp.base.Controller = openerp.base.Controller.extend( /** @lends openerp.base.Controller# */{
     init: function(parent, element_id) {
@@ -496,6 +505,7 @@
 openerp.base.Notification =  openerp.base.Controller.extend({
     init: function(parent, element_id) {
         this._super(parent, element_id);
+<<<<<<< TREE
         this.$element.notify({
             speed: 500,
             expires: 1500
@@ -512,6 +522,99 @@
             title: title,
             text: text
         });
+=======
+        if(this.parent && this.parent.session) {
+            this.session = this.parent.session;
+        }
+    },
+    /**
+     * Performs a JSON-RPC call
+     *
+     * @param {String} url endpoint url
+     * @param {Object} data RPC parameters
+     * @param {Function} success RPC call success callback
+     * @param {Function} error RPC call error callback
+     * @returns {jQuery.Deferred} deferred object for the RPC call
+     */
+    rpc: function(url, data, success, error) {
+        return this.session.rpc(url, data, success, error);
+    },
+    do_action: function(action, on_finished) {
+        return this.parent.do_action(action, on_finished);
+    }
+});
+
+/**
+ * OpenERP session aware widget
+ * A widget is a controller that doesnt take an element_id
+ * it render its own html render() that you should insert into the dom
+ * and bind it a start()
+ */
+openerp.base.BaseWidget = openerp.base.Controller.extend({
+    /**
+     * The name of the QWeb template that will be used for rendering. Must be
+     * redefined in subclasses or the render() method can not be used.
+     *
+     * @type string
+     */
+    template: null,
+    /**
+     * The prefix used to generate an id automatically. Should be redefined in
+     * subclasses. If it is not defined, a default identifier will be used.
+     *
+     * @type string
+     */
+    identifier_prefix: 'generic-identifier',
+    /**
+     * Base class for widgets. Handle rendering (based on a QWeb template),
+     * identifier generation, parenting and destruction of the widget.
+     * Also initialize the identifier.
+     *
+     * @constructs
+     * @params {openerp.base.search.BaseWidget} parent The parent widget.
+     */
+    init: function (parent) {
+        this._super(parent);
+        this.make_id(this.identifier_prefix);
+    },
+    /**
+     * Sets and returns a globally unique identifier for the widget.
+     *
+     * If a prefix is appended, the identifier will be appended to it.
+     *
+     * @params sections prefix sections, empty/falsy sections will be removed
+     */
+    make_id: function () {
+        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
+        return this.element_id;
+    },
+    /**
+     * "Starts" the widgets. Called at the end of the rendering, this allows
+     * to get a jQuery object referring to the DOM ($element attribute).
+     */
+    start: function () {
+        this._super();
+        var tmp = document.getElementById(this.element_id);
+        this.$element = tmp ? $(tmp) : null;
+    },
+    /**
+     * "Stops" the widgets. Called when the view destroys itself, this
+     * lets the widgets clean up after themselves.
+     */
+    stop: function () {
+        if(this.$element != null) {
+            this.$element.remove();
+        }
+    },
+    /**
+     * Render the widget. This.template must be defined.
+     * The content of the current object is passed as context to the template.
+     *
+     * @param {object} additional Additional context arguments to pass to the template.
+     */
+    render: function (additional) {
+        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
+>>>>>>> MERGE-SOURCE
     }
 });
 

=== added file 'addons/base/static/src/js/export.js'
--- addons/base/static/src/js/export.js	1970-01-01 00:00:00 +0000
+++ addons/base/static/src/js/export.js	2011-07-22 13:28:35 +0000
@@ -0,0 +1,409 @@
+openerp.base.export = function(openerp) {
+openerp.base.Export = openerp.base.Dialog.extend({
+
+    init: function(parent, dataset, views){
+        this._super(parent);
+        this.dataset = dataset
+        this.views = views
+        this.views_id = {};
+        for (var key in this.views) {
+            this.views_id[key] = this.views[key].view_id
+        }
+    },
+
+    start: function() {
+        var self = this
+        self._super(false);
+        self.template = 'ExportTreeView';
+        self.dialog_title = "Export Data "
+        self.open({
+                    modal: true,
+                    width: '55%',
+                    height: 'auto',
+                    position: 'top',
+                    buttons : {
+                        "Close" : function() {
+                            self.close();
+                          },
+                        "Export To File" : function() {
+                            self.on_click_export_data();
+                          }
+                       },
+                    close: function(event, ui){ self.close();}
+                   });
+        this.on_show_exists_export_list();
+        jQuery(this.$dialog).removeClass('ui-dialog-content ui-widget-content');
+        $('#add_field').click(function(){
+            if($("#field-tree-structure tr.ui-selected")){
+                var fld = $("#field-tree-structure tr.ui-selected").find('a');
+                for (var i=0;i<fld.length; i++){
+                    var id = $(fld[i]).attr('id').split("-")[1];
+                    var string = $(fld[i]).attr('string');
+                    self.add_field(id,string);
+                }
+                $("#field-tree-structure tr").removeClass("ui-selected");
+            }
+        });
+        $('#remove_field').click(function(){
+            $("#fields_list option:selected").remove();
+        });
+        $('#remove_all_field').click(function(){
+            $("#fields_list option").remove();
+        });
+        $('#export_new_list').click(function(){
+            self.on_show_save_list();
+        });
+        import_comp = $("#import_compat option:selected").val()
+        var params = {"import_compat":parseInt(import_comp), "views_id": this.views_id}
+        this.rpc("/base/export/get_fields", {"model": this.dataset.model, "params": params}, this.on_show_data);
+
+        $("#import_compat").change(function(){
+            $("#fields_list option").remove();
+            $("#field-tree-structure").remove();
+            import_comp = $("#import_compat option:selected").val();
+            if(import_comp){
+                var params = {"import_compat":parseInt(import_comp), "views_id": this.views_id}
+                self.rpc("/base/export/get_fields", {"model": self.dataset.model, "params": params}, self.on_show_data);
+            }
+        });
+    },
+
+    on_show_exists_export_list: function(){
+        var self = this;
+        if($("#saved_export_list").is(":hidden")){
+            $("#ExistsExportList").show();
+        }
+        else{
+            this.rpc("/base/export/exist_export_lists", {"model": this.dataset.model}, function(export_list){
+                if(export_list.length){
+                    $("#ExistsExportList").append(QWeb.render('Exists.ExportList', {'existing_exports':export_list}));
+                    $("#saved_export_list").change(function(){
+                        $("#fields_list option").remove();
+                        export_id = $("#saved_export_list option:selected").val();
+                        if (export_id){
+                            self.rpc("/base/export/namelist", {"model": self.dataset.model, export_id: parseInt(export_id)}, self.do_load_export_field);
+                        }
+                    });
+                    $('#delete_export_list').click(function(){
+                        select_exp = $("#saved_export_list option:selected")
+                        if (select_exp.val()){
+                            self.rpc("/base/export/delete_export", {"export_id": parseInt(select_exp.val())}, {});
+                            select_exp.remove();
+                            if($("#saved_export_list option").length <= 1){
+                                $("#ExistsExportList").hide();
+                            }
+                        }
+                    });
+                }
+            });
+        }
+    },
+
+    do_load_export_field: function(field_list){
+        var export_node = $("#fields_list");
+        for (var key in field_list) {
+            export_node.append(new Option(field_list[key], key));
+        }
+    },
+
+    on_show_save_list: function(){
+        var self = this;
+        var current_node = $("#savenewlist");
+        if(!(current_node.find("label")).length){
+            current_node.append(QWeb.render('ExportNewList'));
+            current_node.find("#add_export_list").click(function(){
+                var value = current_node.find("#savelist_name").val();
+                if (value){
+                    self.do_save_export_list(value);
+                }
+                else{
+                    alert("Pleae Enter Save Field List Name");
+                }
+            });
+        }
+        else{
+            if (current_node.is(':hidden')){
+                current_node.show();
+            }
+            else{
+               current_node.hide();
+            }
+        }
+    },
+
+    do_save_export_list: function(value){
+        var self = this;
+        var export_field = self.get_fields()
+        if(export_field.length){
+            self.rpc("/base/export/save_export_lists", {"model": self.dataset.model, "name":value, "field_list":export_field}, function(exp_id){
+                if(exp_id){
+                    if($("#saved_export_list").length > 0){
+                        $("#saved_export_list").append( new Option(value, exp_id));
+                    }
+                    else{
+                        self.on_show_exists_export_list();
+                    }
+                    if($("#saved_export_list").is(":hidden")){
+                        self.on_show_exists_export_list();
+                    }
+                }
+            });
+            self.on_show_save_list()
+            $("#fields_list option").remove();
+        }
+    },
+
+    on_click: function(id, result) {
+        var self = this
+        self.field_id = id.split("-")[1];
+        var model = ''
+        var prefix = ''
+        var name = ''
+        var is_loaded = 0;
+        _.each(result, function(record) {
+            if(record['id'] == self.field_id && (record['children']).length >= 1){
+                model = record['params']['model']
+                prefix = record['params']['prefix']
+                name = record['params']['name']
+                $(record['children']).each (function(e, childid) {
+                    if ($("tr[id='treerow-" + childid +"']").length > 0) {
+                        if ($("tr[id='treerow-" + childid +"']").is(':hidden')) {
+                            is_loaded = -1;
+                        } else {
+                            is_loaded++;
+                        }
+                    }
+                });
+                if (is_loaded == 0) {
+                    if ($("tr[id='treerow-" + self.field_id +"']").find('img').attr('src') == '/base/static/src/img/expand.gif') {
+                        if (model){
+                            import_comp = $("#import_compat option:selected").val()
+                            var params = {"import_compat":parseInt(import_comp), "views_id": this.views_id, "parent_field_type" : record['field_type']}
+                            self.rpc("/base/export/get_fields", {"model": model, "prefix": prefix, "name": name,  "field_parent" : self.field_id, "params":params}, function (results) {
+                                self.on_show_data(results);
+                            });
+                        }
+                    }
+                } else if (is_loaded > 0) {
+                    self.showcontent(self.field_id, true);
+                } else {
+                    self.showcontent(self.field_id, false);
+                }
+            }
+
+        });
+    },
+
+    on_show_data: function(result) {
+        var self = this;
+        var current_tr = $("tr[id='treerow-" + self.field_id + "']");
+        if (current_tr.length >= 1){
+            current_tr.find('img').attr('src','/base/static/src/img/collapse.gif');
+            current_tr.after(QWeb.render('ExportTreeView-Secondary.children', {'fields': result}));
+        }
+        else{
+            $('#left_field_panel').append(QWeb.render('ExportTreeView-Secondary',  {'fields': result}));
+        }
+        _.each(result, function(record) {
+            if(record.field_type == "one2many"){
+                var o2m_fld = $("tr[id^='treerow-" + record.id + "']").find('#tree-column');
+                o2m_fld.addClass("readonlyfield");
+            }
+            if ((record.required == true) || record.required == "True"){
+                var required_fld = $("tr[id^='treerow-" + record.id + "']").find('#tree-column');
+                required_fld.addClass("requiredfield");
+            }
+            $("img[id ^='parentimg-" + record.id +"']").click(function(){
+                self.on_click(this.id, result);
+            });
+
+            $("tr[id^='treerow-" + record.id + "']").click(function(e){
+                if (e.shiftKey == true){
+                    var frst_click,scnd_click = '';
+                    if (self.row_index == 0){
+                        self.row_index = this.rowIndex;
+                        frst_click = $("tr[id^='treerow-']")[self.row_index-1];
+                        $(frst_click).addClass("ui-selected");
+                    }else{
+                        if (this.rowIndex >=self.row_index){
+                            for (i = (self.row_index-1); i < this.rowIndex; i++) {
+                                scnd_click = $("tr[id^='treerow-']")[i];
+                                if(!$(scnd_click).find('#tree-column').hasClass("readonlyfield")){
+                                    $(scnd_click).addClass("ui-selected");
+                                }
+                            }
+                        }else{
+                            for (i = (self.row_index-1); i >= (this.rowIndex-1); i--) {
+                                scnd_click = $("tr[id^='treerow-']")[i];
+                                if(!$(scnd_click).find('#tree-column').hasClass("readonlyfield")){
+                                    $(scnd_click).addClass("ui-selected");
+                                }
+                            }
+                        }
+                    }
+                }
+                self.row_index = this.rowIndex;
+
+                $("tr[id^='treerow-" + record.id + "']").keyup(function (e) {
+                        self.row_index = 0;
+                });
+                var o2m_selection = $("tr[id^='treerow-" + record.id + "']").find('#tree-column');
+                if ($(o2m_selection).hasClass("readonlyfield")){
+                    return false;
+                }
+                var selected = $("tr.ui-selected");
+                if ($(this).hasClass("ui-selected") && (e.ctrlKey == true)){
+                    $(this).find('a').blur();
+                    $(this).removeClass("ui-selected");
+                }else if($(this).hasClass("ui-selected") && (e.ctrlKey == false) && (e.shiftKey == false)){
+                    selected.find('a').blur();
+                    selected.removeClass("ui-selected");
+                    $(this).find('a').focus();
+                    $(this).addClass("ui-selected");
+                }else if(!$(this).hasClass("ui-selected") && (e.ctrlKey == false) && (e.shiftKey == false)){
+                    selected.find('a').blur();
+                    selected.removeClass("ui-selected");
+                    $(this).find('a').focus();
+                    $(this).addClass("ui-selected");
+                }else if(!$(this).hasClass("ui-selected") && (e.ctrlKey == true)){
+                    $(this).find('a').focus();
+                    $(this).addClass("ui-selected");
+                }
+                return false;
+            });
+
+            $("tr[id^='treerow-" + record.id + "']").keydown(function (e) {
+                var keyCode = e.keyCode || e.which;
+                arrow = {left: 37, up: 38, right: 39, down: 40 };
+                switch (keyCode) {
+                    case arrow.left:
+                        if( jQuery(this).find('img').attr('src') == '/base/static/src/img/collapse.gif'){
+                            self.on_click(this.id, result);
+                        }
+                    break;
+                    case arrow.up:
+                        var elem = this;
+                        $(elem).removeClass("ui-selected");
+                        while($(elem).prev().is(":visible") == false){
+                            elem = $(elem).prev();
+                        }
+                        if(!$(elem).prev().find('#tree-column').hasClass("readonlyfield")){
+                            $(elem).prev().addClass("ui-selected");
+                        }
+                        $(elem).prev().find('a').focus();
+                    break;
+                    case arrow.right:
+                        if( jQuery(this).find('img').attr('src') == '/base/static/src/img/expand.gif'){
+                            self.on_click(this.id, result);
+                        }
+                    break;
+                    case arrow.down:
+                        var elem = this;
+                        $(elem).removeClass("ui-selected");
+                        while($(elem).next().is(":visible") == false){
+                            elem = $(elem).next();
+                        }
+                        if(!$(elem).next().find('#tree-column').hasClass("readonlyfield")){
+                            $(elem).next().addClass("ui-selected");
+                        }
+                        $(elem).next().find('a').focus();
+                    break;
+                }
+            });
+            $("tr[id^='treerow-" + record.id + "']").dblclick(function (e) {
+                var o2m_selection = $("tr[id^='treerow-" + record.id + "']").find('#tree-column');
+                if (! $(o2m_selection).hasClass("readonlyfield")){
+                    var field_id =  $(this).find("a").attr("id");
+                    if(field_id){
+                       self.add_field(field_id.split('-')[1], $(this).find("a").attr("string"))
+                   }
+                }
+            });
+        });
+        $('#fields_list').mouseover(function(event){
+            if(event.relatedTarget){
+                if (event.relatedTarget.attributes['id'] && event.relatedTarget.attributes['string']){
+                    field_id = event.relatedTarget.attributes["id"]["value"]
+                    if (field_id && field_id.split("-")[0] == 'export'){
+                        if(!$("tr[id^='treerow-" + field_id.split("-")[1] + "']").find('#tree-column').hasClass("readonlyfield")){
+                            self.add_field(field_id.split("-")[1], event.relatedTarget.attributes["string"]["value"]);
+                        }
+                    }
+                }
+            }
+        });
+    },
+
+    // show & hide the contents
+    showcontent: function (id, flag) {
+        var first_child = $("tr[id='treerow-" + id + "']").find('img')
+        if (flag) {
+            first_child.attr('src', '/base/static/src/img/expand.gif');
+        }
+        else {
+            first_child.attr('src', '/base/static/src/img/collapse.gif');
+        }
+        var child_field = $("tr[id^='treerow-" + id +"/']")
+        var child_len = (id.split("/")).length + 1
+        for (var i = 0; i < child_field.length; i++) {
+            if (flag) {
+                $(child_field[i]).hide();
+            }
+            else {
+                if(child_len ==  (child_field[i].id.split("/")).length){
+                    if( jQuery(child_field[i]).find('img').attr('src') == '/base/static/src/img/collapse.gif'){
+                        jQuery(child_field[i]).find('img').attr('src', '/base/static/src/img/expand.gif')
+                    }
+                    $(child_field[i]).show();
+                }
+            }
+        }
+    },
+
+    add_field: function(field_id, string) {
+        var field_list = $('#fields_list')
+        if ( $("#fields_list option[value='" + field_id + "']") && !$("#fields_list option[value='" + field_id + "']").length){
+            field_list.append( new Option(string, field_id));
+        }
+    },
+
+    get_fields: function (){
+        var export_field = [];
+        $("#fields_list option").each(function(){
+            export_field.push(jQuery(this).val());
+        });
+        if (! export_field.length){
+            alert('Please select fields to save export list...');
+        }
+        return export_field;
+    },
+    on_click_export_data: function(){
+        var self = this;
+        var export_field = {};
+        var flag = true;
+        $("#fields_list option").each(function(){
+            export_field[jQuery(this).val()] = jQuery(this).text();
+            flag = false;
+        });
+        if (flag){
+            alert('Please select fields to export...');
+            return;
+        }
+
+        import_comp = $("#import_compat option:selected").val()
+        export_format = $("#export_format").val()
+
+        self.rpc("/base/export/export_data", {"model": self.dataset.model, "fields":export_field, 'ids': self.dataset.ids, 'domain': self.dataset.domain, "import_compat":parseInt(import_comp), "export_format" :export_format}, function(data){
+            window.location="data:text/csv/excel;charset=utf8," + data
+            self.close();
+        });
+    },
+
+    close: function() {
+        jQuery(this.$dialog).remove();
+        this._super();
+    },
+
+});
+
+};

=== modified file 'addons/base/static/src/js/views.js'
--- addons/base/static/src/js/views.js	2011-07-22 12:15:42 +0000
+++ addons/base/static/src/js/views.js	2011-07-22 13:28:35 +0000
@@ -205,11 +205,24 @@
                 }
             }
         }
+        if(this.flags && this.flags.sidebar) {
+            if(this.$element.find('#exportview')){
+                this.$element.find('#exportview').remove()
+            }
+            if(this.active_view == 'list' || this.active_view == 'form') {
+                this.views[this.active_view].controller.$element.after(QWeb.render('ExportView'))
+                this.$element.find('#exportview').click(function(ev) {
+                    var export_view = new openerp.base.Export(self, self.dataset, self.views);
+                    export_view.start(false);
+                    ev.preventDefault();
+                });
+            }
+        }
         return view_promise;
     },
     /**
      * Event launched when a controller has been inited.
-     * 
+     *
      * @param {String} view_type type of view
      * @param {String} view the inited controller
      */
@@ -417,6 +430,7 @@
 
 openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar);
 
+/*
 openerp.base.Export = openerp.base.Dialog.extend({
     dialog_title: "Export",
     template: 'ExportDialog',
@@ -435,7 +449,7 @@
         this.$element.dialog("close");
     }
 });
-
+*/
 openerp.base.View = openerp.base.Controller.extend({
     /**
      * Fetches and executes the action identified by ``action_data``.
@@ -492,7 +506,7 @@
      * Directly set a view to use instead of calling fields_view_get. This method must
      * be called before start(). When an embedded view is set, underlying implementations
      * of openerp.base.View must use the provided view instead of any other one.
-     * 
+     *
      * @param embedded_view A view.
      */
     set_embedded_view: function(embedded_view) {

=== modified file 'addons/base/static/src/xml/base.xml'
--- addons/base/static/src/xml/base.xml	2011-07-20 11:23:42 +0000
+++ addons/base/static/src/xml/base.xml	2011-07-22 13:28:35 +0000
@@ -103,7 +103,7 @@
     <div class="oe_login_right_pane">
         <p>We think that daily job activities can be more intuitive, efficient, automated, .. and even fun.</p>
         <h3>OpenERP's vision to be:</h3>
-        
+
         <table cellpadding="0" cellspacing="0" width="100%" style="border:none;">
             <tbody>
             <tr>
@@ -135,7 +135,7 @@
             </tr>
             </tbody>
         </table>
-        
+
     </div>
 </t>
 <t t-name="Header">
@@ -311,7 +311,7 @@
     t-att-data-index="row_index">
     <t t-foreach="columns" t-as="column">
         <td t-if="column.meta">
-            
+
         </td>
     </t>
     <th t-if="options.selectable" class="oe-record-selector" width="1">
@@ -786,7 +786,7 @@
             <option value="all">All the following conditions must match</option>
             <option value="none">None of the following conditions must match</option>
         </select>
-        <a class="searchview_extended_delete_group" 
+        <a class="searchview_extended_delete_group"
                 href="javascript:void(0)"><span></span></a>
         <div class="searchview_extended_propositions_list">
         </div>
@@ -932,4 +932,145 @@
             .unwrap();
     </t>
 </t>
+
+<t t-name="ExportView">
+    <a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
+</t>
+
+<t t-name="ExportTreeView">
+    <table class="view" style="background-color: #F3F3F3;">
+        <tr>
+            <td align="left">
+                This wizard will export all data that matches the current search criteria to a CSV file.
+                You can export all data or only the fields that can be reimported after modification.
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <table>
+                    <tr>
+                        <td class="label"><label>Export Type:</label></td>
+                        <td>
+                            <select id="import_compat" name="import_compat">
+                                <option value="1">Import Compatible Export</option>
+                                <option value="0">Export all Data</option>
+                            </select>
+                        </td>
+                        <td class="label"><label>Export Format</label></td>
+                        <td>
+                            <select id="export_format" name="export_format">
+                                <option value="csv">CSV</option>
+                                <option value="xls">Excel</option>
+                            </select>
+                        </td>
+
+                    </tr>
+                </table>
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <table class="fields-selector-export">
+                    <tr>
+                        <th class="oe_view_title" valign="bottom">Available fields</th>
+                        <th class="oe_view_title"></th>
+                        <th class="oe_view_title">Fields to export
+                        <a style="color: blue; text-decoration: none;" href="#" id="export_new_list">Save fields list</a>
+                        <div id="savenewlist"></div>
+                        <div id="ExistsExportList"></div>
+                        </th>
+                    </tr>
+                    <tr>
+                        <td class="fields-selector-left">
+                            <div id="left_field_panel">
+                            </div>
+                        </td>
+                        <td>
+                            <table class="fields-selector-center">
+                                <tr>
+                                    <td align="center">
+                                        <button id="add_field" class="button-export">Add</button>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td align="center">
+                                        <button id="remove_field" class="button-export">Remove</button>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td align="center">
+                                        <button id="remove_all_field" class="button-export">Remove All</button>
+                                    </td>
+                                </tr>
+                            </table>
+                        </td>
+                        <td class="fields-selector-right">
+                            <select name="fields_list" id="fields_list" multiple="multiple"></select>
+                        </td>
+                    </tr>
+                </table>
+            </td>
+        </tr>
+    </table>
+</t>
+
+<t t-name="ExportTreeView-Secondary">
+    <table id="field-tree-structure" class="fields-selector-export" cellspacing="0" cellpadding="0">
+        <tr><th class="tree_header"> Name </th></tr>
+        <t t-call="ExportTreeView-Secondary.children"/>
+    </table>
+</t>
+<t t-name="ExportTreeView-Secondary.children">
+    <t t-foreach="fields" t-as="field" >
+        <tr t-att-id="'treerow-' + field.id" class="row">
+            <td>
+                <table class="tree-grid" border="0">
+                    <tr class="row">
+                        <t t-foreach="(field.id).split('/')" t-as="level" >
+                            <t t-if="(field.id).split('/')[0] != level">
+                                <td width="18">&amp;nbsp;</td>
+                            </t>
+                        </t>
+                        <td valign="top" align="left" style="cursor: pointer;" width="18">
+                            <t t-if="(field.children).length >= 1">
+                                <t t-if="(field.id).split('/').length != 3">
+                                    <img t-att-id="'parentimg-' + field.id" src="/base/static/src/img/expand.gif" width="16" height="16" border="0"/>
+                                </t>
+                            </t>
+                        </td>
+                        <td id="tree-column" valign="middle" align="left" style="cursor: pointer;">
+                            <a t-att-id="'export-' + field.id"  t-att-string="field.string" href="javascript: void(0);" style="text-decoration: none;">
+                                <t t-esc="field.string"/>
+                            </a>
+                        </td>
+                    </tr>
+                </table>
+            </td>
+        </tr>
+    </t>
+</t>
+
+<t t-name="ExportNewList">
+    <tr>
+        <th><label>Save as:</label></th>
+        <td><input size="10" type="text" id="savelist_name"/></td>
+        <td><button class="button-export" id="add_export_list">Ok</button></td>
+    </tr>
+</t>
+
+<t t-name="Exists.ExportList">
+    <tr><th align="right"><label >Saved exports:</label></th></tr>
+    <tr align="left">
+        <td>
+            <select id="saved_export_list" style="width: 100%;">
+                <option></option>
+                <t t-foreach="existing_exports" t-as="export">
+                    <option t-att-value="export.id"><t t-esc="export.name"/></option>
+                </t>
+            </select>
+        </td>
+        <td><button class="button-export" id="delete_export_list">Delete</button></td>
+    </tr>
+</t>
 </templates>

_______________________________________________
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

Reply via email to