[FIX] Merge last trunk
authorFabien Meghazi <fme@openerp.com>
Wed, 15 Feb 2012 09:59:40 +0000 (10:59 +0100)
committerFabien Meghazi <fme@openerp.com>
Wed, 15 Feb 2012 09:59:40 +0000 (10:59 +0100)
bzr revid: fme@openerp.com-20120215095940-2jv27t91i7u5mm0r

1  2 
addons/web/static/src/css/base.css
addons/web/static/src/js/view_form.js
addons/web/static/src/xml/base.xml

@@@ -1,9 -1,12 +1,12 @@@
- body { padding: 0; margin: 0; }
+ body.openerp {
+     padding: 0;
+     margin: 0;
+     overflow-y: scroll;
+ }
  .openerp {
      padding: 0;
      margin: 0;
      height: 100%;
-     overflow-y: scroll;
      font-size: 80%;
      font-family: Ubuntu, Helvetica, sans-serif;
  }
@@@ -340,7 -343,15 +343,15 @@@ table.db_option_table input.required 
      background-color: #D2D2FF !important;
  }
  
- .db_option_table input[type="text"], .db_option_table input[type="password"], .db_option_table select {
+ .db_option_table label {
+     display: block;
+     text-align: right;
+ }
+ .db_option_table input[type="text"],
+ .db_option_table input[type="password"],
+ .db_option_table input[type="file"],
+ .db_option_table select {
      width: 300px;
  }
  
@@@ -374,6 -385,14 +385,14 @@@ label.error 
      height: 100%;
  }
  
+ /* IE Hack - for IE < 9
+  * Avoids footer to be placed statically at 100% cutting the middle of the views
+  * */
+ .openerp .oe-application-container {
+     height: auto\9;
+     min-height: 100%\9;
+ }
  /* Menu */
  .openerp .menu {
      height: 34px;
  }
  .openerp .filter_label.enabled, .openerp .filter_icon.enabled {
      background: #aaa;
+     filter: none;
      -moz-box-shadow: none;
      -webkit-box-shadow: none;
      -o-box-shadow: none;
  
  
  /* Form */
 -
 +.openerp .oe_form_button_save_dirty {
 +    display: none;
 +}
 +.openerp .oe_form_dirty > .oe_form_header > .oe_form_buttons > .oe_form_button_save {
 +    font-weight: bold;
 +}
 +.openerp .oe_form_dirty > .oe_form_header > .oe_form_buttons > .oe_form_button_save > .oe_form_button_save_dirty {
 +    display: inline;
 +    font-weight: bold;
 +    font-size: 80%;
 +    position: relative;
 +    bottom: 0.4em;
 +}
  .openerp .oe_form_frame_cell input[type="checkbox"] {
      margin-top: 3px;
      vertical-align: middle;
  .openerp td.oe_form_frame_cell {
      padding: 2px;
      position: relative;
+ }
+ .openerp td.oe_form_field_translatable,
+ .openerp td.oe_form_field_many2one,
+ .openerp td.oe_form_field_date,
+ .openerp td.oe_form_field_datetime {
      white-space: nowrap;
  }
  .openerp td.oe_form_field_boolean {
  }
  
  
- .openerp label.oe_label_help, .openerp label.oe_label, .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .oe_button, .openerp .oe_forms textarea {
+ .openerp label.oe_label_help, .openerp label.oe_label,
+ .openerp .oe_form_paragraph,
+ .openerp .oe_form_field_statusbar,
+ .openerp .oe_forms input[type="text"],
+ .openerp .oe_forms input[type="password"],
+ .openerp .oe_forms input[type="file"],
+ .openerp .oe_forms select,
+ .openerp .oe_forms .oe_button,
+ .openerp .oe_forms textarea {
      font-size: 85%;
  }
  
      white-space: normal;
  }
  
+ .openerp .oe_forms .oe_form_paragraph.oe_multilines {
+     white-space: pre;
+ }
  .openerp .oe_form_field_one2many .oe-actions h3.oe_view_title,
  .openerp .oe_form_field_one2many_list .oe-actions h3.oe_view_title{
      display: inline;
      margin: 0 0.5em 0 0;
  }
  
+ .openerp .oe_forms .oe-listview th.oe-sortable .ui-icon,
+ .openerp .oe_forms .oe-listview th.oe-sortable .ui-icon {
+     height: 100%;
+     margin-top: -9px;
+ }
+ .openerp table.oe_frame .oe-listview-content td {
+     color: inherit;
+ }
  /* Uneditable Form View */
  .openerp .oe_form_readonly {
  
      min-height:100px;
  }
  /* Inputs */
- .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms textarea {
+ .openerp .oe_forms input[type="text"],
+ .openerp .oe_forms input[type="password"],
+ .openerp .oe_forms input[type="file"],
+ .openerp .oe_forms select,
+ .openerp .oe_forms textarea {
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
      -ms-box-sizing: border-box;
  .openerp .oe_forms select{
      padding-top: 2px;
  }
+ .openerp .oe_forms input[readonly],
+ .openerp .oe_forms select[readonly],
+ .openerp .oe_forms textarea[readonly],
  .openerp .oe_forms input[disabled],
  .openerp .oe_forms select[disabled],
  .openerp .oe_forms textarea[disabled]{
-     background: #E0E0E0;
+     background: #E5E5E5 !important;
+     color: #666;
  }
  .openerp .oe_forms textarea {
      resize:vertical;
  }
- .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .oe_button {
+ .openerp .oe_forms input[type="text"],
+ .openerp .oe_forms input[type="password"],
+ .openerp .oe_forms input[type="file"],
+ .openerp .oe_forms select,
+ .openerp .oe_forms .oe_button {
      height: 22px;
  }
  
      min-width: 100%;
      width: 100%;
  }
- .openerp .oe_forms .button {
-     height: 22px;
- }
  @-moz-document url-prefix() {
      /* Strange firefox behaviour on width: 100% + white-space: nowrap */
      .openerp .oe_forms .oe_form_button .oe_button {
          width: auto;
      }
  }
+ /* IE Hack - for IE < 9
+  * Avoids buttons overflow
+  * */
+ .openerp .oe_forms .oe_form_button .oe_button {
+     min-width: auto\9;
+ }
+ .openerp .oe_forms .button {
+     height: 22px;
+ }
  .openerp .oe_forms .oe_button span {
      position: relative;
      vertical-align: top;
      position: absolute;
      /* Should be adjusted for all browsers */
      top: -2px;
-     left: -700px;
+     right: 0;
      opacity: 0;
      filter: alpha(opacity = 0);
      -ms-filter: "alpha(opacity=0)";
      width: 100%;
      background-color : #FFFFFF;
      border-spacing: 0;
+     
  }
  .openerp .oe-treeview-table tr:hover{
      color: blue;
      text-align: left;
      border-bottom: 1px solid #CFCCCC;
  }
- .oe-number{
+ .openerp .oe-treeview-table .oe-number {
     text-align: right !important;
  }
  .treeview-tr span, .treeview-td span {
      white-space: nowrap;
      display: block;
      }
- .treeview-tr:first-of-type {
+ .treeview-tr.oe-treeview-first {
      background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
  }
- .oe-open .treeview-tr:first-of-type {
+ .oe-open .treeview-tr.oe-treeview-first {
      background-image: url(/web/static/src/img/collapse.gif);
  }
- .treeview-tr:first-of-type span,
- .treeview-td:first-of-type span {
+ .treeview-tr.oe-treeview-first span,
+ .treeview-td.oe-treeview-first span {
      margin-left: 16px;
  }
  
@@@ -2012,34 -2066,31 +2078,31 @@@ ul.oe-arrow-list li.oe-arrow-list-selec
      border-bottom-right-radius: 3px;
  }
  .openerp .oe_view_editor {
-     border-collapse: collapse;
-     padding: 0;
-     align: left;
+     width:100%;
+     border-collapse : collapse;
+     margin-left: -12px;
+     
      width: 100%;
+     background-color : white;
+     border-spacing: 0;
  }
- .openerp .oe_view_editor_colum{
+ .openerp .oe_view_editor td{
+     text-align: center;
+     white-space: nowrap;
+     border: 1px solid #D8D8D8;
+     
+     cursor: pointer;
      font-size: 90%;
-     font-weight: normal;
-     padding: 0;
-     border-bottom: 1px solid #CFCCCC;
  }
- .openerp .oe_view_editor_row:hover {
-     background-color: #F3F3F3;
+ .openerp .oe_view_editor_field td{
+     border: 0px !important;
  }
  
- .openerp .oe_view_editor_tree_grid{
-     text-align: left;
-     white-space: nowrap;
-     border-collapse: collapse;
-     width: 100%;
- }
- .openerp .oe_view_editor_tree_grid a:hover {
-     color: blue;
- }
- .openerp .oe_view_editor_tree_grid a {
-     display: block;
+ .openerp .oe_view_editor tr:hover {
+     background-color: #ecebf2;
  }
  
  /* Dialog traceback cases */
  .openerp .oe_error_detail{
      display: block;
@@@ -117,18 -117,28 +117,28 @@@ openerp.web.FormView = openerp.web.View
              this.sidebar.attachments = new openerp.web.form.SidebarAttachments(this.sidebar, this);
              this.sidebar.add_toolbar(this.fields_view.toolbar);
              this.set_common_sidebar_sections(this.sidebar);
+             this.sidebar.add_section(_t('Customize'), 'customize');
+             this.sidebar.add_items('customize', [{
+                 label: _t('Set Default'),
+                 form: this,
+                 callback: function (item) {
+                     item.form.open_defaults_dialog();
+                 }
+             }]);
          }
          this.has_been_loaded.resolve();
      },
  
-     do_load_state: function(state) {
+     do_load_state: function(state, warm) {
          if (state.id && this.datarecord.id != state.id) {
-             var idx = this.dataset.get_id_index(state.id);
-             if (idx === null) {
+             if (!this.dataset.get_id_index(state.id)) {
                  this.dataset.ids.push(state.id);
-                 this.dataset.index = this.dataset.ids.length - 1;
              }
-             this.do_show();
+             this.dataset.select_id(state.id);
+             if (warm) {
+                 this.do_show();
+             }
          }
      },
  
      on_record_loaded: function(record) {
          var self = this, set_values = [];
          if (!record) {
-             throw new Error("Form: No record received");
+             this.do_warn("Form", "The record could not be found in the database.", true);
+             return $.Deferred().reject();
          }
          this.datarecord = record;
  
              if (record.id) {
                  self.do_push_state({id:record.id});
              }
 +            self.$element.removeClass('oe_form_dirty');
          });
      },
 -    on_form_changed: function() {
 +    on_form_changed: function(changed_by_user) {
 +        if (changed_by_user) {
 +            this.$element.addClass('oe_form_dirty');
 +        }
          for (var w in this.widgets) {
              w = this.widgets[w];
              w.process_modifiers();
          var self = this;
          return this.on_change_mutex.exec(function() {
              try {
+                 var response = {}, can_process_onchange = $.Deferred();
                  processed = processed || [];
+                 processed.push(widget.name);
                  var on_change = widget.node.attrs.on_change;
                  if (on_change) {
                      var change_spec = self.parse_on_change(on_change, widget);
                              url: '/web/dataset/onchange',
                              async: false
                          };
-                         return self.rpc(ajax, {
+                         can_process_onchange = self.rpc(ajax, {
                              model: self.dataset.model,
                              method: change_spec.method,
                              args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args),
                              context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1
-                         }).pipe(function(response) {
-                             return self.on_processed_onchange(response, processed);
+                         }).then(function(r) {
+                             _.extend(response, r);
                          });
                      } else {
                          console.warn("Wrong on_change format", on_change);
                      }
                  }
+                 // fail if onchange failed
+                 if (can_process_onchange.isRejected()) {
+                     return can_process_onchange;
+                 }
+                 if (widget.field['change_default']) {
+                     var fieldname = widget.name, value;
+                     if (response.value && (fieldname in response.value)) {
+                         // Use value from onchange if onchange executed
+                         value = response.value[fieldname];
+                     } else {
+                         // otherwise get form value for field
+                         value = self.fields[fieldname].get_on_change_value();
+                     }
+                     var condition = fieldname + '=' + value;
+                     if (value) {
+                         can_process_onchange = self.rpc({
+                             url: '/web/dataset/call',
+                             async: false
+                         }, {
+                             model: 'ir.values',
+                             method: 'get_defaults',
+                             args: [self.model, condition]
+                         }).then(function (results) {
+                             if (!results.length) { return; }
+                             if (!response.value) {
+                                 response.value = {};
+                             }
+                             for(var i=0; i<results.length; ++i) {
+                                 // [whatever, key, value]
+                                 var triplet = results[i];
+                                 response.value[triplet[1]] = triplet[2];
+                             }
+                         });
+                     }
+                 }
+                 if (can_process_onchange.isRejected()) {
+                     return can_process_onchange;
+                 }
+                 return self.on_processed_onchange(response, processed);
              } catch(e) {
                  console.error(e);
                  return $.Deferred().reject();
                  // If field is not defined in the view, just ignore it
                  if (field) {
                      var value = result.value[f];
                      if (field.get_value() != value) {
                          field.set_value(value);
                          field.dirty = true;
-                         if (_.indexOf(processed, field.name) < 0) {
+                         if (!_.contains(processed, field.name)) {
                              this.do_onchange(field, processed);
                          }
                      }
          } else {
              this.datarecord.id = r.result;
              if (!prepend_on_create) {
-                 this.dataset.ids.push(this.datarecord.id);
+                 this.dataset.alter_ids(this.dataset.ids.concat([this.datarecord.id]));
                  this.dataset.index = this.dataset.ids.length - 1;
              } else {
-                 this.dataset.ids.unshift(this.datarecord.id);
+               this.dataset.alter_ids([this.datarecord.id].concat(this.dataset.ids));
                  this.dataset.index = 0;
              }
              this.do_update_pager();
      },
      sidebar_context: function () {
          return this.do_save().pipe(_.bind(function() {return this.get_fields_values();}, this));
+     },
+     open_defaults_dialog: function () {
+         var self = this;
+         var fields = _.chain(this.fields)
+             .map(function (field, name) {
+                 var value = field.get_value();
+                 // ignore fields which are empty, invisible, readonly, o2m
+                 // or m2m
+                 if (!value
+                         || field.invisible
+                         || field.readonly
+                         || field.field.type === 'one2many'
+                         || field.field.type === 'many2many') {
+                     return false;
+                 }
+                 var displayed;
+                 switch(field.field.type) {
+                 case 'selection':
+                     displayed = _(field.values).find(function (option) {
+                             return option[0] === value;
+                         })[1];
+                     break;
+                 case 'many2one':
+                     displayed = field.value[1] || value;
+                     break;
+                 default:
+                     displayed = value;
+                 }
+                 return {
+                     name: name,
+                     string: field.string,
+                     value: value,
+                     displayed: displayed,
+                     // convert undefined to false
+                     change_default: !!field.field.change_default
+                 }
+             })
+             .compact()
+             .sortBy(function (field) { return field.string; })
+             .value();
+         var conditions = _.chain(fields)
+             .filter(function (field) { return field.change_default; })
+             .value();
+         var d = new openerp.web.Dialog(this, {
+             title: _t("Set Default"),
+             args: {
+                 fields: fields,
+                 conditions: conditions
+             },
+             buttons: [
+                 {text: _t("Close"), click: function () { d.close(); }},
+                 {text: _t("Save default"), click: function () {
+                     var $defaults = d.$element.find('#formview_default_fields');
+                     var field_to_set = $defaults.val();
+                     if (!field_to_set) {
+                         $defaults.parent().addClass('invalid');
+                         return;
+                     }
+                     var condition = d.$element.find('#formview_default_conditions').val(),
+                         all_users = d.$element.find('#formview_default_all').is(':checked');
+                     new openerp.web.DataSet(self, 'ir.values').call(
+                         'set_default', [
+                             self.dataset.model,
+                             field_to_set,
+                             self.fields[field_to_set].get_value(),
+                             all_users,
+                             false,
+                             condition || false
+                     ]).then(function () { d.close(); });
+                 }}
+             ]
+         });
+         d.template = 'FormView.set_default';
+         d.open();
      }
  });
  openerp.web.FormDialog = openerp.web.Dialog.extend({
@@@ -692,13 -818,17 +822,17 @@@ openerp.web.form.compute_domain = funct
                      stack.push(!top);
                      continue;
                  default:
-                     throw new Error('Unknown domain operator ' + ex);
+                     throw new Error(_.str.sprintf(
+                         _t("Unknown operator %s in domain %s"),
+                         ex, JSON.stringify(expr)));
              }
          }
  
          var field = fields[ex[0]];
          if (!field) {
-             throw new Error("Domain references unknown field : " + ex[0]);
+             throw new Error(_.str.sprintf(
+                 _t("Unknown field %s in domain %s"),
+                 ex[0], JSON.stringify(expr)));
          }
          var field_value = field.get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
          var op = ex[1];
                  stack.push(!_(val).contains(field_value));
                  break;
              default:
-                 console.warn("Unsupported operator in modifiers :", op);
+                 console.warn(
+                     _t("Unsupported operator %s in domain %s"),
+                     op, JSON.stringify(expr));
          }
      }
      return _.all(stack, _.identity);
@@@ -790,7 -922,7 +926,7 @@@ openerp.web.form.Widget = openerp.web.O
      },
      stop: function() {
          this._super.apply(this, arguments);
-         $('div.tipsy').stop().remove();
+         $.fn.tipsy.clear();
      },
      process_modifiers: function() {
          var compute_domain = openerp.web.form.compute_domain;
                          debug: openerp.connection.debug,
                          widget: widget
                  })},
-                 gravity: $.fn.tipsy.autoNS,
+                 gravity: $.fn.tipsy.autoBounds(50, 'nw'),
                  html: true,
                  opacity: 0.85,
                  trigger: 'hover'
@@@ -1151,6 -1283,11 +1287,11 @@@ openerp.web.form.WidgetLabel = openerp.
  
          this._super(view, node);
  
+         if (this.node.tag == 'label' && !this.string && this.node.children.length) {
+             this.string = this.node.children[0];
+             this.align = 'left';
+         }
          if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) {
              this.template = "WidgetParagraph";
              this.colspan = parseInt(this.node.attrs.colspan || 1, 10);
              if (isNaN(parseFloat(this.node.attrs.align))) {
                  this.align = 'left';
              }
+             this.multilines = this.string && _.str.lines(this.string).length > 1;
          } else {
              this.colspan = 1;
              this.width = '1%';
@@@ -1222,6 -1361,7 +1365,7 @@@ openerp.web.form.Field = openerp.web.fo
          this._super.apply(this, arguments);
          if (this.field.translate) {
              this.view.translatable_fields.push(this);
+             this.$element.addClass('oe_form_field_translatable');
              this.$element.find('.oe_field_translate').click(this.on_translate);
          }
          if (this.nolabel && openerp.connection.debug) {
          if (this.is_valid()) {
              this.set_value_from_ui();
              this.view.do_onchange(this);
 -            this.view.on_form_changed();
 +            this.view.on_form_changed(true);
          } else {
              this.update_dom(true);
          }
@@@ -1318,7 -1458,7 +1462,7 @@@ openerp.web.form.FieldChar = openerp.we
      },
      update_dom: function() {
          this._super.apply(this, arguments);
-         this.$element.find('input').prop('disabled', this.readonly);
+         this.$element.find('input').prop('readonly', this.readonly);
      },
      set_value_from_ui: function() {
          this.value = openerp.web.parse_value(this.$element.find('input').val(), this);
  openerp.web.form.FieldID = openerp.web.form.FieldChar.extend({
      update_dom: function() {
          this._super.apply(this, arguments);
-         this.$element.find('input').prop('disabled', true);
+         this.$element.find('input').prop('readonly', true);
      }
  });
  
@@@ -1419,7 -1559,7 +1563,7 @@@ openerp.web.DateTimeWidget = openerp.we
              showButtonPanel: true
          });
          this.$element.find('img.oe_datepicker_trigger').click(function() {
-             if (!self.readonly) {
+             if (!self.readonly && !self.picker('widget').is(':visible')) {
                  self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
                  self.$input_picker.show();
                  self.picker('show');
      },
      set_readonly: function(readonly) {
          this.readonly = readonly;
-         this.$input.prop('disabled', this.readonly);
+         this.$input.prop('readonly', this.readonly);
          this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
      },
      is_valid: function(required) {
@@@ -1538,7 -1678,7 +1682,7 @@@ openerp.web.form.FieldText = openerp.we
      },
      update_dom: function() {
          this._super.apply(this, arguments);
-         this.$element.find('textarea').prop('disabled', this.readonly);
+         this.$element.find('textarea').prop('readonly', this.readonly);
      },
      set_value_from_ui: function() {
          this.value = openerp.web.parse_value(this.$element.find('textarea').val(), this);
@@@ -1896,7 -2036,12 +2040,12 @@@ openerp.web.form.FieldMany2One = opener
              self.last_search = data;
              // possible selections for the m2o
              var values = _.map(data, function(x) {
-                 return {label: $('<span />').text(x[1]).html(), name:x[1], id:x[0]};
+                 return {
+                     label: _.str.escapeHTML(x[1]),
+                     value:x[1],
+                     name:x[1],
+                     id:x[0]
+                 };
              });
  
              // search more... if more results that max
      },
      update_dom: function() {
          this._super.apply(this, arguments);
-         this.$input.prop('disabled', this.readonly);
+         this.$input.prop('readonly', this.readonly);
      }
  });
  
@@@ -2172,7 -2317,7 +2321,7 @@@ openerp.web.form.FieldOne2Many = opener
  
          this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, {});
          this.viewmanager.template = 'One2Many.viewmanager';
-         this.viewmanager.registry = openerp.web.views.clone({
+         this.viewmanager.registry = openerp.web.views.extend({
              list: 'openerp.web.form.One2ManyListView',
              form: 'openerp.web.form.One2ManyFormView',
              page: 'openerp.web.PageView'
                          obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix);
                          obj.defaults = {};
                          self.dataset.to_create.push(obj);
-                         self.dataset.cache.push(_.clone(obj));
+                         self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
                          ids.push(obj.id);
                          return;
                      case commands.UPDATE:
                          obj['id'] = command[1];
                          self.dataset.to_write.push(obj);
-                         self.dataset.cache.push(_.clone(obj));
+                         self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
                          ids.push(obj.id);
                          return;
                      case commands.DELETE:
@@@ -2689,7 -2834,7 +2838,7 @@@ openerp.web.form.SelectCreatePopup = op
                      contexts, groupbys);
                  self.initial_ids = undefined;
              } else {
-                 self.do_search(domains.concat([self.domain]), contexts, groupbys);
+                 self.do_search(domains.concat([self.domain]), contexts.concat(self.context), groupbys);
              }
          });
          this.searchview.on_loaded.add_last(function () {
@@@ -3046,10 -3191,19 +3195,19 @@@ openerp.web.form.FieldBinary = openerp.
      on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
      },
      on_save_as: function() {
-         var url = '/web/binary/saveas?session_id=' + this.session.session_id + '&model=' +
-             this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name +
-             '&filename_field=' + (this.node.attrs.filename || '') + '&t=' + (new Date().getTime());
-         window.open(url);
+         $.blockUI();
+         this.session.get_file({
+             url: '/web/binary/saveas_ajax',
+             data: {data: JSON.stringify({
+                 model: this.view.dataset.model,
+                 id: (this.view.datarecord.id || ''),
+                 field: this.name,
+                 filename_field: (this.node.attrs.filename || ''),
+                 context: this.view.dataset.get_context()
+             })},
+             complete: $.unblockUI,
+             error: openerp.webclient.crashmanager.on_rpc_error
+         });
      },
      on_clear: function() {
          if (this.value !== false) {
@@@ -3066,7 -3220,7 +3224,7 @@@ openerp.web.form.FieldBinaryFile = open
      update_dom: function() {
          this._super.apply(this, arguments);
          this.$element.find('.oe-binary-file-set, .oe-binary-file-clear').toggle(!this.readonly);
-         this.$element.find('input[type=text]').prop('disabled', this.readonly);
+         this.$element.find('input[type=text]').prop('readonly', this.readonly);
      },
      set_value: function(value) {
          this._super.apply(this, arguments);
@@@ -3,7 -3,7 +3,7 @@@
  -->
  <templates id="template" xml:space="preserve">
  <t t-name="Notification">
-     <div class="oe_notification">
+     <div class="oe_notification" t-translation="off">
          <div id="oe_notification_default">
              <a class="ui-notify-cross ui-notify-close" href="#">x</a>
              <h1>#{title}</h1>
                              <option t-att-value="db"><t t-esc="db"/></option>
                          </t>
                      </select>
+                     <input t-if="!db_list" name="drop_db" class="required"
+                            type="text" autofocus="autofocus"/>
                  </td>
              </tr>
              <tr>
                              <option t-att-value="db"><t t-esc="db"/></option>
                          </t>
                      </select>
+                     <input t-if="!db_list" name="drop_db" class="required"
+                            type="text" autofocus="autofocus"/>
                  </td>
              </tr>
              <tr>
  </t>
  <t t-name="Menu.secondary">
      <div t-attf-class="oe_toggle_secondary_menu">
-         <span class="oe_menu_fold" title="Fold menu">&amp;laquo;</span>
-         <span class="oe_menu_unfold" title="Unfold menu">&amp;raquo;</span>
+         <span class="oe_menu_fold" title="Fold menu"><t t-raw="'&amp;laquo;'"/></span>
+         <span class="oe_menu_unfold" title="Unfold menu"><t t-raw="'&amp;raquo;'"/></span>
      </div>
      <div t-foreach="widget.data.data.children" t-as="menu" style="display: none" class="oe_secondary_menu" t-att-data-menu-parent="menu.id">
          <t t-foreach="menu.children" t-as="menu">
-             <t t-set="classname">oe_secondary_menu_item</t>
+             <t t-set="classname" t-translation="off">oe_secondary_menu_item</t>
              <t t-set="level" t-value="0"/>
              <t t-call="Menu.secondary.children"/>
          </t>
      </a>
      <div t-attf-class="oe_secondary_submenu" t-if="menu.children.length" t-att-style="menu_first and level == 1 ? undefined : 'display: none'">
          <t t-foreach="menu.children" t-as="menu">
-             <t t-set="classname">oe_secondary_submenu_item</t>
+             <t t-set="classname" t-translation="off">oe_secondary_submenu_item</t>
              <t t-call="Menu.secondary.children"/>
          </t>
      </div>
                  <div class="oe_vm_switch">
                      <t t-if="views.length != 1" t-foreach="views" t-as="view">
  
-                         <button type="button" t-attf-class="oe_vm_switch_#{view.view_type}" t-att-data-view-type="view.view_type" t-att-title="view.view_type">
+                         <button type="button" t-attf-class="oe_vm_switch_#{view.view_type}" t-att-data-view-type="view.view_type" t-att-title="view.label || view.view_type">
                              <span><t t-esc="view.label || view.view_type"/></span>
                          </button>
                      </t>
          <option t-if="view_manager.searchview" value="edit" data-model="ir.ui.view" t-att-data-id="view_manager.searchview.view_id">Edit SearchView</option>
          <option t-if="view_manager.action" value="edit" t-att-data-model="view_manager.action.type" t-att-data-id="view_manager.action.id">Edit Action</option>
          <option value="edit_workflow">Edit Workflow</option>
-         <option value="customize_object">Customize Object</option>
      </t>
  </t>
  <t t-name="ViewManagerDebugViewLog">
      </div>
  </t>
  <t t-name="Sidebar.section.items">
-             <li t-foreach="items" t-as="item" t-att-class="item.classname">
-                 <a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#">
-                     <t t-esc="item.label"/>
-                 </a>
-             </li>
+     <li t-foreach="items" t-as="item" t-att-class="item.classname">
+         <a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#">
+             <t t-esc="item.label"/>
+         </a>
+     </li>
  </t>
  
  <t t-name="TranslateDialog">
          t-att-data-id="record.id" t-att-data-level="level + 1">
      <t t-set="children" t-value="record[children_field]"/>
      <t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
+     <t t-set="rank" t-value="'oe-treeview-first'"/>
      <t t-set="style" t-value="'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px;'"/>
  
      <td t-foreach="fields_view" t-as="field"
          t-if="!field.attrs.modifiers.tree_invisible"
          t-att-data-id="record.id"
          t-att-style="color_for(record) + style "
-         t-att-class="(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer')
-                     ? (class +' ' +'oe-number') : class">
+         t-attf-class="#{class} #{rank} #{(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer') ? 'oe-number' : ''}">
  
          <span t-if="!field.attrs.modifiers.invisible" >
              <t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
          </span>
  
          <t t-set="class" t-value="'treeview-td'"/>
+         <t t-set="rank" t-value="''"/>
          <t t-set="style" t-value="''"/>
      </td>
  </tr>
  
      <t t-jquery="td.oe-actions">
          this.removeAttr('t-if');
-         var $title = $(document.createElement('h3')).addClass('oe_view_title');
-         $title.append($(document.createElement('t')).attr(
-             't-esc', 'fields_view.arch.attrs.string'));
-         this.prepend($title);
+     </t>
+     <t t-jquery="td.oe-actions" t-operation="prepend">
+         <h3 class="oe_view_title"><t t-esc="fields_view.arch.attrs.string"/></h3>
      </t>
  </t>
  <th t-name="Listview.navigation.button" t-if="!no_leaf and options.pager !== false"
  <t t-name="FormView">
      <div class="oe_form_header">
          <div class="oe_form_buttons" t-if="widget.options.action_buttons !== false">
 -            <button type="button" class="oe_button oe_form_button_save">Save</button>
 +            <button type="button" class="oe_button oe_form_button_save">
 +                Save
 +                <span class="oe_form_button_save_dirty">(*)</span>
 +            </button>
              <button type="button" class="oe_button oe_form_button_cancel">Cancel</button>
          </div>
          <div class="oe_form_pager" t-if="widget.options.pager !== false">
          </li>
      </ul>
  </t>
+ <form t-name="FormView.set_default" class="oe_forms oe_frame">
+     <t t-set="args" t-value="widget.dialog_options.args"/>
+     <table style="width: 100%">
+         <tr>
+             <td>
+                 <label for="formview_default_fields"
+                        class="oe_label oe_align_right">
+                     Default:
+                 </label>
+             </td>
+             <td class="required">
+                 <select id="formview_default_fields">
+                     <option value=""/>
+                     <option t-foreach="args.fields" t-as="field"
+                             t-att-value="field.name">
+                         <t t-esc="field.string"/> = <t t-esc="field.displayed"/>
+                     </option>
+                 </select>
+             </td>
+         </tr>
+         <tr t-if="args.conditions.length">
+             <td>
+                 <label for="formview_default_conditions"
+                        class="oe_label oe_align_right">
+                     Condition:
+                 </label>
+             </td>
+             <td>
+                 <select id="formview_default_conditions">
+                     <option value=""/>
+                     <option t-foreach="args.conditions" t-as="cond"
+                             t-att-value="cond.name + '=' + cond.value">
+                         <t t-esc="cond.string"/>=<t t-esc="cond.displayed"/>
+                     </option>
+                 </select>
+             </td>
+         </tr>
+         <tr>
+             <td colspan="2">
+                 <input type="radio" id="formview_default_self"
+                        value="self" name="scope" checked="checked"/>
+                 <label for="formview_default_self" class="oe_label"
+                        style="display: inline;">
+                     Only you
+                 </label>
+                 <br/>
+                 <input type="radio" id="formview_default_all"
+                        value="all" name="scope"/>
+                 <label for="formview_default_all" class="oe_label"
+                        style="display: inline;">
+                     All users
+                 </label>
+             </td>
+         </tr>
+     </table>
+ </form>
  <t t-name="Widget">
      Unhandled widget
      <t t-js="dict">console.warn('Unhandled widget', dict.widget);</t>
              <span class="oe_tooltip_technical_title">Modifiers:</span>
              <t t-esc="widget.node.attrs.modifiers"/>
          </li>
+         <li t-if="widget.field and widget.field.change_default" data-item="change_default">
+             <span class="oe_tooltip_technical_title">Change default:</span>
+             Yes
+         </li>
          <li t-if="widget.node.attrs.on_change" data-item="on_change">
              <span class="oe_tooltip_technical_title">On change:</span>
              <t t-esc="widget.node.attrs.on_change"/>
      </ul>
  </t>
  <t t-name="WidgetParagraph">
-     <p t-attf-class="oe_form_paragraph oe_align_#{widget.align}"><t t-esc="widget.string"/></p>
+     <p t-attf-class="oe_form_paragraph oe_align_#{widget.align} #{widget.multilines ? 'oe_multilines' : ''}"><t t-esc="widget.string"/></p>
  </t>
  <t t-name="FieldChar">
      <input t-att-type="widget.password ? 'password' : 'text'" size="1"
  </t>
  <t t-name="FieldURI.readonly">
      <div>
-         <a href="#" class="oe_form_uri">#</a>
+         <a href="#" class="oe_form_uri"/>
      </div>
  </t>
  <t t-name="FieldEmail">
      <option class="oe-filters-title" value="">Filters</option>
      <optgroup label="-- Filters --">
          <t t-foreach="filters" t-as="filter">
-             <option t-attf-value="get:#{filter_index}"><t t-esc="filter.name"/></option>
+             <option t-attf-value="get:#{filter_index}"
+                     t-att-disabled="filter.disabled and 'disabled'"
+                     t-att-title="filter.disabled and disabled_filter_message">
+                 <t t-esc="filter.name"/>
+             </option>
          </t>
      </optgroup>
      <optgroup label="-- Actions --">
          <span t-if="attrs.help">?</span>
      </label>
      <div t-att-style="style">
-         <span t-att-id="element_id"></span>
+         <span t-att-id="element_id"/>
          <t t-if="filters.length" t-raw="filters.render(defaults)"/>
      </div>
  </t>
              <t t-foreach="attrs.selection" t-as="option">
                  <t t-set="selected" t-value="defaults[attrs.name] === option[0]"/>
                  <option t-if="selected"
-                         t-att-value="option_index" selected="selected">
+                         t-attf-selected="selected"
+                         t-att-value="option_index">
                      <t t-esc="option[1]"/>
                  </option>
                  <option t-if="!selected" t-att-value="option_index">
      </table>
  </t>
  <t t-name="view_editor.row">
-     <tr  class="oe_view_editor_row" t-att-id="'viewedit-' + rec.id"  t-att-level="rec.level" t-foreach="data" t-as="rec">
-         <td class="oe_view_editor_colum"  width="85%">
-             <table class="oe_view_editor_tree_grid">
+     <tr  t-att-id="'viewedit-' + rec.id"  t-att-level="rec.level" t-foreach="data" t-as="rec">
+         <td width="90%">
+             <table class="oe_view_editor_field">
                  <tr>
                      <td width="16px" t-att-style="'background-position: ' + 20*rec.level + 'px; padding-left: ' + 20*rec.level + 'px'">
                          <img t-if="rec.child_id.length" t-att-id="'parentimg-' + rec.id"
                  </tr>
              </table>
          </td>
-         <td align="left" class="oe_view_editor_colum"  width="15%">
-             <table width="100%">
-                 <tr>
-                     <td width="20%">
-                         <img t-if="rec.att_list.length"
-                             id="side-add" src="/web/static/src/img/icons/gtk-add.png" style="cursor: pointer;"/>
-                     </td>
-                     <td width="20%">
-                         <img  id="side-remove" src="/web/static/src/img/icons/gtk-remove.png" style="cursor: pointer;"/>
-                     </td>
-                     <td width="20%">
-                         <img t-if="rec.att_list.length and !_.include(no_properties, rec.att_list[0])"
-                             id="side-edit" src="/web/static/src/img/icons/gtk-edit.png" style="cursor: pointer;"/>
-                     </td>
-                     <td width="20%">
-                         <img t-if="rec.att_list.length"
-                             id="side-up" src="/web/static/src/img/icons/gtk-go-up.png" style="cursor: pointer;"/>
-                     </td>
-                     <td width="20%">
-                         <img t-if="rec.att_list.length"
-                             id="side-down" src="/web/static/src/img/icons/gtk-go-down.png" style="cursor: pointer;"/>
-                     </td>
-                 </tr>
-             </table>
+         <td width="2%">
+             <img t-if="rec.att_list.length"
+                 id="side-add" src="/web/static/src/img/icons/gtk-add.png" style="cursor: pointer;"/>
+         </td>
+         <td width="2%">
+             <img  id="side-remove" src="/web/static/src/img/icons/gtk-remove.png" style="cursor: pointer;"/>
+         </td>
+         <td width="2%">
+             <img t-if="rec.att_list.length and !_.include(no_properties, rec.att_list[0])"
+                 id="side-edit" src="/web/static/src/img/icons/gtk-edit.png" style="cursor: pointer;"/>
+         </td>
+         <td width="2%">
+             <img t-if="rec.att_list.length"
+                 id="side-up" src="/web/static/src/img/icons/gtk-go-up.png" style="cursor: pointer;"/>
+         </td>
+         <td width="2%">
+             <img t-if="rec.att_list.length"
+                 id="side-down" src="/web/static/src/img/icons/gtk-go-down.png" style="cursor: pointer;"/>
          </td>
          <t t-if="rec.child_id.length">
              <t t-set="data" t-value="rec.child_id"/>
              <tr class="oe_export_row">
                  <t t-foreach="(field.id).split('/')" t-as="level" >
                      <t t-if="(field.id).split('/')[0] != level">
-                         <td width="18">&amp;nbsp;</td>
+                         <td width="18" t-translation="off">&amp;nbsp;</td>
                      </t>
                  </t>
                  <td valign="top" align="left" style="cursor: pointer;" width="18">