[MERGE] from upstream
authorFrédéric van der Essen <fva@openerp.com>
Mon, 24 Feb 2014 13:50:38 +0000 (14:50 +0100)
committerFrédéric van der Essen <fva@openerp.com>
Mon, 24 Feb 2014 13:50:38 +0000 (14:50 +0100)
bzr revid: fva@openerp.com-20140224135038-3l6p5ebb5klmw8yr

37 files changed:
addons/point_of_sale/point_of_sale.py
addons/point_of_sale/static/src/js/models.js
addons/web/controllers/main.py
addons/web/static/src/css/Makefile
addons/web/static/src/css/base.css
addons/web/static/src/css/base.sass
addons/web/static/src/js/chrome.js
addons/web/static/src/js/data.js
addons/web/static/src/js/formats.js
addons/web/static/src/js/search.js
addons/web/static/src/js/view_form.js
addons/web/static/src/js/view_list.js
addons/web/static/src/js/views.js
addons/web/static/src/xml/base.xml
addons/web_calendar/static/src/js/web_calendar.js
addons/web_graph/static/src/js/graph_view.js
addons/web_graph/static/src/js/graph_widget.js
addons/web_graph/static/src/xml/web_graph.xml
addons/web_view_editor/static/src/js/view_editor.js
openerp/addons/base/ir/ir_actions.py
openerp/addons/base/ir/ir_actions.xml
openerp/addons/base/ir/ir_model.py
openerp/addons/base/ir/ir_ui_view.py
openerp/addons/base/ir/ir_values.py
openerp/addons/base/res/res_company.py
openerp/addons/base/res/res_company_view.xml
openerp/addons/base/res/res_partner.py
openerp/addons/base/res/res_users.py
openerp/addons/base/res/res_users_view.xml
openerp/addons/base/tests/test_base.py
openerp/addons/base/tests/test_views.py
openerp/osv/fields.py
openerp/osv/orm.py
openerp/service/db.py
openerp/sql_db.py
openerp/tests/test_fields.py
openerp/tools/image.py

index 1f3564e..01e7a49 100644 (file)
@@ -514,13 +514,18 @@ class pos_order(osv.osv):
     _order = "id desc"
 
     def create_from_ui(self, cr, uid, orders, context=None):
-        #_logger.info("orders: %r", orders)
+        
+        # Keep only new orders
+        submitted_references = [o['data']['name'] for o in orders]
+        existing_orders = self.search_read(cr, uid, domain=[('pos_reference', 'in', submitted_references)], fields=['pos_reference'], context=context)
+        existing_references = set([o['pos_reference'] for o in existing_orders])
+        orders_to_save = [o for o in orders if o['data']['name'] not in existing_references]
+
         order_ids = []
-        for tmp_order in orders:
+        for tmp_order in orders_to_save:
             to_invoice = tmp_order['to_invoice']
             order = tmp_order['data']
 
-
             order_id = self.create(cr, uid, {
                 'name': order['name'],
                 'user_id': order['user_id'] or False,
index 6b54c14..90aa5fe 100644 (file)
@@ -421,62 +421,67 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
         // it is therefore important to only call this method from inside a mutex
         // this method returns a deferred indicating wether the sending was successful or not
         // there is a timeout parameter which is set to 2 seconds by default. 
-        _flush_order: function(order_id, options){
-            var self   = this;
-            options = options || {};
-            timeout = typeof options.timeout === 'number' ? options.timeout : 7500;
-
-            this.set('synch',{state:'connecting', pending: this.get('synch').pending});
-
-            var order  = this.db.get_order(order_id);
-            order.to_invoice = options.to_invoice || false;
-
-            if(!order){
-                // flushing a non existing order always fails
-                return (new $.Deferred()).reject();
-            }
-
-            // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice,
-            // then we want to notify the user that we are waiting on something )
-            var rpc = (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{shadow: !options.to_invoice, timeout:timeout});
-
-            rpc.fail(function(unused,event){
-                // prevent an error popup creation by the rpc failure
-                // we want the failure to be silent as we send the orders in the background
-                event.preventDefault();
-                console.error('Failed to send order:',order);
-            });
-
-            rpc.done(function(){
-                self.db.remove_order(order_id);
-                var pending = self.db.get_orders().length;
-                self.set('synch',{state: pending ? 'connecting' : 'connected', pending:pending});
-            });
-
-            return rpc;
+        _flush_order: function( order_id, options) {
+            return this._flush_all_orders([this.db.get_order(order_id)], options);
         },
         
         // attempts to send all the locally stored orders. As with _flush_order, it should only be
         // called from within a mutex. 
         // this method returns a deferred that always succeeds when all orders have been tried to be sent,
         // even if none of them could actually be sent. 
-        _flush_all_orders: function(){
+        _flush_all_orders: function () {
             var self = this;
-            var orders = this.db.get_orders();
-            var tried_all = new $.Deferred();
-
-            function rec_flush(index){
-                if(index < orders.length){
-                    self._flush_order(orders[index].id).always(function(){ 
-                        rec_flush(index+1); 
-                    })
-                }else{
-                    tried_all.resolve();
-                }
+            self.set('synch', {
+                state: 'connecting',
+                pending: self.get('synch').pending
+            });
+            return self._save_to_server(self.db.get_orders()).done(function () {
+                var pending = self.db.get_orders().length;
+                self.set('synch', {
+                    state: pending ? 'connecting' : 'connected',
+                    pending: pending
+                });
+            });
+        },
+
+        // send an array of orders to the server
+        // available options:
+        // - timeout: timeout for the rpc call in ms
+        _save_to_server: function (orders, options) {
+            if (!orders || !orders.length) {
+                var result = $.Deferred();
+                result.resolve();
+                return result;
             }
-            rec_flush(0);
+                
+            options = options || {};
+
+            var self = this;
+            var timeout = typeof options.timeout === 'number' ? options.timeout : 7500;
 
-            return tried_all;
+            // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice,
+            // then we want to notify the user that we are waiting on something )
+            var posOrderModel = new instance.web.Model('pos.order');
+            return posOrderModel.call('create_from_ui',
+                [_.map(orders, function (order) {
+                    order.to_invoice = options.to_invoice || false;
+                    return order;
+                })],
+                undefined,
+                {
+                    shadow: !options.to_invoice,
+                    timeout: timeout
+                }
+            ).then(function () {
+                _.each(orders, function (order) {
+                    self.db.remove_order(order.id);
+                });
+            }).fail(function (unused, event){
+                // prevent an error popup creation by the rpc failure
+                // we want the failure to be silent as we send the orders in the background
+                event.preventDefault();
+                console.error('Failed to send orders:', orders);
+            });
         },
 
         scan_product: function(parsed_code){
index 03ae42f..94357c0 100644 (file)
@@ -1596,8 +1596,8 @@ class Export(http.Controller):
             model, map(operator.itemgetter('name'), export_fields_list))
 
         return [
-            {'name': field['name'], 'label': fields_data[field['name']]}
-            for field in export_fields_list
+            {'name': field_name, 'label': fields_data[field_name]}
+            for field_name in fields_data.keys()
         ]
 
     def fields_info(self, model, export_fields):
index ba88946..f4f1f6d 100644 (file)
@@ -1,5 +1,2 @@
-all: *.css
-%.css: %.sass
-       sass -t expanded --compass --unix-newlines $< $@
-watch:
-       sass -t expanded --compass --unix-newlines --watch .:.
+sass:
+       sass -t expanded --compass --unix-newlines --watch base.sass:base.css&
\ No newline at end of file
index e43a2fb..6b568f8 100644 (file)
 .openerp td {
   vertical-align: top;
 }
-.openerp .oe_title {
-  width: 50%;
-  float: left;
-}
-.openerp .oe_title:after {
-  content: ".";
-  display: block;
-  height: 0;
-  clear: both;
-  visibility: hidden;
-}
-.openerp .oe_form_group {
-  clear: both;
-}
 .openerp .zebra tbody tr:nth-child(odd) td {
   background-color: #f0f0fa;
   background-color: #efeff8;
 .openerp .oe_about .oe_bottom a {
   color: #eeeeee;
 }
-.openerp a.oe_form_uri:hover {
+.openerp .oe_form_uri {
+  color: #7c7bad;
+}
+.openerp .oe_form_uri:hover {
   text-decoration: underline;
 }
 .openerp .oe_application {
   border-radius: 0 3px 3px 0;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
+  height: 18px;
   padding: 0 4px;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category {
 }
 .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button {
   margin: 3px 2px 1px;
+  float: left;
 }
 .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button:first-child {
   margin-left: 6px;
 }
 .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span {
   font-size: 80%;
-  color: darkgreen;
+  color: darkGreen;
   vertical-align: top;
   position: relative;
   top: -4px;
   font-size: 95%;
   line-height: 1.2em;
 }
+.openerp .oe_debug_view_log label {
+  display: block;
+  width: 49%;
+  text-align: right;
+  float: left;
+  font-weight: bold;
+  color: #000099;
+}
+.openerp .oe_debug_view_log span {
+  display: block;
+  width: 49%;
+  float: right;
+  color: #333333;
+}
 .openerp .navbar {
   min-height: 32px;
   margin-bottom: 0px;
   border: none;
   z-index: 1;
-  position: static;
   background-color: #414141;
   background-color: #454343;
   background-image: -webkit-gradient(linear, left top, left bottom, from(#646060), to(#262626));
   border: none;
   padding: 10px 0 3px 0;
 }
+.openerp .jqstooltip {
+  height: auto !important;
+  width: auto !important;
+}
 .openerp h5 {
   font-weight: bold;
   font-size: smaller;
   margin: 3px 3px 0 !important;
 }
 
-.jqstooltip {
-  height: auto !important;
-  width: auto !important;
-  padding: 0;
-}
-
 @-moz-document url-prefix() {
   .openerp .oe_searchview .oe_searchview_search {
     top: -1px;
index b19db9e..5bb2bb9 100644 (file)
@@ -189,17 +189,6 @@ $sheet-padding: 16px
         vertical-align: middle
     td
         vertical-align: top
-    .oe_title
-        width: 50%
-        float: left    
-    .oe_title:after
-        content: "."
-        display: block
-        height: 0
-        clear: both
-        visibility: hidden    
-    .oe_form_group
-        clear: both
     .zebra tbody tr:nth-child(odd) td
         background-color: #f0f0fa
         @include vertical-gradient(#f0f0fa, #eeeef6)
@@ -1013,8 +1002,10 @@ $sheet-padding: 16px
                 color: #eee
     // }}}
     // ActionManager {{{
-    a.oe_form_uri:hover
-        text-decoration: underline
+    .oe_form_uri
+        color: $link-color
+        &:hover
+            text-decoration: underline
     .oe_application
         width: 100%
         height: 100%
@@ -1311,6 +1302,7 @@ $sheet-padding: 16px
                     background: $tag-bg-light
                     @include radius(0 3px 3px 0)
                 .oe_facet_category, .oe_facet_value
+                    height: 18px
                     padding: 0 4px
                 .oe_facet_category
                     color: white
@@ -1647,6 +1639,7 @@ $sheet-padding: 16px
             float: right
         .oe_button
             margin: 3px 2px 1px
+            float: left
             &:first-child
                 margin-left: 6px
 
@@ -2426,6 +2419,18 @@ $sheet-padding: 16px
     .oe_debug_view_log
         font-size: 95%
         line-height: 1.2em
+    .oe_debug_view_log label
+        display: block
+        width: 49%
+        text-align: right
+        float: left
+        font-weight: bold
+        color: #009
+    .oe_debug_view_log span
+        display: block
+        width: 49%
+        float: right
+        color: #333
     // }}}
     // Bootstrap HACKS {{{
     .navbar
@@ -2433,7 +2438,6 @@ $sheet-padding: 16px
         margin-bottom: 0px
         border: none
         z-index: 1
-        position: static
         background-color: #414141
         @include vertical-gradient(#646060, #262626)
     .navbar-default
@@ -2513,7 +2517,10 @@ $sheet-padding: 16px
         border: none
         padding: 10px 0 3px 0
 
-
+    // Customize for kanban tooltip
+    .jqstooltip
+        height: auto !important
+        width: auto !important
 
     // Customize for chatter
     h5
@@ -2524,12 +2531,7 @@ $sheet-padding: 16px
     .oe_msg_subtype_check
         margin: 3px 3px 0 !important
     // }}}
-// Customize for kanban tooltip
-.jqstooltip
-    height: auto !important
-    width: auto !important
-    padding: 0
-        
+
 @-moz-document url-prefix()
     .openerp
         .oe_searchview .oe_searchview_search
index 461bfef..afa761d 100644 (file)
@@ -1336,15 +1336,10 @@ instance.web.WebClient = instance.web.Client.extend({
         var state = $.bbq.getState(true);
         if (_.isEmpty(state) || state.action == "login") {
             self.menu.has_been_loaded.done(function() {
-                new instance.web.Model("res.users").call("read", [self.session.uid, ["action_id"]]).done(function(data) {
-                    var first_menu_id = self.menu.$el.find("a:first").data("menu");
-                    if(first_menu_id)
-                        self.menu.menu_click(first_menu_id);
-
-                    if(data.action_id) {
-                        self.action_manager.do_action(data.action_id[0]);
-                    }
-                });
+                var first_menu_id = self.menu.$el.find("a:first").data("menu");
+                if(first_menu_id) {
+                    self.menu.menu_click(first_menu_id);
+                }
             });
         } else {
             $(window).trigger('hashchange');
index cc595c3..78e3001 100644 (file)
@@ -452,9 +452,6 @@ instance.web.DataSet =  instance.web.Class.extend(instance.web.PropertiesMixin,
      * @returns {$.Deferred}
      */
     read_ids: function (ids, fields, options) {
-        if (_.isEmpty(ids))
-            return $.Deferred().resolve([]);
-            
         options = options || {};
         // TODO: reorder results to match ids list
         return this._model.call('read',
@@ -875,8 +872,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
         });
         var return_records = function() {
             var records = _.map(ids, function(id) {
-                var c = _.find(self.cache, function(c) {return c.id === id;});
-                return _.isUndefined(c) ? c : _.extend({}, c.values, {"id": id});
+                return _.extend({}, _.detect(self.cache, function(c) {return c.id === id;}).values, {"id": id});
             });
             if (self.debug_mode) {
                 if (_.include(records, undefined)) {
index 3c32dbe..2f6bbce 100644 (file)
@@ -205,7 +205,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) {
         case 'selection': case 'statusbar':
             // Each choice is [value, label]
             if(_.isArray(value)) {
-                 return value[1];
+                 value = value[0];
             }
             var result = _(descriptor.selection).detect(function (choice) {
                 return choice[0] === value;
index b667d13..903a9f4 100644 (file)
@@ -414,7 +414,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
                 context: this.dataset.get_context(),
             });
 
-            this.alive($.when(load_view)).then(function (r) {
+            $.when(load_view).then(function (r) {
                 return self.search_view_loaded(r);
             }).fail(function () {
                 self.ready.reject.apply(null, arguments);
index f1fc377..4576e9d 100644 (file)
@@ -1030,9 +1030,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
     open_defaults_dialog: function () {
         var self = this;
         var display = function (field, value) {
-            if (!value) { return value; }
             if (field instanceof instance.web.form.FieldSelection) {
-                return _(field.get('values')).find(function (option) {
+                return _(field.values).find(function (option) {
                     return option[0] === value;
                 })[1];
             } else if (field instanceof instance.web.form.FieldMany2One) {
@@ -3092,7 +3091,7 @@ instance.web.form.CompletionFieldMixin = {
             // quick create
             var raw_result = _(data.result).map(function(x) {return x[1];});
             if (search_val.length > 0 && !_.include(raw_result, search_val) &&
-                ! (self.options && (self.options.no_create || self.options.no_quick_create))) {
+                ! (self.options && self.options.no_quick_create)) {
                 values.push({
                     label: _.str.sprintf(_t('Create "<strong>%s</strong>"'),
                         $('<span />').text(search_val).html()),
@@ -3103,15 +3102,13 @@ instance.web.form.CompletionFieldMixin = {
                 });
             }
             // create...
-            if (!(self.options && self.options.no_create)){
-                values.push({
-                    label: _t("Create and Edit..."),
-                    action: function() {
-                        self._search_create_popup("form", undefined, self._create_context(search_val));
-                    },
-                    classname: 'oe_m2o_dropdown_option'
-                });
-            }
+            values.push({
+                label: _t("Create and Edit..."),
+                action: function() {
+                    self._search_create_popup("form", undefined, self._create_context(search_val));
+                },
+                classname: 'oe_m2o_dropdown_option'
+            });
 
             return values;
         });
@@ -5132,7 +5129,7 @@ instance.web.form.FieldReference = instance.web.form.AbstractField.extend(instan
             .on('blurred', null, function () {self.trigger('blurred');});
 
         this.m2o = new instance.web.form.FieldMany2One(fm, { attrs: {
-            name: 'Referenced Document',
+            name: 'm2o',
             modifiers: JSON.stringify({readonly: this.get('effective_readonly')}),
         }});
         this.m2o.on("change:value", this, this.data_changed);
index e01ab29..8e3923d 100644 (file)
@@ -1654,12 +1654,9 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
 function synchronized(fn) {
     var fn_mutex = new $.Mutex();
     return function () {
-        var obj = this;
         var args = _.toArray(arguments);
-        return fn_mutex.exec(function () {
-            if (obj.isDestroyed()) { return $.when(); }
-            return fn.apply(obj, args)
-        });
+        args.unshift(this);
+        return fn_mutex.exec(fn.bind.apply(fn, args));
     };
 }
 var DataGroup =  instance.web.Class.extend({
index 23390df..82a2095 100644 (file)
@@ -600,7 +600,6 @@ instance.web.ViewManager =  instance.web.Widget.extend({
                     action_views_ids : views_ids
                 }, self.flags, self.flags[view.view_type] || {}, view.options || {})
             });
-            
             views_ids[view.view_type] = view.view_id;
         });
         if (this.flags.views_switcher === false) {
@@ -608,11 +607,7 @@ instance.web.ViewManager =  instance.web.Widget.extend({
         }
         // If no default view defined, switch to the first one in sequence
         var default_view = this.flags.default_view || this.views_src[0].view_type;
-  
-
-        return this.switch_mode(default_view, null, this.flags[default_view] && this.flags[default_view].options);
-      
-        
+        return this.switch_mode(default_view);
     },
     switch_mode: function(view_type, no_store, view_options) {
         var self = this;
@@ -820,11 +815,6 @@ instance.web.ViewManager =  instance.web.Widget.extend({
             contexts: [action_context].concat(contexts || []),
             group_by_seq: groupbys || []
         }).done(function (results) {
-            if (results.error) {
-                throw new Error(
-                        _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s",
-                                      JSON.stringify(results.error)));
-            }
             self.dataset._model = new instance.web.Model(
                 self.dataset.model, results.context, results.domain);
             var groupby = results.group_by.length
@@ -1269,7 +1259,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
         this.dataset = dataset;
         this.model_id = model_id;
         if (args && args[0].error) {
-            this.do_warn(_t('Uploading Error'), args[0].error);
+            this.do_warn( instance.web.qweb.render('message_error_uploading'), args[0].error);
         }
         if (!model_id) {
             this.on_attachments_loaded([]);
@@ -1353,7 +1343,7 @@ instance.web.View = instance.web.Widget.extend({
                 "context": this.dataset.get_context(),
             });
         }
-        return this.alive(view_loaded_def).then(function(r) {
+        return view_loaded_def.then(function(r) {
             self.fields_view = r;
             // add css classes that reflect the (absence of) access rights
             self.$el.addClass('oe_view')
index 80b82c1..fc9c215 100644 (file)
 </t>
 <t t-name="ViewManagerDebugViewLog">
     <div class="oe_debug_view_log">
-        <table class="table table-condensed table-striped">
-            <tr>
-                <th>ID:</th>
-                <td><t t-esc="perm.id"/></td>
-            </tr>
-            <tr>
-                <th>XML ID:</th>
-                <td><t t-esc="perm.xmlid or '/'"/></td>
-            </tr>
-            <tr>
-                <th>Creation User:</th>
-                <td><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Creation Date:</th>
-                <td><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Latest Modification by:</th>
-                <td><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Latest Modification Date:</th>
-                <td><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></td>
-            </tr>
-        </table>
+        <label>ID:</label>
+        <span><t t-esc="perm.id"/></span>
+
+        <label>XML ID:</label>
+        <span><t t-esc="perm.xmlid"/></span>
+
+        <label>Creation User:</label>
+        <span><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+        <label>Creation Date:</label>
+        <span><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></span>
+
+        <label>Latest Modification by:</label>
+        <span><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+        <label>Latest Modification Date:</label>
+        <span><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></span>
     </div>
 </t>
 <t t-name="ViewPager">
index 77bf3fb..ef84f8a 100644 (file)
@@ -5,9 +5,9 @@
 _.str.toBoolElse = function(str, elseValues, trueValues, falseValues) {
       var ret = _.str.toBool(str, trueValues, falseValues);
       if (_.isUndefined(ret)) {
-        return elseValues;
+        return elseValues
       }
-      return ret;
+      return ret
 };
 
 openerp.web_calendar = function(instance) {
@@ -37,7 +37,7 @@ openerp.web_calendar = function(instance) {
     }
 
     function isNullOrUndef(value) {
-        return _.isUndefined(value) || _.isNull(value);
+        return _.isUndefined(value) || _.isNull(value)
     }
     
     instance.web.views.add('calendar', 'instance.web_calendar.CalendarView');
@@ -60,6 +60,7 @@ openerp.web_calendar = function(instance) {
             this.range_start = null;
             this.range_stop = null;
             this.selected_filters = [];
+                        
         },
 
         set_default_options: function(options) {
@@ -71,9 +72,7 @@ openerp.web_calendar = function(instance) {
 
         destroy: function() {
             this.$calendar.fullCalendar('destroy');
-            if (this.$small_calendar){
-                this.$small_calendar.datepicker('destroy');
-            }
+            this.$small_calendar.datepicker('destroy');
             this._super.apply(this, arguments);
         },
 
@@ -113,21 +112,21 @@ openerp.web_calendar = function(instance) {
             this.date_start = attrs.date_start;     // Field name of starting date field
             this.date_delay = attrs.date_delay;     // duration
             this.date_stop = attrs.date_stop;
-            this.all_day = attrs.all_day;
+            this.all_day = attrs.all_day; 
+            this.attendee_people = attrs.attendee;  
             this.how_display_event = '';
-            this.attendee_people = attrs.attendee;
-
+           
             if (!isNullOrUndef(attrs.quick_create_instance)) {
-                self.quick_create_instance = 'instance.' + attrs.quick_create_instance;
+                self.quick_create_instance = 'instance.' + attrs.quick_create_instance;                
             }
                 
             //if quick_add = False, we don't allow quick_add
             //if quick_add = not specified in view, we use the default quick_create_instance
             //if quick_add = is NOT False and IS specified in view, we this one for quick_create_instance'   
             
-            this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) );
+            this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) );            
             if (this.quick_add_pop && !isNullOrUndef(attrs.quick_add)) {
-                self.quick_create_instance = 'instance.' + attrs.quick_add;
+                self.quick_create_instance = 'instance.' + attrs.quick_add;                
             }
             // The display format which will be used to display the event where fields are between "[" and "]"
             if (!isNullOrUndef(attrs.display)) {
@@ -136,29 +135,18 @@ openerp.web_calendar = function(instance) {
             
             // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter
             if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup,true)) {
-                this.open_popup_action = false;
+                this.open_popup_action = false; 
             }
             else {
                 this.open_popup_action = attrs.event_open_popup;
             }
             
-
-            // If this field is set to true, we will use the calendar_friends model as filter and not the color field.
-            this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)) && (!isNullOrUndef(self.options.$sidebar));
+            // If this field is set to true, we will use de calendar_friends model as filter and not the color field.
+            this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)); 
 
             // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event
             // The color is the color of the attendee, so don't need to show again that it will be present
-            this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee, true))) && (!isNullOrUndef(self.options.$sidebar));
-
-
-
-            // if we have not sidebar, (eg: Dashboard), we don't use the filter "coworkers"
-            if (isNullOrUndef(self.options.$sidebar)) {
-                this.useContacts = false;
-                this.colorIsAttendee = false;
-                this.attendee_people = undefined;
-            }
-
+            this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee,true))); 
                 
 /*
             Will be more logic to do it in futur, but see below to stay Retro-compatible
@@ -176,14 +164,14 @@ openerp.web_calendar = function(instance) {
             }            
 */
             if (isNullOrUndef(attrs.avatar_model)) {
-                this.avatar_model = null;
+                this.avatar_model = null; 
             }
             else {
                 this.avatar_model = attrs.avatar_model;
             }
            
             if (isNullOrUndef(attrs.avatar_title)) {
-                this.avatar_title = this.avatar_model;
+                this.avatar_title = this.avatar_model; 
             }
             else {
                 this.avatar_title = attrs.avatar_title;
@@ -207,7 +195,7 @@ openerp.web_calendar = function(instance) {
                 .call("check_access_rights", ["create", false])
                 .then(function (create_right) {
                     self.create_right = create_right;
-                    self.init_calendar().then(function() {
+                    self.init_calendar().then(function() {    
                         self.trigger('calendar_view_loaded', fv);
                         self.ready.resolve();
                     });
@@ -243,15 +231,15 @@ openerp.web_calendar = function(instance) {
                     self.proxy('update_record')(event._id, data);
                 },
                 eventRender: function (event, element, view) {
-                    element.find('.fc-event-title').html(event.title);
+                    element.find('.fc-event-title').html(event.title);                    
                 },
-                eventAfterRender: function (event, element, view) {
+                eventAfterRender: function (event, element, view) {                    
                     if ((view.name !== 'month') && (((event.end-event.start)/60000)<=30)) {
                         //if duration is too small, we see the html code of img
                         var current_title = $(element.find('.fc-event-time')).text();
-                        var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length);
+                        var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length)
                         element.find('.fc-event-time').html(new_title);
-                    }
+                    }                    
                 },
                 eventClick: function (event) { self.open_event(event._id,event.title); },
                 select: function (start_date, end_date, all_day, _js_event, _view) {
@@ -260,6 +248,7 @@ openerp.web_calendar = function(instance) {
                         end: end_date,
                         allDay: all_day,
                     });
+
                     self.open_quick_create(data_template);
 
                 },
@@ -288,7 +277,7 @@ openerp.web_calendar = function(instance) {
                             agenda: 'h:mm{ - h:mm}', // 5:00 - 6:30
 
                             // for all other views
-                            '': 'h(:mm)tt'  // 7pm
+                            '': 'h(:mm)tt'            // 7pm
                         },
                 weekMode : 'liquid',
                 aspectRatio: 1.8,
@@ -305,11 +294,11 @@ openerp.web_calendar = function(instance) {
                         context.$calendar.fullCalendar('changeView','agendaDay');
                     }
                 }
-                else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)===0)) {
+                else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)==0)) {
                         context.$calendar.fullCalendar('changeView','agendaWeek');
                 }
                 context.$calendar.fullCalendar('gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay);
-            };
+            }
         },
 
         init_calendar: function() {
@@ -323,10 +312,9 @@ openerp.web_calendar = function(instance) {
                 this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) });
             
                 if (this.useContacts) {
-                    //Get my Partner ID
                     new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first()
                         .done(
-                            function(result) {
+                            function(result) { 
                                 var sidebar_items = {};
                                 var filter_value = result.partner_id[0];
                                 var filter_item = {
@@ -338,12 +326,12 @@ openerp.web_calendar = function(instance) {
                                 sidebar_items[filter_value] = filter_item ;
                                 filter_item = {
                                         value: -1,
-                                        label: _lt("Everybody's calendars"),
+                                        label: _lt("All calendars"),
                                         color: self.get_color(-1),
                                         avatar_model: self.avatar_model
                                     };
                                 sidebar_items[-1] = filter_item ;
-                                //Get my coworkers/contacts
+
                                 new instance.web.Model("calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) {
                                     _.each(result, function(item) {
                                         filter_value = item.partner_id[0];
@@ -359,12 +347,12 @@ openerp.web_calendar = function(instance) {
                                     self.allFilters = sidebar_items;
                                     self.sidebar.filter.events_loaded(sidebar_items);
                                     self.sidebar.filter.addUpdateButton();
-                                }).done(function () {
-                                    self.$calendar.fullCalendar('refetchEvents');
+                                }).done(function () { 
+                                    self.$calendar.fullCalendar('refetchEvents');            
                                 });
                             }
-                         );
-                }
+                         );               
+                };
                 this.extraSideBar();
                 
             }
@@ -392,7 +380,7 @@ openerp.web_calendar = function(instance) {
                         delete this.quick;
                         this.$calendar.fullCalendar('unselect');
                     });
-            this.quick.replace(this.$el.find('.oe_calendar_qc_placeholder'));
+            this.quick.replace($(".oe_calendar_qc_placeholder"));
             this.quick.focus();
             
         },
@@ -498,20 +486,13 @@ openerp.web_calendar = function(instance) {
         event_data_transform: function(evt) {
             var self = this;
 
-            var date_delay = evt[this.date_delay] || 1.0,
+            var date_start = instance.web.auto_str_to_date(evt[this.date_start]),
+                date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null,
+                date_delay = evt[this.date_delay] || 1.0,
                 all_day = this.all_day ? evt[this.all_day] : false,
                 res_computed_text = '',
                 the_title = '',
-                attendees = [];
-
-            if (!all_day) {
-                date_start = instance.web.auto_str_to_date(evt[this.date_start]);
-                date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null;
-            }
-            else {
-                date_start = instance.web.auto_str_to_date(evt[this.date_start].split(' ')[0],'date');
-                date_stop = this.date_stop  ? instance.web.auto_str_to_date(evt[this.date_stop].split(' ')[0],'date').addMinutes(-1) : null;
-            }
+                attendees = [];          
 
             if (this.info_fields) {
                 var temp_ret = {};
@@ -545,7 +526,7 @@ openerp.web_calendar = function(instance) {
                         temp_ret[fieldname] = value;
                     }
                     res_computed_text = res_computed_text.replace("["+fieldname+"]",temp_ret[fieldname]);
-                });
+                });                
 
                 
                 if (res_computed_text.length) {
@@ -553,8 +534,8 @@ openerp.web_calendar = function(instance) {
                 }
                 else {
                     var res_text= [];
-                    _.each(temp_ret, function(val,key) { res_text.push(val); });
-                    the_title = res_text.join(', ');
+                    _.each(temp_ret, function(val,key) { res_text.push(val)} );
+                    the_title = res_text.join(', ');                    
                 }
                 the_title = _.escape(the_title);
                 
@@ -566,41 +547,41 @@ openerp.web_calendar = function(instance) {
                     var attendee_showed = 0;
                     var attendee_other = '';
 
-                    _.each(temp_ret[this.attendee_people],
-                        function (the_attendee_people) {
+                    _.each(temp_ret[this.attendee_people], 
+                        function (the_attendee_people) { 
                             attendees.push(the_attendee_people);
                             attendee_showed += 1;
-                            if (attendee_showed<= MAX_ATTENDEES) {
-                                if (self.avatar_model !== null) {
-                                       the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head"  \
-                                                            src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';
+                            if (attendee_showed<= MAX_ATTENDEES) {                            
+                                if (self.avatar_model != null) {
+                                       the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head" src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';                                
                                 }
                                 else {
                                     if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) {
                                             tempColor = (self.all_filters[the_attendee_people] != undefined) 
                                                                 ? self.all_filters[the_attendee_people].color
                                                                 : self.all_filters[-1].color;
-                                        the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>';
+                                            
+                                        the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>' 
                                     }//else don't add myself
                                 }
                             }
                             else {
                                 attendee_other += self.all_attendees[the_attendee_people] +", ";
-                            }
+                            }                                    
                         }
                     );
                     if (attendee_other.length>2) {
-                        the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';
+                        the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';                    
                     }
                     the_title = the_title_avatar + the_title;
-                }
+                }                
             }
             
             if (!date_stop && date_delay) {
                 date_stop = date_start.clone().addHours(date_delay);
             }
             if (this.fields[this.date_start].type != "date" && all_day) {
-                //date_stop.addDays(-1);
+                date_stop.addDays(-1);
             }
             var r = {
                 'start': date_start.toString('yyyy-MM-dd HH:mm:ss'),
@@ -612,19 +593,20 @@ openerp.web_calendar = function(instance) {
             };
             
 
-            if (!self.useContacts || self.all_filters[evt[this.color_field]] !== undefined) {
+            if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) {
                 if (this.color_field && evt[this.color_field]) {
                     var color_key = evt[this.color_field];
                     if (typeof color_key === "object") {
                         color_key = color_key[0];
                     }
-                    r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);
+                    r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);                                
                 }
             }
             else  { // if form all, get color -1
 
                   r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color;
             }
+            
             return r;
         },
         
@@ -641,7 +623,7 @@ openerp.web_calendar = function(instance) {
             
             var event_end = event.end;
             //Bug when we move an all_day event from week or day view, we don't have a dateend or duration...            
-            if (event_end === null) {
+            if (event_end == null) {
                 event_end = new Date(event.start).addHours(2);
             }
 
@@ -651,14 +633,14 @@ openerp.web_calendar = function(instance) {
                     event_end = new Date(event.start);
                 }
                 if (this.all_day) {
-                    event_end = (new Date(event_end.getTime())).addDays(1);
-                    date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),12);
-                    date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),12);
+                    event_end = (new Date(event_end.getTime())).addDays(1); 
+                    date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate()))
+                    date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate()))            
                 }
                 else {
-                    date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7);
-                    date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19);
-                }
+                    date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7))
+                    date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19))            
+                }                                
                 data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]);
                 if (this.date_stop) {
                     data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]);
@@ -666,15 +648,17 @@ openerp.web_calendar = function(instance) {
                                 
             }
             else {
+                
                 data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]);
                 if (this.date_stop) {
                     data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]);
-                }
+                }            
+
             }
 
 
             if (this.all_day) {
-                data[this.all_day] = event.allDay;
+                data[this.all_day] = event.allDay;                
             }
 
             if (this.date_delay) {
@@ -683,14 +667,8 @@ openerp.web_calendar = function(instance) {
             }
             return data;
         },
-
         do_search: function(domain, context, _group_by) {
             var self = this;
-
-            if (self.sidebar) {
-                self.sidebar.filter.is_loaded = false;
-            }
-
             if (! _.isUndefined(this.event_source)) {
                 this.$calendar.fullCalendar('removeEventSource', this.event_source);
             }
@@ -702,32 +680,33 @@ openerp.web_calendar = function(instance) {
                         domain: self.get_range_domain(domain, start, end),
                         context: context,
                     }).done(function(events) {
-
                         if (self.event_source !== current_event_source) {
                             console.log("Consecutive ``do_search`` called. Cancelling.");
                             return;
                         }
+                        // We should make sure that *2many used in title of event have their extended form [ID, NAME]...
                         
-                       if (self.attendee_people !== undefined) {
-                            //Else we filter on 'Everybody's Calendar, we don't filter events 
-                            if (self.selected_filters.indexOf(-1) == -1) {
-
-                                //If we filter on contacts... we keep only events from coworkers                                 
-                                events = $.map(events, function (e) {
-                                        if (_.intersection(self.selected_filters,e[self.attendee_people]).length ) {
-                                            return e;
-                                        }
-                                        return null;
-                                });
+                        events = $.map(events, function (e) {
+                            
+                            if (self.attendee_people != undefined) { //If we filter on contacts...
+                                if (_.intersection(self.selected_filters,e[self.attendee_people]).length || (self.selected_filters.indexOf(-1) > -1)) {
+                                    return e;
+                                }
+                                else {
+                                    return null;
+                                }   
                             }
-                        }
+                            else { //We adds all events 
+                                return e;
+                            }                            
+                            return null;                            
+                        });
                         
-                        if (!self.useContacts) {  // If we use all peoples displayed in the current month as filter in sidebars
+                        if (!self.useContacts) {  // If we use all peoples as filter in sidebars
                             var now_filters = {};
                             var filter_value;
                             var filter_item;
                             
-                            
                             _.each(events, function (e) {
                                 filter_value = e[self.color_field][0];
                                 filter_item = {
@@ -741,44 +720,31 @@ openerp.web_calendar = function(instance) {
                                 }
                             });
                             
-                            
                             self.allFilters = now_filters;
-
-                            if (self.sidebar) {
-                                if (!self.sidebar.filter.is_loaded) {
-                                    self.sidebar.filter.events_loaded(now_filters);
-                                }
-                                else {
-                                    events = $.map(events, function (e) {
-                                        if (_.contains(self.selected_filters,e[self.color_field][0]) ) {
-                                            return e;
-                                        }
-                                        return null;
-                                    });
-                                }
-                            }
+                            self.sidebar.filter.events_loaded(now_filters);                            
+                            
                             return self.perform_necessary_name_gets(events).then(callback);
                         }
                         else {
                             var all_attendees = [];
                             
                             _.each(events, function (e) {
-                                all_attendees.push(e[self.attendee_people]);
+                                all_attendees.push(e[self.attendee_people]);                                
                             });
                             
-                            self.all_attendees = {};
+                            self.all_attendees = {}
                             
                             all_attendees = _.chain(all_attendees).flatten().uniq().value();
                             
-                            if (self.avatar_title !== null) {
+                            if (self.avatar_title != null) {
                                 new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) {
                                     _.each(result, function(item) {
                                         self.all_attendees[item.id] = item.name;
                                     });
-                                }).done(function() {
+                                }).done(function() { 
                                     return self.perform_necessary_name_gets(events).then(callback);
                                 });
-                            }
+                            }                                                        
                             else {
                                 _.each(all_attendees,function(item){
                                         self.all_attendees[item] = '';
@@ -786,7 +752,10 @@ openerp.web_calendar = function(instance) {
                                 return self.perform_necessary_name_gets(events).then(callback);
                                 
                             }
+                            
                         }
+                        
+
                     });
                 },
                 eventDataTransform: function (event) {
@@ -807,6 +776,7 @@ openerp.web_calendar = function(instance) {
                  [this.date_start, '<=', format(end.clone())]]);
         },
 
+
         /**
          * Updates record identified by ``id`` with values in object ``data``
          */
@@ -829,22 +799,26 @@ openerp.web_calendar = function(instance) {
             }
             return false;
         },
-        open_event: function(id, title) {
+        open_event: function(id,title) {
             var self = this;
-            if (! this.open_popup_action) {
+            if (! this.open_popup_action) { 
                 var index = this.dataset.get_id_index(id);
                 this.dataset.index = index;
                 this.do_switch_view('form', null, { mode: "edit" });
-            }
+            }            
             else {
+
+                var self = this;
+
                 var pop = new instance.web.form.FormOpenPopup(this);
+                console.log(this.open_popup_action, +this.open_popup_action);
                 pop.show_element(this.dataset.model, id, this.dataset.get_context(), {
                     title: _.str.sprintf(_t("View: %s"),title),
                     view_id: +this.open_popup_action,
                     res_id: id,
                     target: 'new',
                     readonly:true
-                });
+                });              
 
                var form_controller = pop.view_form;
                form_controller.on("load_record", self, function(){
@@ -852,25 +826,33 @@ openerp.web_calendar = function(instance) {
                     button_edit = _.str.sprintf("<button class='oe_button oe_bold editme oe_highlight'><span> %s </span></button>",_t("Edit Event"));
                     
                     
-                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete);
-                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit);
+                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete)
+                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit)
                     
                     $('.delme').click(
-                        function() {
-                            $('.oe_form_button_cancel').trigger('click');
-                            self.remove_event(id);
+                        function() { 
+                            $('.oe_form_button_cancel').trigger('click'); 
+                            self.remove_event(id); 
                         }
                     );
                     $('.editme').click(
-                        function() {
-                            $('.oe_form_button_cancel').trigger('click');
-                            self.dataset.index = self.dataset.get_id_index(id);
+                        function() { 
+                            $('.oe_form_button_cancel').trigger('click'); 
+
+                            var index = self.dataset.get_id_index(id);
+                            self.dataset.index = index;
                             self.do_switch_view('form', null, { mode: "edit" });
+
                         }
                     );
+                    
+                    
                });
-            }
-            return false;
+                 
+            }   
+            
+            return false;         
+            
         },
 
         do_show: function() {
@@ -914,10 +896,6 @@ openerp.web_calendar = function(instance) {
         slow_created: function () {
             // refresh all view, because maybe some recurrents item
             var self = this;
-            if (self.sidebar) {
-                // force filter refresh
-                self.sidebar.filter.is_loaded = false;
-            }
             self.$calendar.fullCalendar('refetchEvents');
         },
 
@@ -951,7 +929,7 @@ openerp.web_calendar = function(instance) {
         template: 'CalendarView.quick_create',
         
         init: function(parent, dataset, buttons, options, data_template) {
-            this._super(parent);
+            this._super(parent);            
             this.dataset = dataset;
             this._buttons = buttons || false;
             this.options = options;
@@ -962,7 +940,7 @@ openerp.web_calendar = function(instance) {
         get_title: function () {
             var parent = this.getParent();
             if (_.isUndefined(parent)) {
-                return _t("Create");
+                return _t("Create")
             }
             var title = (_.isUndefined(parent.field_widget)) ?
                     (parent.string || parent.name) :
@@ -983,7 +961,7 @@ openerp.web_calendar = function(instance) {
                 if(event.keyCode == 13){
                     self.$input.off('keyup', enterHandler);
                     if (!self.quick_add()){
-                        self.$input.on('keyup', enterHandler);
+                        self.$input.on('keyup', enterHandler);                    
                     }
                 }
             });
@@ -992,13 +970,14 @@ openerp.web_calendar = function(instance) {
             submit.click(function clickHandler() {
                 submit.off('click', clickHandler);
                 if (!self.quick_add()){
-                   submit.on('click', clickHandler);                }
+                   submit.on('click', clickHandler);                    
+                }
                 self.focus();
             });
             this.$el.find(".oe_calendar_quick_create_edit").click(function () {
                 self.slow_add();
                 self.focus();
-            });
+            });            
             this.$el.find(".oe_calendar_quick_create_close").click(function (ev) {
                 ev.preventDefault();
                 self.trigger('close');
@@ -1014,6 +993,7 @@ openerp.web_calendar = function(instance) {
             });
             
             self.$el.on('dialogclose', self, function() {
+                console.log("dialogclose");
                 self.trigger('close');
             });
 
@@ -1027,10 +1007,10 @@ openerp.web_calendar = function(instance) {
          */
         quick_add: function() {
             var val = this.$input.val();
-            if (/^\s*$/.test(val)) {
-                return false;
+            if (/^\s*$/.test(val)) { 
+                return false; 
             }
-            return this.quick_create({'name': val}).always(function() { return true; });
+            return this.quick_create({'name': val}).always(function() { return true });
         },
         
         slow_add: function() {
@@ -1069,19 +1049,21 @@ openerp.web_calendar = function(instance) {
             return infos;
         },
         slow_create: function(data) {
-            //if all day, we could reset time to display 00:00:00
-            
             var self = this;
             var def = $.Deferred();
             var defaults = {};
-
             _.each($.extend({}, this.data_template, data), function(val, field_name) {
                 defaults['default_' + field_name] = val;
             });
-                        
+            
+            if (defaults['default_allday'] && (defaults['default_date_deadline'] || defaults['default_duration'])) {
+                delete defaults['default_date_deadline'];
+                delete defaults['default_duration'];
+            }
+
             var pop_infos = self.get_form_popup_infos();
             var pop = new instance.web.form.FormOpenPopup(this);
-            var context = new instance.web.CompoundContext(this.dataset.context, defaults);
+            var context = new instance.web.CompoundContext(this.dataset.context, defaults)
             pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
                 title: this.get_title(),
                 disable_multiple_selection: true,
@@ -1330,6 +1312,7 @@ openerp.web_calendar = function(instance) {
         },
 
         render_value: function() {
+            console.log("In render value");
             var self = this;
             this.dataset.set_ids(this.get("value"));
             this.is_loaded = this.is_loaded.then(function() {
@@ -1373,7 +1356,7 @@ openerp.web_calendar = function(instance) {
                 },
 
                 alternative_form_view: this.field.views ? this.field.views.form : undefined,
-                parent_view: this.view,
+                parent_view: this.view, //XXXvlab: to check ! this.view is likely undefined
                 child_name: this.name,
                 readonly: this.get("effective_readonly")
             });
@@ -1390,26 +1373,19 @@ openerp.web_calendar = function(instance) {
         }
     });
     instance.web_calendar.SidebarFilter = instance.web.Widget.extend({
-        is_loaded:false,
         events: {
             'change input:checkbox': 'filter_click'
         },
         init: function(parent, view) {
             this._super(parent);
-            this.view = view;
+            this.view = view;            
         },
-
-   
-
         events_loaded: function(filters) {
             var self = this;
-            self.is_loaded=true;
-            
             self.selected_filters = [];
             self.view.all_filters = filters;
             this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
-            this.filter_click(null);
-
+            this.filter_click(null);                        
         },
         filter_click: function(e) {
             var self = this,
@@ -1418,21 +1394,25 @@ openerp.web_calendar = function(instance) {
             this.$('div.oe_calendar_responsible input:checked').each(function() {
                 responsibles.push($(this).val());
                 
-                if (e==null && parseInt($(this).val())<0){
+                if (e==null && parseInt($(this).val())<0) {
                     $(this).prop('checked',false);
                     return;
-                }
-
+                }                    
                 self.view.selected_filters.push(parseInt($(this).val()));
             });
-            self.view.$calendar.fullCalendar('refetchEvents');
+            
+            if (e !== null) { //First intialize 
+                self.view.$calendar.fullCalendar('refetchEvents');  
+            }
+
+            
         },
         addUpdateButton: function() {
             var self=this;
             this.$('div.oe_calendar_all_responsibles').append(QWeb.render('CalendarView.sidebar.button_add_contact'));
-            this.$(".add_contacts_link_btn").on('click', function() {
-                self.rpc("/web/action/load", {
-                    action_id: "calendar.action_calendar_contacts"
+            this.$(".add_contacts_link_btn").on('click', function() {  
+                self.rpc("/web/action/load", { 
+                    action_id: "calendar.action_calendar_contacts" 
                 }).then( function(result) { return self.do_action(result); });
             });
             
index ace2f14..e1a50d4 100644 (file)
@@ -50,7 +50,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
             var field_name = field.attrs.name;
             if (_.has(field.attrs, 'interval')) {
                 field_name = field.attrs.name + ':' + field.attrs.interval;
-            }
+            } 
             if (_.has(field.attrs, 'type')) {
                 switch (field.attrs.type) {
                     case 'row':
@@ -77,20 +77,15 @@ instance.web_graph.GraphView = instance.web.View.extend({
     },
 
     do_search: function (domain, context, group_by) {
-        if (this.ignore_do_search) {
-            this.ignore_do_search = false;
-            return;
-        }
-
         var self = this,
-            col_group_by = self.get_groupbys_from_searchview('ColGroupBy', 'col_group_by'); 
+            col_group_by = context.col_group_by || this.get_groupbys_from_searchview('ColGroupBy', 'col_group_by');
 
         if (!this.graph_widget) {
             if (group_by.length) {
                 this.widget_config.row_groupby = group_by;
             }
             if (col_group_by.length) {
-                this.widget_config.col_groupby = col_group_by;
+                this.widget_config.col_groupby = group_by;
             }
             this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config);
             this.graph_widget.appendTo(this.$el);
@@ -106,18 +101,16 @@ instance.web_graph.GraphView = instance.web.View.extend({
         this.graph_widget.set(domain, group_by, col_group_by);
     },
 
-    extract_groupby: function (cat_field, context) {
-        context = (_.isString(context)) ? py.eval(context) : context;
-        return context[cat_field];
-    },
-
     get_groupbys_from_searchview: function (cat_name, cat_field) {
-        var self=this,
-            facet = this.search_view.query.findWhere({category:cat_name}),
+        var facet = this.search_view.query.findWhere({category:cat_name}),
             groupby_list = facet ? facet.values.models : [];
         return _.map(groupby_list, function (g) { 
             var context = g.attributes.value.attrs.context;
-            return self.extract_groupby(cat_field, context);
+            if (_.isString(context)) {
+                return py.eval(context).group_by;
+            } else {
+                return context[cat_field]; 
+            }
         });
     },
 
@@ -136,14 +129,6 @@ instance.web_graph.GraphView = instance.web.View.extend({
 
         if (!_.has(this.search_view, '_s_groupby')) { return; }
 
-        if (row_groupby.length && col_groupby.length) {
-            // when two changes to the search view will be done, the method do_search
-            // will be called twice, once with the correct groupby and incorrect col_groupby,
-            // and once with correct informations. This flag is necessary to prevent the 
-            // incorrect informations to propagate and trigger useless queries
-            this.ignore_do_search = true;
-        }
-
         // add row groupbys
         var row_facet = this.make_row_groupby_facets(row_groupby),
             row_search_facet = query.findWhere({category:'GroupBy'});
index 26f4797..ef547e2 100644 (file)
@@ -258,6 +258,9 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
             case 'swap_axis':
                 this.swap_axis();
                 break;
+            case 'expand_all':
+                this.pivot.expand_all().then(this.proxy('display_data'));
+                break;
             case 'update_values':
                 this.pivot.update_data().then(this.proxy('display_data'));
                 break;
@@ -284,30 +287,25 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
 
         if (header.expanded) {
             this.fold(header);
-            return;
-        } 
-        if (header.path.length < header.root.groupby.length) {
-            this.expand(id);
-            return;
-        } 
-        if (!this.important_fields.length) {
-            return;
-        }
+        } else {
+            if (header.path.length < header.root.groupby.length) {
+                this.expand(id);
+            } else {
+                if (!this.important_fields.length) {
+                    return;
+                }
 
-        var fields = _.map(this.important_fields, function (field) {
-                return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
-        });
-        if (this.dropdown) {
-            this.dropdown.remove();
+                var fields = _.map(this.important_fields, function (field) {
+                        return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
+                });
+                this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
+                $(event.target).after(this.dropdown);
+                this.dropdown.css({position:'absolute',
+                                   left:event.pageX,
+                                   top:event.pageY});
+                this.$('.field-selection').next('.dropdown-menu').toggle();
+            }
         }
-        this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
-        $(event.target).after(this.dropdown);
-        this.dropdown.css({position:'absolute',
-                           left:event.pageX,
-                           top:event.pageY});
-        this.$('.field-selection').next('.dropdown-menu').toggle();
-        
-        
     },
 
     field_selection: function (event) {
index eb0fb65..deb34e3 100644 (file)
@@ -35,6 +35,9 @@
             <label class="btn btn-default" data-choice="swap_axis" title="Swap Axis">
                 <span class="fa fa-expand"></span>
             </label>
+            <label class="btn btn-default" data-choice="expand_all" title="Expand All">
+                <span class="fa fa-arrows-alt"></span>
+            </label>
             <label class="btn btn-default" data-choice="update_values" title="Reload Data">
                 <span class="fa fa-refresh"></span>
             </label>
index 69e9a30..a790668 100644 (file)
@@ -15,7 +15,7 @@ instance.web.ViewManagerAction.include({
                 }
                 evt.currentTarget.selectedIndex = 0;
         }else{
-            return this._super.apply(this,arguments);
+            return this._super.apply(this,arguments); 
         }
     }
 });
@@ -73,10 +73,12 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         $.when(this.action_manager.do_action(action)).done(function() {
             var viewmanager = self.action_manager.inner_widget;
             var controller = viewmanager.views[viewmanager.active_view].controller;
-            $(controller.groups).bind({
-                'selected': function (e, ids, records, deselected) {
+            controller.on('view_loaded', self, function(){
+                $(controller.groups).bind({
+                    'selected': function(e, ids, records) {
                         self.main_view_id = ids[0];
-                }
+                    }
+                });
             });
         });
     },
@@ -230,11 +232,10 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         return main_object;
     },
     parse_xml: function(arch, view_id) {
-        //First element of att_list must be element tagname.
         main_object = {
             'level': 0,
             'id': this.xml_element_id +=1,
-            'att_list': ["view"],
+            'att_list': [],
             'name': _.str.sprintf("<view view_id = %s>", view_id),
             'child_id': []
         };
@@ -534,22 +535,15 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         var field_dataset = new instance.web.DataSetSearch(this, this.model, null, null);
         parent_tr = self.get_object_by_id(parseInt($(parent_tr).attr('id').replace(/[^0-9]+/g, '')), this.one_object['main_object'], [])[0].att_list[0];
         _.each([tr, parent_tr],function(element) {
-            var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
+            var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false; 
             property_to_check.push(value);
         });
         field_dataset.call( 'fields_get', []).done(function(result) {
             var fields = _.keys(result);
             fields.push(" "),fields.sort();
-            self.on_add_node(property_to_check, fields, self.inject_position(parent_tr,tr));
+            self.on_add_node(property_to_check, fields);
         });
     },
-    inject_position : function(parent_tag,current_tag){
-        if(parent_tag == "view")
-            return ['Inside'];
-        if(current_tag == "field")
-            return ['After','Before'];
-        return ['After','Before','Inside'];
-    },
     do_node_edit: function(side) {
         var self = this;
         var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []);
@@ -643,12 +637,12 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
             var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) {
                 return child.nodeType == 1;
             });
-            var inherited_view = _.detect(children, function(xml_child) {
+            arch.arch = _.detect(children, function(xml_child) {
                 var temp_obj = self.create_View_Node(xml_child),
                     insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list));
                 if (insert.length == _.uniq(check_list).length ) {return xml_child;}
             });
-            xml_arch = QWeb.load_xml(instance.web.xml_to_str(inherited_view));
+            xml_arch = QWeb.load_xml(arch.arch);
         }
         return self.do_save_xml(xml_arch.documentElement, obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
     },
@@ -947,11 +941,11 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
             });
         return def.promise();
     },
-    on_add_node: function(properties, fields, position){
+    on_add_node: function(properties, fields){
         var self = this;
         var  render_list = [{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), 'value': 'field', 'string': 'Node Type','type': 'selection'},
                             {'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'},
-                            {'name': 'position','selection': position, 'value': false, 'string': 'Position','type': 'selection'}];
+                            {'name': 'position','selection': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}];
         this.add_widget = [];
         this.add_node_dialog = new instance.web.Dialog(this,{
             title: _t("Properties"),
@@ -1192,7 +1186,7 @@ var _CHILDREN = {
 //e.g.:xyz 'td' : ['field']
 };
 // Generic html_tag list and can be added html tag in future. It's support above _CHILDREN dict's *html_tag* by default.
-// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
+// For specific child node one has to define tag above and specify children tag in list. Like above xyz example. 
 var html_tag = ['div','h1','h2','h3','h4','h5','h6','td','tr'];
 
 var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
index 2e95b3e..a6bb38b 100644 (file)
@@ -24,8 +24,6 @@ import logging
 import operator
 import os
 import time
-import datetime
-import dateutil
 
 import openerp
 from openerp import SUPERUSER_ID
@@ -270,7 +268,7 @@ class ir_actions_act_window(osv.osv):
         'filter': fields.boolean('Filter'),
         'auto_search':fields.boolean('Auto Search'),
         'search_view' : fields.function(_search_view, type='text', string='Search View'),
-        'multi': fields.boolean('Restrict to lists', help="If checked and the action is bound to a model, it will only appear in the More menu on list views"),
+        'multi': fields.boolean('Action on Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view"),
     }
 
     _defaults = {
@@ -912,33 +910,6 @@ class ir_actions_server(osv.osv):
         if action.link_new_record and action.link_field_id:
             self.pool[action.model_id.model].write(cr, uid, [context.get('active_id')], {action.link_field_id.name: res_id})
 
-    def _eval_context_for_action(self, cr, uid, action, context=None):
-        if context is None:
-            context = {}
-        model = self.pool[action.model_id.model]
-        active_id = context.get('active_id')
-        active_ids = context.get('active_ids', [active_id] if active_id else [])
-        target_record = None
-        if context.get('active_model') == action.model_id.model and active_id:
-            context = dict(context, active_ids=active_ids, active_id=active_id)
-            target_record = model.browse(cr, uid, active_id, context=context) if active_id else None
-        user = self.pool['res.users'].browse(cr, uid, uid)
-        eval_context = {
-            'self': model,
-            'object': target_record,
-            'obj': target_record,
-            'pool': self.pool,
-            'time': time,
-            'datetime': datetime,
-            'dateutil': dateutil,
-            'cr': cr,
-            'uid': uid,
-            'user': user,
-            'context': context,
-        }
-        return eval_context
-
-
     def run(self, cr, uid, ids, context=None):
         """ Runs the server action. For each server action, the condition is
         checked. Note that a void (``False``) condition is considered as always
@@ -961,14 +932,33 @@ class ir_actions_server(osv.osv):
         if context is None:
             context = {}
         res = False
+        user = self.pool.get('res.users').browse(cr, uid, uid)
+        active_ids = context.get('active_ids', [context.get('active_id')])
         for action in self.browse(cr, uid, ids, context):
-            eval_context = self._eval_context_for_action(cr, uid, action, context)
+            obj_pool = self.pool[action.model_id.model]
+            obj = None
+            if context.get('active_model') == action.model_id.model and context.get('active_id'):
+                obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
+
+            # evaluation context for python strings to evaluate
+            eval_context = {
+                'self': obj_pool,
+                'object': obj,
+                'obj': obj,
+                'pool': self.pool,
+                'time': time,
+                'cr': cr,
+                'uid': uid,
+                'user': user,
+            }
             condition = action.condition
             if condition is False:
                 # Void (aka False) conditions are considered as True
                 condition = True
             if hasattr(self, 'run_action_%s_multi' % action.state):
-                run_context = eval_context['context']
+                # set active_ids in context only needed if one active_id
+                run_context = dict(context, active_ids=active_ids)
+                eval_context["context"] = run_context
                 expr = eval(str(condition), eval_context)
                 if not expr:
                     continue
@@ -978,8 +968,6 @@ class ir_actions_server(osv.osv):
 
             elif hasattr(self, 'run_action_%s' % action.state):
                 func = getattr(self, 'run_action_%s' % action.state)
-                active_id = context.get('active_id')
-                active_ids = context.get('active_ids', [active_id] if active_id else [])
                 for active_id in active_ids:
                     # run context dedicated to a particular active_id
                     run_context = dict(context, active_ids=[active_id], active_id=active_id)
index 7ac0252..7e6c1f9 100644 (file)
                                     <field name="auto_refresh"/>
                                     <field name="auto_search"/>
                                     <field name="filter"/>
-                                    <field name="multi"/>
                                 </group>
                             </group>
                             <group string="Help">
index 634152f..d119c03 100644 (file)
@@ -1117,10 +1117,6 @@ class ir_model_data(osv.osv):
                     # Don't remove the LOG_ACCESS_COLUMNS unless _log_access
                     # has been turned off on the model.
                     field = self.pool[model].browse(cr, uid, [res_id], context=context)[0]
-                    if not field.exists():
-                        _logger.info('Deleting orphan external_ids %s', external_ids)
-                        self.unlink(cr, uid, external_ids)
-                        continue
                     if field.name in openerp.osv.orm.LOG_ACCESS_COLUMNS and self.pool[field.model]._log_access:
                         continue
                     if field.name == 'id':
index d4655bf..ccbd563 100644 (file)
@@ -316,14 +316,14 @@ class view(osv.osv):
                 return node
         return None
 
-    def inherit_branding(self, specs_tree, view_id, root_id):
+    def inherit_branding(self, specs_tree, view_id, source_id):
         for node in specs_tree.iterchildren(tag=etree.Element):
             xpath = node.getroottree().getpath(node)
             if node.tag == 'data' or node.tag == 'xpath':
-                self.inherit_branding(node, view_id, root_id)
+                self.inherit_branding(node, view_id, source_id)
             else:
                 node.set('data-oe-id', str(view_id))
-                node.set('data-oe-source-id', str(root_id))
+                node.set('data-oe-source-id', str(source_id))
                 node.set('data-oe-xpath', xpath)
                 node.set('data-oe-model', 'ir.ui.view')
                 node.set('data-oe-field', 'arch')
@@ -397,7 +397,7 @@ class view(osv.osv):
 
         return source
 
-    def apply_view_inheritance(self, cr, uid, source, source_id, model, root_id=None, context=None):
+    def apply_view_inheritance(self, cr, uid, source, source_id, model, context=None):
         """ Apply all the (directly and indirectly) inheriting views.
 
         :param source: a parent architecture to modify (with parent modifications already applied)
@@ -408,15 +408,13 @@ class view(osv.osv):
         :return: a modified source where all the modifying architecture are applied
         """
         if context is None: context = {}
-        if root_id is None:
-            root_id = source_id
         sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, uid, source_id, model, context=context)
         for (specs, view_id) in sql_inherit:
             specs_tree = etree.fromstring(specs.encode('utf-8'))
             if context.get('inherit_branding'):
-                self.inherit_branding(specs_tree, view_id, root_id)
+                self.inherit_branding(specs_tree, view_id, source_id)
             source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
-            source = self.apply_view_inheritance(cr, uid, source, view_id, model, root_id=root_id, context=context)
+            source = self.apply_view_inheritance(cr, uid, source, view_id, model, context=context)
         return source
 
     def read_combined(self, cr, uid, view_id, fields=None, context=None):
@@ -559,7 +557,7 @@ class view(osv.osv):
                         if f.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
                             node.remove(f)
                             ctx = context.copy()
-                            ctx['base_model_name'] = model
+                            ctx['base_model_name'] = Model
                             xarch, xfields = self.postprocess_and_fields(cr, user, column._obj or None, f, view_id, ctx)
                             views[str(f.tag)] = {
                                 'arch': xarch,
@@ -757,10 +755,6 @@ class view(osv.osv):
                 # running index by tag type, for XPath query generation
                 indexes = collections.defaultdict(lambda: 0)
                 for child in e.iterchildren(tag=etree.Element):
-                    if child.get('data-oe-xpath'):
-                        # injected by view inheritance, skip otherwise
-                        # generated xpath is incorrect
-                        continue
                     indexes[child.tag] += 1
                     self.distribute_branding(child, distributed_branding,
                                              parent_xpath=node_path,
index 6af09b7..a21b034 100644 (file)
@@ -394,16 +394,17 @@ class ir_values(osv.osv):
         for action in cr.dictfetchall():
             if not action['value']:
                 continue    # skip if undefined
-            action_model_name, action_id = action['value'].split(',')
-            action_model = self.pool.get(action_model_name)
-            if not action_model:
-                continue    # unknow model? skip it
-            fields = [field for field in action_model._all_columns if field not in EXCLUDED_FIELDS]
+            action_model,id = action['value'].split(',')
+            fields = [
+                    field
+                    for field in self.pool[action_model]._all_columns
+                    if field not in EXCLUDED_FIELDS]
             # FIXME: needs cleanup
             try:
-                action_def = action_model.read(cr, uid, int(action_id), fields, context)
+                action_def = self.pool[action_model].read(cr, uid, int(id), fields, context)
                 if action_def:
-                    if action_model_name in ('ir.actions.report.xml', 'ir.actions.act_window'):
+                    if action_model in ('ir.actions.report.xml','ir.actions.act_window',
+                                        'ir.actions.wizard'):
                         groups = action_def.get('groups_id')
                         if groups:
                             cr.execute('SELECT 1 FROM res_groups_users_rel WHERE gid IN %s AND uid=%s',
index 91a7799..558afbe 100644 (file)
@@ -124,8 +124,7 @@ class res_company(osv.osv):
         'rml_footer': fields.text('Report Footer', help="Footer text displayed at the bottom of all reports."),
         'rml_footer_readonly': fields.related('rml_footer', type='text', string='Report Footer', readonly=True),
         'custom_footer': fields.boolean('Custom Footer', help="Check this to define the report footer manually.  Otherwise it will be filled in automatically."),
-        'font': fields.many2one('res.font', string="Font", domain=[('mode', 'in', ('Normal', 'Regular', 'all', 'Book'))],
-            help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
+        'font': fields.many2one('res.font', string="Font",help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
         'logo': fields.related('partner_id', 'image', string="Logo", type="binary"),
         'logo_web': fields.function(_get_logo_web, string="Logo Web", type="binary", store={
             'res.company': (lambda s, c, u, i, x: i, ['partner_id'], 10),
index 0f404bd..c037b0e 100644 (file)
@@ -85,7 +85,7 @@
                                 <label for="font" />
                                 <div>
                                     <div>
-                                        <field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)" />
+                                        <field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)" domain="[('mode', 'in', ('normal', 'regular', 'all', 'book'))]" />
                                         <button string="(reload fonts)" name="act_discover_fonts" type="object" class="oe_link" colspan="1"/>
                                     </div>
                                 </div>
index e957308..9115cca 100644 (file)
@@ -209,7 +209,6 @@ class res_partner(osv.osv, format_address):
         context = dict(context or {})
         context.pop('show_address', None)
         context.pop('show_address_only', None)
-        context.pop('show_email', None)
         return dict(self.name_get(cr, uid, ids, context=context))
 
     # indirections to avoid passing a copy of the overridable method when declaring the function field
index b2aba69..ad01738 100644 (file)
@@ -906,8 +906,6 @@ class change_password_wizard(osv.TransientModel):
         for user in wizard.user_ids:
             user_ids.append(user.id)
         self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context)
-        # don't keep temporary password copies in the database longer than necessary
-        self.pool.get('change.password.user').unlink(cr, uid, user_ids)
         return {
             'type': 'ir.actions.act_window_close',
         }
index ba603c7..9c84d43 100644 (file)
             <field name="model">res.users</field>
             <field name="arch" type="xml">
                 <search string="Users">
-                    <field name="name" filter_domain="['|', '|', ('name','ilike',self), ('login','ilike',self), ('email','ilike',self)]" string="User"/>
+                    <field name="name" filter_domain="['|', '|', ('name','ilike',self), ('login','ilike',self), ('email,'ilike',self)]" string="User"/>
                     <field name="company_ids" string="Company" groups="base.group_multi_company"/>
                 </search>
             </field>
index 89f935d..2038273 100644 (file)
@@ -289,7 +289,6 @@ class test_base(common.TransactionCase):
           {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend'},
           {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend'},
           {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper'},
-          {'name': 'Nab', 'login': 'nab', 'color': 2, 'function': '5$ Wrench'},
         ]:
           self.res_users.create(cr, uid, user_data)
 
@@ -299,14 +298,6 @@ class test_base(common.TransactionCase):
           self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
           self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
 
-        groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color'], groupby='name', orderby='name DESC, color asc')
-        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
-        self.assertEqual([user['name'] for user in groups_data], ['Eve', 'Bob', 'Alice'], 'Incorrect ordering of the list')
-
-        groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve', 'nab'))], fields=['function', 'color'], groupby='function', orderby='color ASC')
-        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
-        self.assertEqual(groups_data, sorted(groups_data, key=lambda x: x['color']), 'Incorrect ordering of the list')
-
 class test_partner_recursion(common.TransactionCase):
 
     def setUp(self):
index 6780996..d93734f 100644 (file)
@@ -417,61 +417,6 @@ class TestNoModel(common.TransactionCase):
             ET.tostring(sarch, encoding='utf-8'),
             ET.tostring(self.arch, encoding='utf-8'))
 
-class TestTemplating(common.TransactionCase):
-    def setUp(self):
-        import openerp.modules
-        super(TestTemplating, self).setUp()
-        self._pool = openerp.modules.registry.RegistryManager.get(common.DB)
-        self._init = self._pool._init
-        # fuck off
-        self._pool._init = False
-
-    def tearDown(self):
-        self._pool._init = self._init
-        super(TestTemplating, self).tearDown()
-
-    def test_branding_inherit(self):
-        Views = self.registry('ir.ui.view')
-        id = Views.create(self.cr, self.uid, {
-            'name': "Base view",
-            'type': 'qweb',
-            'arch': """<root>
-                <item order="1"/>
-            </root>
-            """
-        })
-        id2 = Views.create(self.cr, self.uid, {
-            'name': "Extension",
-            'type': 'qweb',
-            'inherit_id': id,
-            'arch': """<xpath expr="//item" position="before">
-                <item order="2"/>
-            </xpath>
-            """
-        })
-
-        arch_string = Views.read_combined(
-            self.cr, self.uid, id, fields=['arch'],
-            context={'inherit_branding': True})['arch']
-
-        arch = ET.fromstring(arch_string)
-        Views.distribute_branding(arch)
-
-        [initial] = arch.xpath('//item[@order=1]')
-        self.assertEqual(
-            str(id),
-            initial.get('data-oe-id'),
-            "initial should come from the root view")
-        self.assertEqual(
-            '/root[1]/item[1]',
-            initial.get('data-oe-xpath'),
-            "initial's xpath should be within the root view only")
-
-        [second] = arch.xpath('//item[@order=2]')
-        self.assertEqual(
-            str(id2),
-            second.get('data-oe-id'),
-            "second should come from the extension view")
 
 class test_views(common.TransactionCase):
 
index 478f982..190453d 100644 (file)
@@ -1461,9 +1461,11 @@ class property(function):
     def _get_by_id(self, obj, cr, uid, prop_name, ids, context=None):
         prop = obj.pool.get('ir.property')
         vids = [obj._name + ',' + str(oid) for oid in  ids]
-        domain = [('fields_id.model', '=', obj._name), ('fields_id.name', 'in', prop_name)]
-        if context and context.get('company_id'):
-            domain += [('company_id', '=', context.get('company_id'))]
+        def_id = self._field_get(cr, uid, obj._name, prop_name[0])
+        company = obj.pool.get('res.company')
+        cid = company._company_default_get(cr, uid, obj._name, def_id, context=context)
+        domain = [('fields_id.model', '=', obj._name), ('fields_id.name', 'in', prop_name), ('company_id', '=', cid)]
+        #domain = prop._get_domain(cr, uid, prop_name, obj._name, context)
         if vids:
             domain = [('res_id', 'in', vids)] + domain
         return prop.search(cr, uid, domain, context=context)
@@ -1473,12 +1475,7 @@ class property(function):
         if context is None:
             context = {}
 
-        def_id = self._field_get(cr, uid, obj._name, prop_name)
-        company = obj.pool.get('res.company')
-        cid = company._company_default_get(cr, uid, obj._name, def_id, context=context)
-        # TODO for trunk: add new parameter company_id to _get_by_id method
-        context_company = dict(context, company_id=cid)
-        nids = self._get_by_id(obj, cr, uid, [prop_name], [id], context_company)
+        nids = self._get_by_id(obj, cr, uid, [prop_name], [id], context)
         if nids:
             cr.execute('DELETE FROM ir_property WHERE id IN %s', (tuple(nids),))
 
@@ -1492,6 +1489,10 @@ class property(function):
             property_create = True
 
         if property_create:
+            def_id = self._field_get(cr, uid, obj._name, prop_name)
+            company = obj.pool.get('res.company')
+            cid = company._company_default_get(cr, uid, obj._name, def_id,
+                                               context=context)
             propdef = obj.pool.get('ir.model.fields').browse(cr, uid, def_id,
                                                              context=context)
             prop = obj.pool.get('ir.property')
index 268ba04..6ac6512 100644 (file)
@@ -770,6 +770,8 @@ class BaseModel(object):
                     (name_id, context['module'], 'ir.model', model_id)
                 )
 
+        cr.commit()
+
         cr.execute("SELECT * FROM ir_model_fields WHERE model=%s", (self._name,))
         cols = {}
         for rec in cr.dictfetchall():
@@ -836,6 +838,7 @@ class BaseModel(object):
                 for key, val in vals.items():
                     if cols[k][key] != vals[key]:
                         cr.execute('update ir_model_fields set field_description=%s where model=%s and name=%s', (vals['field_description'], vals['model'], vals['name']))
+                        cr.commit()
                         cr.execute("""UPDATE ir_model_fields SET
                             model_id=%s, field_description=%s, ttype=%s, relation=%s,
                             select_level=%s, readonly=%s ,required=%s, selectable=%s, relation_field=%s, translate=%s, serialization_field_id=%s
@@ -846,6 +849,7 @@ class BaseModel(object):
                                 vals['select_level'], bool(vals['readonly']), bool(vals['required']), bool(vals['selectable']), vals['relation_field'], bool(vals['translate']), vals['serialization_field_id'], vals['model'], vals['name']
                             ))
                         break
+        cr.commit()
 
     #
     # Goal: try to apply inheritance at the instanciation level and
@@ -2185,37 +2189,6 @@ class BaseModel(object):
                 r['__fold'] = folded.get(r[groupby] and r[groupby][0], False)
         return result
 
-    def _read_group_generate_order_by(self, orderby, aggregated_fields, groupby, query):
-        """
-        Generates the ORDER BY sql clause for the read group method. Adds the missing JOIN clause
-        to the query if order should be computed against m2o field. 
-        :param orderby: the orderby definition in the form "%(field)s %(order)s"
-        :param aggregated_fields: list of aggregated fields in the query
-        :param groupby: the current groupby field name
-        :param query: the query object used to construct the query afterwards
-        """
-        orderby_list = []
-        ob = []
-        for order_splits in orderby.split(','):
-            order_split = order_splits.split()
-            orderby_field = order_split[0]
-            fields = openerp.osv.fields
-            if isinstance(self._all_columns[orderby_field].column, (fields.date, fields.datetime)):
-                continue
-            orderby_dir = len(order_split) == 2 and order_split[1].upper() == 'ASC' and 'ASC' or 'DESC'
-            if orderby_field == groupby:
-                orderby_item = self._generate_order_by(order_splits, query).replace('ORDER BY ', '')
-                if orderby_item:
-                    orderby_list.append(orderby_item)
-                    ob += [obi.split()[0] for obi in orderby_item.split(',')]
-            elif orderby_field in aggregated_fields:
-                orderby_list.append('%s %s' % (orderby_field,orderby_dir))
-
-        if orderby_list:
-            return ' ORDER BY %s' % (','.join(orderby_list)), ob and ','.join(ob) or ''
-        else:
-            return '', ''
-
     def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
         """
         Get the list of records in list view grouped by the given ``groupby`` fields
@@ -2328,12 +2301,6 @@ class BaseModel(object):
             qualified_field = self._inherits_join_calc(f, query)
             flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
 
-        order = orderby or groupby
-        orderby_clause = ''
-        ob = ''
-        if order:
-            orderby_clause, ob = self._read_group_generate_order_by(order, aggregated_fields, groupby, query)
-
         gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
 
         from_clause, where_clause, where_clause_params = query.get_sql()
@@ -2342,21 +2309,20 @@ class BaseModel(object):
         offset_str = offset and ' offset %d' % offset or ''
         if len(groupby_list) < 2 and context.get('group_by_no_leaf'):
             group_count = '_'
-        cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + (ob and ',') + ob + orderby_clause + limit_str + offset_str, where_clause_params)
+        cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + limit_str + offset_str, where_clause_params)
         alldata = {}
         groupby = group_by
-
-        fetched_data = cr.dictfetchall()
-
-        data_ids = []
-        for r in fetched_data:
+        for r in cr.dictfetchall():
             for fld, val in r.items():
                 if val is None: r[fld] = False
             alldata[r['id']] = r
-            data_ids.append(r['id'])
             del r['id']
 
+        order = orderby or groupby
+        data_ids = self.search(cr, uid, [('id', 'in', alldata.keys())], order=order, context=context)
 
+        # the IDs of records that have groupby field value = False or '' should be included too
+        data_ids += set(alldata.keys()).difference(data_ids)
 
         if groupby:
             data = self.read(cr, uid, data_ids, [groupby], context=context)
@@ -2750,16 +2716,10 @@ class BaseModel(object):
                                 ('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
                             ]
                             if f_pg_type == 'varchar' and f._type == 'char' and ((f.size is None and f_pg_size) or f_pg_size < f.size):
-                                try:
-                                    with cr.savepoint():
-                                        cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s' % (self._table, k, pg_varchar(f.size)))
-                                except psycopg2.NotSupportedError:
-                                    # In place alter table cannot be done because a view is depending of this field.
-                                    # Do a manual copy. This will drop the view (that will be recreated later)
-                                    cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
-                                    cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size)))
-                                    cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size)))
-                                    cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
+                                cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
+                                cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size)))
+                                cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size)))
+                                cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
                                 cr.commit()
                                 _schema.debug("Table '%s': column '%s' (type varchar) changed size from %s to %s",
                                     self._table, k, f_pg_size or 'unlimited', f.size or 'unlimited')
@@ -2767,10 +2727,10 @@ class BaseModel(object):
                                 if (f_pg_type==c[0]) and (f._type==c[1]):
                                     if f_pg_type != f_obj_type:
                                         ok = True
-                                        cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO __temp_type_cast' % (self._table, k))
+                                        cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
                                         cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
-                                        cr.execute(('UPDATE "%s" SET "%s"= __temp_type_cast'+c[3]) % (self._table, k))
-                                        cr.execute('ALTER TABLE "%s" DROP COLUMN  __temp_type_cast CASCADE' % (self._table,))
+                                        cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k))
+                                        cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
                                         cr.commit()
                                         _schema.debug("Table '%s': column '%s' changed type from %s to %s",
                                             self._table, k, c[0], c[1])
@@ -4662,22 +4622,24 @@ class BaseModel(object):
 
         blacklist_given_fields(self)
 
-
-        fields_to_copy = dict((f,fi) for f, fi in self._all_columns.iteritems()
-                                     if f not in default
-                                     if f not in blacklist
-                                     if not isinstance(fi.column, fields.function))
-
-        data = self.read(cr, uid, [id], fields_to_copy.keys(), context=context)
+        fields_to_read = [f for f in self.check_field_access_rights(cr, uid, 'read', None)
+                          if f not in blacklist]
+        data = self.read(cr, uid, [id], fields_to_read, context=context)
         if data:
             data = data[0]
         else:
-            raise IndexError( _("Record #%d of %s not found, cannot copy!") %( id, self._name))
+            raise IndexError(_("Record #%d of %s not found, cannot copy!") % (id, self._name))
 
         res = dict(default)
-        for f, colinfo in fields_to_copy.iteritems():
+        for f, colinfo in self._all_columns.items():
             field = colinfo.column
-            if field._type == 'many2one':
+            if f in default:
+                pass
+            elif f in blacklist:
+                pass
+            elif isinstance(field, fields.function):
+                pass
+            elif field._type == 'many2one':
                 res[f] = data[f] and data[f][0]
             elif field._type == 'one2many':
                 other = self.pool[field._obj]
index adbd058..fa1bc13 100644 (file)
@@ -311,7 +311,7 @@ def exp_list(document=False):
                 cr.execute("select datname from pg_database where datdba=(select usesysid from pg_user where usename=%s) and datname not in %s order by datname", (db_user, templates_list))
             else:
                 cr.execute("select datname from pg_database where datname not in %s order by datname", (templates_list,))
-            res = [openerp.tools.ustr(name) for (name,) in cr.fetchall()]
+            res = [str(name) for (name,) in cr.fetchall()]
         except Exception:
             res = []
     res.sort()
index 694ae02..de9d21d 100644 (file)
@@ -3,7 +3,7 @@
 #
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#    Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+#    Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -27,11 +27,8 @@ the database, *not* a database abstraction toolkit. Database abstraction is what
 the ORM does, in fact.
 """
 
-from contextlib import contextmanager
 from functools import wraps
 import logging
-import time
-import uuid
 import psycopg2.extensions
 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_REPEATABLE_READ
 from psycopg2.pool import PoolError
@@ -347,19 +344,6 @@ class Cursor(object):
         """
         return self._cnx.rollback()
 
-    @contextmanager
-    @check
-    def savepoint(self):
-        """context manager entering in a new savepoint"""
-        name = uuid.uuid1().hex
-        self.execute('SAVEPOINT "%s"' % name)
-        try:
-            yield
-            self.execute('RELEASE SAVEPOINT "%s"' % name)
-        except:
-            self.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
-            raise
-
     @check
     def __getattr__(self, name):
         return getattr(self._obj, name)
index cb05861..774bbf4 100644 (file)
@@ -121,62 +121,4 @@ class TestRelatedField(common.TransactionCase):
         # restore res.partner fields
         self.partner._columns = old_columns
 
-
-class TestPropertyField(common.TransactionCase):
-
-    def setUp(self):
-        super(TestPropertyField, self).setUp()
-        self.user = self.registry('res.users')
-        self.partner = self.registry('res.partner')
-        self.company = self.registry('res.company')
-        self.country = self.registry('res.country')
-        self.property = self.registry('ir.property')
-        self.imd = self.registry('ir.model.data')
-
-    def test_1_property_multicompany(self):
-        cr, uid = self.cr, self.uid
-
-        parent_company_id = self.imd.get_object_reference(cr, uid, 'base', 'main_company')[1]
-        country_be = self.imd.get_object_reference(cr, uid, 'base', 'be')[1]
-        country_fr = self.imd.get_object_reference(cr, uid, 'base', 'fr')[1]
-        group_partner_manager = self.imd.get_object_reference(cr, uid, 'base', 'group_partner_manager')[1]
-        group_multi_company = self.imd.get_object_reference(cr, uid, 'base', 'group_multi_company')[1]
-
-        sub_company = self.company.create(cr, uid, {'name': 'MegaCorp', 'parent_id': parent_company_id})
-        alice = self.user.create(cr, uid, {'name': 'Alice',
-            'login':'alice',
-            'email':'alice@youcompany.com',
-            'company_id':parent_company_id,
-            'company_ids':[(6, 0, [parent_company_id, sub_company])],
-            'country_id':country_be,
-            'groups_id': [(6, 0, [group_partner_manager, group_multi_company])]
-        })
-        bob = self.user.create(cr, uid, {'name': 'Bob',
-            'login':'bob',
-            'email':'bob@megacorp.com',
-            'company_id':sub_company,
-            'company_ids':[(6, 0, [parent_company_id, sub_company])],
-            'country_id':country_fr,
-            'groups_id': [(6, 0, [group_partner_manager, group_multi_company])]
-        })
-        
-        self.partner._columns = dict(self.partner._columns)
-        self.partner._columns.update({
-            'property_country': fields.property(type='many2one', relation="res.country", string="Country by company"),
-        })
-        self.partner._all_columns.update({
-            'property_country': fields.column_info('property_country', self.partner._columns['property_country'], None, None, None),
-        })
-        self.partner._field_create(cr)
-
-        partner_id = self.partner.create(cr, alice, {
-            'name': 'An International Partner',
-            'email': 'partner@example.com',
-            'company_id': parent_company_id,
-        })
-        self.partner.write(cr, bob, [partner_id], {'property_country': country_fr})
-        self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Bob does not see the value he has set on the property field")
-
-        self.partner.write(cr, alice, [partner_id], {'property_country': country_be})
-        self.assertEqual(self.partner.browse(cr, alice, partner_id).property_country.id, country_be, "Alice does not see the value he has set on the property field")
-        self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Changes made by Alice have overwritten Bob's value")
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index 196ace2..5e5055f 100644 (file)
@@ -25,7 +25,7 @@ except ImportError:
     import StringIO
 
 from PIL import Image
-from PIL import ImageEnhance
+from PIL import ImageOps
 from random import randint
 
 # ----------------------------------------
@@ -81,13 +81,8 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
         return base64_source
 
     if image.size != size:
-        # create a thumbnail: will resize and keep ratios, then sharpen for better looking result
-        image.thumbnail(size, Image.ANTIALIAS)
-        sharpener = ImageEnhance.Sharpness(image.convert('RGBA'))
-        resized_image = sharpener.enhance(2.0)
-        # create a transparent image for background and paste the image on it
-        image = Image.new('RGBA', size, (255, 255, 255, 0))
-        image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
+        # If you need faster thumbnails you may use use Image.NEAREST
+        image = ImageOps.fit(image, size, Image.ANTIALIAS)
     if image.mode not in ["1", "L", "P", "RGB", "RGBA"]:
         image = image.convert("RGB")