tfr (Openerp) has proposed merging 
lp:~nch-openerp/openobject-client/nch_dynamic_searchview into 
lp:openobject-client.

Requested reviews:
  OpenERP sa GTK client R&D (openerp-dev-gtk)

For more details, see:
https://code.launchpad.net/~nch-openerp/openobject-client/nch_dynamic_searchview/+merge/54663

Hello,

This branch contains the improved Custom filter. You can now get more user 
friendly widgets while creating a custom filter. like say if you select a field 
in custom filter of type Many2one then you criteria input widget will be 
changed to a many2one widgets where you can select any records you want. 
Similarly if the field selected is a selection type then you get a drop down 
selection widgets with the fields filled in. you just need to select the value. 
the domain will be created based on key but the user can now select the value.
Similarly for other widgets too.


Thanks,
-- 
https://code.launchpad.net/~nch-openerp/openobject-client/nch_dynamic_searchview/+merge/54663
Your team OpenERP sa GTK client R&D is requested to review the proposed merge 
of lp:~nch-openerp/openobject-client/nch_dynamic_searchview into 
lp:openobject-client.
=== modified file 'bin/openerp.glade'
--- bin/openerp.glade	2011-01-17 14:10:46 +0000
+++ bin/openerp.glade	2011-03-24 09:09:30 +0000
@@ -8242,83 +8242,6 @@
       </widget>
     </child>
   </widget>
-  <widget class="GtkHBox" id="hbox_custom_filter">
-    <property name="visible">True</property>
-    <property name="spacing">5</property>
-    <child>
-          <widget class="GtkComboBox" id="combo_fields">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="tooltip" translatable="yes">Fields on which Search criteria to be applied</property>
-            <property name="items" translatable="yes"></property>
-          </widget>
-          <packing>
-          <property name="expand">False</property>
-          <property name="fill">False</property>
-          <property name="position">1</property>
-        </packing>
-    </child>
-    <child>
-      <widget class="GtkComboBox" id="combo_operator">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="tooltip" translatable="yes">Conditional Operators</property>
-        <property name="items" translatable="yes"></property>
-      </widget>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-    <child>
-      <widget class="GtkEntry" id="right_compare">
-        <property name="visible">True</property>
-        <property name="editable">True</property>
-        <property name="can_focus">True</property>
-        <property name="activates_default">True</property>
-        <property name="width_chars">21</property>
-      </widget>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">3</property>
-      </packing>
-    </child>
-    <child>
-      <widget class="GtkComboBox" id="cond_custom">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="tooltip" translatable="yes">The Choice will be applied with next filter if any</property>
-        <property name="items" translatable="yes">AND
-OR</property>
-      </widget>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">4</property>
-      </packing>
-    </child>
-    <child>
-      <widget class="GtkButton" id="remove_custom">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="tooltip" translatable="yes">Remove Filter</property>
-        <signal name="button_press_event" handler="on_remove_custom"/>
-        <child>
-          <widget class="GtkImage" id="image4168">
-            <property name="visible">True</property>
-            <property name="stock">gtk-remove</property>
-          </widget>
-        </child>
-      </widget>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">5</property>
-      </packing>
-    </child>
-  </widget>
   <widget class="GtkDialog" id="dia_get_action">
     <property name="width_request">230</property>
     <property name="height_request">122</property>

=== modified file 'bin/widget/screen/screen.py'
--- bin/widget/screen/screen.py	2011-01-27 12:43:03 +0000
+++ bin/widget/screen/screen.py	2011-03-24 09:09:30 +0000
@@ -113,7 +113,6 @@
         self.old_limit = limit
         self.offset = 0
         self.readonly= readonly
-        self.custom_panels = []
         self.view_fields = {} # Used to switch self.fields when the view switchs
         self.sort_domain = []
         self.old_ctx = {}
@@ -157,11 +156,7 @@
                 self.filter_widget = widget_search.form(self.search_view['arch'],
                         self.search_view['fields'], self.name, self.window,
                         self.domain, (self, self.search_filter))
-                self.screen_container.add_filter(self.filter_widget.widget,
-                        self.search_filter, self.search_clear,
-                        self.search_offset_next,
-                        self.search_offset_previous,
-                        self.execute_action, self.add_custom, self.name, self.limit)
+                self.screen_container.add_filter(self)
 
         if active and show_search:
             self.screen_container.show_filter()
@@ -285,21 +280,6 @@
         self.load(ids)
         return True
 
-    def add_custom(self, dynamic_button):
-        fields_list = []
-        for k,v in self.search_view['fields'].items():
-            if v['type'] in ('many2one','text','char','float','integer','date','datetime','selection','many2many','boolean','one2many') and v.get('selectable', False):
-                selection = v.get('selection', False)
-                fields_list.append([k,v['string'], v['type'], selection])
-        if fields_list:
-            fields_list.sort(lambda x, y: cmp(x[1], y[1]))
-        panel = self.filter_widget.add_custom(self.filter_widget, self.filter_widget.widget, fields_list)
-        self.custom_panels.append(panel)
-
-        if len(self.custom_panels)>1:
-            self.custom_panels[-1].condition_next.hide()
-            self.custom_panels[-2].condition_next.show()
-
     def execute_action(self, combo):
         flag = combo.get_active_text()
         combo_model = combo.get_model()

=== modified file 'bin/widget/view/screen_container.py'
--- bin/widget/view/screen_container.py	2011-01-10 11:59:36 +0000
+++ bin/widget/view/screen_container.py	2011-03-24 09:09:30 +0000
@@ -26,7 +26,6 @@
 from rpc import RPCProxy
 import rpc
 
-
 class screen_container(object):
     def __init__(self, win_search=False):
         self.old_widget = False
@@ -48,6 +47,7 @@
         self.domain = []
         self.context = {}
         self.handler_id = None
+        self.custom_panels = []
 
     def __del__(self):
         for (ref, value) in self.__dict__.items():
@@ -100,7 +100,15 @@
         self.action_list.foreach(fnct, filter_name)
         return str(self.domain),str(self.context)
 
-    def add_filter(self, widget, fnct, clear_fnct, next_fnct, prev_fnct, execute_action=None, add_custom=None, model=None, limit=100):
+    def add_custom_filter(self, button, screen):
+        fields = screen.search_view.get('fields', {})
+        panel = screen.filter_widget.add_custom(screen.filter_widget, screen.filter_widget.widget, fields)
+        self.custom_panels.append(panel)
+        if len(self.custom_panels)>1:
+            self.custom_panels[-1].condition_next.hide()
+            self.custom_panels[-2].condition_next.show()
+
+    def add_filter(self, screen):
         self.filter_vbox = gtk.VBox(spacing=1)
         self.filter_vbox.set_border_width(1)
         if self.help and not self.win_search:
@@ -108,14 +116,14 @@
             self.help_frame = action_tips.help_frame
             if self.help_frame:
                 self.filter_vbox.pack_start(self.help_frame, expand=False, fill=False, padding=3)
-        self.filter_vbox.pack_start(widget, expand=True, fill=True)
+        self.filter_vbox.pack_start(screen.filter_widget.widget, expand=True, fill=True)
 
         hs = gtk.HBox(homogeneous=False, spacing=0)
         hb1 = gtk.HButtonBox()
         hb1.set_layout(gtk.BUTTONBOX_START)
 
         button_clear = gtk.Button(stock=gtk.STOCK_CLEAR)
-        button_clear.connect('clicked', clear_fnct)
+        button_clear.connect('clicked', screen.search_clear)
         if self.win_search:
             hb3 = hb1
             hs.pack_start(hb3, expand=False, fill=False)
@@ -130,7 +138,7 @@
 
     #Find Clear Buttons
             self.button = gtk.Button(stock=gtk.STOCK_FIND)
-            self.button.connect('clicked', fnct)
+            self.button.connect('clicked', screen.search_filter)
             self.button.set_property('can_default', True)
             hb1.pack_start(self.button, expand=False, fill=False)
             hb1.pack_start(button_clear, expand=False, fill=False)
@@ -143,9 +151,9 @@
             self.action_combo.pack_start(cell, True)
             self.action_combo.add_attribute(cell, 'text', 2)
 
-            self.fill_filter_combo(model)
+            self.fill_filter_combo(screen.name)
             self.action_combo.set_active(0)
-            self.handler_id = self.action_combo.connect('changed', execute_action)
+            self.handler_id = self.action_combo.connect('changed', screen.execute_action)
 
     #Custom Filter Button
             img2 = gtk.Image()
@@ -154,7 +162,7 @@
             self.button_dynamic.set_image(img2)
             self.button_dynamic.set_relief(gtk.RELIEF_NONE)
             self.button_dynamic.set_alignment(0.3,0.3)
-            self.button_dynamic.connect('clicked', add_custom)
+            self.button_dynamic.connect('clicked', self.add_custom_filter, screen)
 
             hb2.pack_start(gtk.Label(''), expand=True, fill=True)
             hb2.pack_start(self.action_combo, expand=False, fill=False)
@@ -170,7 +178,7 @@
 
         self.selection = []
         hb3.pack_start(self.combo, expand=False, fill=False)
-        self.fill_limit_combo(limit)
+        self.fill_limit_combo(screen.limit)
 
 #Back Forward Buttons
 
@@ -179,14 +187,14 @@
         icon.set_from_stock('gtk-go-back', gtk.ICON_SIZE_SMALL_TOOLBAR)
         self.but_previous.set_image(icon)
         self.but_previous.set_relief(gtk.RELIEF_NONE)
-        self.but_previous.connect('clicked', prev_fnct)
+        self.but_previous.connect('clicked', screen.search_offset_previous)
 
         icon2 = gtk.Image()
         icon2.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_SMALL_TOOLBAR)
         self.but_next = gtk.Button()
         self.but_next.set_image(icon2)
         self.but_next.set_relief(gtk.RELIEF_NONE)
-        self.but_next.connect('clicked', next_fnct)
+        self.but_next.connect('clicked', screen.search_offset_next)
         next_prev_box = hb3
         if self.win_search:
             next_prev_box = gtk.HBox(homogeneous=False, spacing=0)

=== modified file 'bin/widget_search/calendar.py'
--- bin/widget_search/calendar.py	2011-01-06 09:49:16 +0000
+++ bin/widget_search/calendar.py	2011-03-24 09:09:30 +0000
@@ -58,8 +58,8 @@
         img.set_alignment(0.5, 0.5)
         self.eb1.add(img)
         self.widget.pack_start(self.eb1, expand=False, fill=False)
-
-        self.widget.pack_start(gtk.Label('-'), expand=False, fill=False)
+        self.label = gtk.Label('-')
+        self.widget.pack_start(self.label, expand=False, fill=False)
 
         self.widget2 = date_widget.ComplexEntry(self.format, spacing=3)
         self.entry2 = self.widget2.widget
@@ -186,8 +186,8 @@
         img.set_alignment(0.5, 0.5)
         self.eb1.add(img)
         self.widget.pack_start(self.eb1, expand=False, fill=False)
-
-        self.widget.pack_start(gtk.Label('-'), expand=False, fill=False)
+        self.label = gtk.Label('-')
+        self.widget.pack_start(self.label, expand=False, fill=False)
 
         self.widget2 = date_widget.ComplexEntry(self.format, spacing=3)
         self.entry2 = self.widget2.widget

=== modified file 'bin/widget_search/custom_filter.py'
--- bin/widget_search/custom_filter.py	2011-03-11 10:40:13 +0000
+++ bin/widget_search/custom_filter.py	2011-03-24 09:09:30 +0000
@@ -19,28 +19,19 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ##############################################################################
-
 import gtk
-from datetime import datetime
-import gettext
-from gtk import glade
-
-import tools
 import wid_int
-import common
+import custom_filter_widgets
 
-DT_FORMAT = '%Y-%m-%d'
-DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
 
 class custom_filter(wid_int.wid_int):
-    def __init__(self, name, parent, attrs={}, call=None):
-        wid_int.wid_int.__init__(self, name, parent, attrs)
-        win_gl = glade.XML(common.terp_path("openerp.glade"),"hbox_custom_filter",gettext.textdomain())
-        self.widget = win_gl.get_widget('hbox_custom_filter')
-
-        # Processing fields
-        self.combo_fields = win_gl.get_widget('combo_fields')
+    def __init__(self, name, parent, fields={}, callback=None, search_callback=None):
+        wid_int.wid_int.__init__(self, name, parent)
+
+        self.fields = fields
+
         self.field_selection = {}
+<<<<<<< TREE
         # this stores the db fields to map with the index of the active_text()
         # becuase when traslation is used the active_text get translated and fails to
         # search.
@@ -51,13 +42,70 @@
         for item in fields:
             self.field_selection[item[1]] = (item[0], item[2], item[3])
             self.field_lst.append(item[1])
+=======
+        self.op_selection = {}
+        # This list will store the fields,operators to map with the index of the active_text()
+        # because when translation is used the active_text get translated and fails to search
+
+        self.field_lst = []
+        self.operators_lst = []
+
+        self.search_callback = search_callback
+        self.widget = gtk.HBox()
+        # fields_list combo
+        self.combo_fields =  gtk.combo_box_new_text()
+        self.combo_fields.connect('changed', self.on_fields_combo_changed)
+
+        self.combo_op = gtk.combo_box_new_text()
+        self.combo_op.connect('changed', self.on_operator_combo_changed)
+
+        self.condition_next = gtk.combo_box_new_text()
+        self.condition_next.append_text(_('AND'))
+        self.condition_next.append_text(_('OR'))
+        self.condition_next.set_active(0)
+        self.condition_next.hide()
+
+        self.remove_filter = gtk.Button()
+        img = gtk.Image()
+        img.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_BUTTON)
+        self.remove_filter.add(img)
+        self.remove_filter.set_relief(gtk.RELIEF_NONE)
+        self.remove_filter.connect('clicked', callback, self)
+
+        self.right_text = gtk.Entry()
+
+        self.widget.pack_start(self.combo_fields)
+        self.widget.pack_start(self.combo_op)
+        self.widget.pack_start(self.right_text)
+        self.widget.pack_start(self.condition_next)
+        self.widget.pack_start(self.remove_filter)
+        self.widget.show_all()
+        sorted_names = []
+        for key, attr in self.fields.iteritems():
+            sorted_names.append([key,attr['string'], attr['type']])
+        sorted_names.sort(lambda x, y:cmp(x[1], y[1]))
+        for item in sorted_names:
+            self.field_selection[item[1]] = (item[0], item[2])
+            self.field_lst.append(item[1])
+>>>>>>> MERGE-SOURCE
             self.combo_fields.append_text(item[1])
-
         self.combo_fields.set_active(0)
 
-        # Processing operator combo
-        self.combo_op = win_gl.get_widget('combo_operator')
+    def on_operator_combo_changed(self, combo):
+        if self.operators_lst:
+            self.widget_obj.selected_oper_text = self.operators_lst[self.combo_op.get_active()]
+        self.widget_obj.set_visibility()
+        return True
+
+    def on_fields_combo_changed(self, combo):
+        field_string = self.field_lst[self.combo_fields.get_active()]
+        field_dbname, type = self.field_selection[field_string]
+        if self.right_text:
+            self.widget.remove(self.right_text)
+        self.widget_obj = custom_filter_widgets.widgets_type[type](field_string, self.parent, self.fields.get(field_dbname, {}), self.search_callback)
+        self.right_text = self.widget_obj.widget
         self.op_selection = {}
+<<<<<<< TREE
 
         for item in (['ilike', _('contains')],
                 ['not ilike', _('doesn\'t contain')],
@@ -72,27 +120,25 @@
             self.operators_lst.append(item[1])
             self.combo_op.append_text(item[1])
 
+=======
+        self.operators_lst = []
+        self.combo_op.get_model().clear()
+        for operator in self.widget_obj.operators:
+            self.op_selection[operator[1]] = operator[0]
+            self.operators_lst.append(operator[1])
+            self.combo_op.append_text(operator[1])
+        self.widget.pack_start(self.right_text)
+        self.widget.reorder_child(self.right_text, 2)
+        vis = self.condition_next.get_visible()
+        self.widget.show_all()
+>>>>>>> MERGE-SOURCE
         self.combo_op.set_active(0)
-
-        # Processing text value
-        self.right_text = win_gl.get_widget('right_compare')
-        # Processing Custom conditions
-        self.condition_next = win_gl.get_widget('cond_custom')
-        self.condition_next.set_active(0)
-
-        self.condition_next.hide()
-        # Processing Removal of panel
-        self.remove_filter = win_gl.get_widget('remove_custom')
-        self.remove_filter.set_relief(gtk.RELIEF_NONE)
-
-        try:
-            self.right_text.set_tooltip_markup(tools.to_xml(_("Enter Values separated by ',' if operator 'in' or 'not in' is chosen.\nFor Date and DateTime Formats, specify text in '%Y-%m-%d' and '%Y-%m-%d %H:%M:%S' formats respectively.")))
-        except:
-            pass
-
-        self.remove_filter.connect('clicked',call,self)
+        if not vis:
+            self.condition_next.hide()
+        return True
 
     def _value_get(self):
+<<<<<<< TREE
         try:
             false_value_domain = []
             type_cast = {'integer':lambda x:int(x),
@@ -163,6 +209,17 @@
 
         except Exception,e:
             return {}
+=======
+        field_string = self.field_lst[self.combo_fields.get_active()]
+        self.widget_obj.field_left  = self.field_selection[field_string][0]
+        self.widget_obj.selected_oper_text = self.operators_lst[self.combo_op.get_active()]
+        self.widget_obj.selected_oper_text = self.combo_op.get_active_text()
+        self.widget_obj.selected_oper = self.op_selection[self.widget_obj.selected_oper_text]
+        wid_domain = self.widget_obj._value_get()
+        condition = self.condition_next.get_active() == 0 and '&' or '|'
+        domain = [condition] + wid_domain
+        return {'domain':domain}
+>>>>>>> MERGE-SOURCE
 
     def sig_exec(self, widget):
         pass
@@ -178,9 +235,12 @@
         return True
 
     def sig_activate(self, fct):
-        self.right_text.connect_after('activate', fct)
+        try:
+            self.right_text.connect_after('activate', fct)
+        except:
+            pass
 
     value = property(_value_get, _value_set, None,
      _('The content of the widget or ValueError if not valid'))
 
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file

=== added file 'bin/widget_search/custom_filter_widgets.py'
--- bin/widget_search/custom_filter_widgets.py	1970-01-01 00:00:00 +0000
+++ bin/widget_search/custom_filter_widgets.py	2011-03-24 09:09:30 +0000
@@ -0,0 +1,382 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+import gtk
+import wid_int
+import calendar
+from calendar import calendar,datetime
+from spinbutton import spinbutton
+from spinint import spinint
+from selection import selection
+import char
+import checkbox
+from reference import reference
+import rpc
+
+class char(char.char):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        super(char,self).__init__(name, parent)
+        self.operators = (['=', _('is')],
+                          ['<>',_('is not')],
+                          ['=', _('is Empty')],
+                          ['<>',_('is not Empty')],
+                          ['ilike', _('contains')],
+                          ['not ilike', _('doesn\'t contain')])
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.widget.connect('activate', search_callback)
+
+    def _value_get(self):
+        text = self.widget.get_text() or False
+        if self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            text = False
+        return [(self.field_left, self.selected_oper, text)]
+
+    def set_visibility(self):
+        self.widget.show_all()
+        self.widget.set_text('')
+        if self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            self.widget.hide()
+
+class many2one(wid_int.wid_int):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        wid_int.wid_int.__init__(self, name, parent)
+        self.attrs = attrs
+        self.operators = (['=', _('is')],
+                          ['<>',_('is not')],
+                          ['=', _('is Empty')],
+                          ['<>',_('is not Empty')],
+                          ['ilike', _('contains')],
+                          ['not ilike', _('doesn\'t contain')])
+
+        self.widget = gtk.HBox(spacing=0)
+        self.widget.set_property('sensitive', True)
+
+        self.wid_text = gtk.Entry()
+        self.wid_text.set_property('width-chars', 20)
+        self.wid_text.connect('key_press_event', self.sig_key_press)
+        self.wid_text.connect_after('activate', self.sig_activate)
+        self.widget.pack_start(self.wid_text, expand=True, fill=True)
+
+        self.but_find = gtk.Button()
+        img = gtk.Image()
+        img.set_from_stock('gtk-find', gtk.ICON_SIZE_BUTTON)
+        self.but_find.set_image(img)
+        self.but_find.set_relief(gtk.RELIEF_NONE)
+        self.but_find.connect('clicked', self.sig_find)
+        self.but_find.set_alignment(0.5, 0.5)
+        self.but_find.set_property('can-focus', False)
+        self.but_find.set_tooltip_text(_('Search a resource'))
+        self.but_find.set_size_request(30,30)
+        self.widget.pack_start(self.but_find, padding=2, expand=False, fill=False)
+
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.enter_pressed = False
+        self.selected_value = False
+
+    def sig_activate(self, widget, event=None, leave=False):
+        if not self.selected_oper_text in  [_('contains'), _('doesn\'t contain')]:
+            event = self.enter_pressed and True or event
+            return self.sig_find(widget, event, leave=True)
+
+    def sig_find(self, widget, event=None, leave=True):
+        from modules.gui.window.win_search import win_search
+        name_search = self.wid_text.get_text() or ''
+        ids = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['relation'], 'name_search', name_search, [], 'ilike', rpc.session.context)
+        win = win_search(self.attrs['relation'], sel_multi=False, ids=map(lambda x: x[0], ids), context=rpc.session.context, parent=self.parent)
+        win.glade.get_widget('newbutton').hide()
+        ids = win.go()
+        if ids:
+            self.selected_value = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['relation'], 'name_get', [ids[0]], rpc.session.context)[0]
+            self.wid_text.set_text(self.selected_value[1])
+        return
+
+    def sig_key_press(self, widget, event, *args):
+        self.enter_pressed = False
+        if event.keyval == gtk.keysyms.F2:
+            self.sig_activate(widget, event)
+        elif event.keyval == gtk.keysyms.Tab:
+            if not self.wid_text.get_text():
+                return False
+            return not self.sig_activate(widget, event, leave=True)
+        elif event.keyval in (gtk.keysyms.KP_Enter,gtk.keysyms.Return):
+            if self.wid_text.get_text():
+                self.enter_pressed = True
+        return False
+
+    def _value_get(self):
+        if self.selected_oper_text in [_('is'), _('is not')]:
+            text = self.selected_value and self.selected_value[0] or False
+        elif self.selected_oper_text in ['is Empty', 'is not Empty']:
+            text = False
+        else:
+            text = self.wid_text.get_text()
+        return [(self.field_left, self.selected_oper, text)]
+
+    def set_visibility(self):
+        self.widget.show_all()
+        self.wid_text.set_text('')
+        self.selected_value = False
+        if self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            self.wid_text.hide()
+            self.but_find.hide()
+        elif not self.selected_oper_text in ['is', 'is not']:
+            self.but_find.hide()
+
+class one2many(many2one):
+     def __init__(self, name, parent, attrs={}, search_callback=None):
+         many2one.__init__(self, name, parent, attrs, search_callback=None)
+         self.operators = (['=', _('is')],
+                           ['<>',_('is not')],
+                           ['=', _('is Empty')],
+                           ['<>',_('is not Empty')])
+class many2many(many2one):
+     def __init__(self, name, parent, attrs={}, search_callback=None):
+         many2one.__init__(self, name, parent, attrs, search_callback=None)
+         self.operators = (['=', _('is')],
+                           ['<>',_('is not')],
+                           ['=', _('is Empty')],
+                           ['<>',_('is not Empty')])
+
+
+class checkbox(wid_int.wid_int):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        wid_int.wid_int.__init__(self, name, parent)
+        self.widget = gtk.CheckButton()
+        self.widget.set_active(False)
+        self.operators = (['=', _('Equals')],)
+        self.selected_oper = False
+        self.field_left = False
+
+    def _value_get(self):
+        return [(self.field_left, self.selected_oper, int(self.widget.get_active()))]
+
+    def set_visibility(self):
+        pass
+
+class calendar(calendar):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        super(calendar,self).__init__(name, parent)
+        self.operators =  (['=', _('is')],
+                          ['<>',_('is not')],
+                          ['*', _('between')],
+                          ['=', _('is Empty')],
+                          ['<>',_('is not Empty')],
+                          ['**', _('exclude range')])
+
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.entry1.connect('activate', search_callback)
+        self.entry2.connect('activate', search_callback)
+
+    def _value_get(self):
+        val1 = self._date_get(self.entry1.get_text())
+        val2 = self._date_get(self.entry2.get_text())
+        if self.selected_oper_text == _('between'):
+            domain = ['&', (self.field_left, '>=', val1),(self.field_left, '<=', val2)]
+            return domain
+        elif self.selected_oper_text == _('exclude range'):
+            domain = ['|',(self.field_left, '<', val1),(self.field_left, '>', val2)]
+            return domain
+        elif self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            val1 = False
+        domain = [(self.field_left, self.selected_oper, val1)]
+        return domain
+
+    def set_visibility(self):
+        self.entry1.set_text(self.widget1.widget.initial_value)
+        self.entry2.set_text(self.widget2.widget.initial_value)
+        if self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            self.widget.hide_all()
+        elif self.selected_oper_text in [_('is'), _('is not')]:
+            self.widget.show_all()
+            self.entry1.show()
+            self.entry2.hide()
+            self.label.hide()
+            self.eb1.show()
+            self.eb2.hide()
+        else:
+            self.widget.show_all()
+
+class datetime(datetime):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        super(datetime,self).__init__(name, parent)
+        self.operators =  (['=', _('is')],
+                          ['<>',_('is not')],
+                          ['*', _('between')],
+                          ['=', _('is Empty')],
+                          ['<>',_('is not Empty')],
+                          ['**', _('exclude range')])
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.entry1.connect('activate', search_callback)
+        self.entry2.connect('activate', search_callback)
+
+
+    def _value_get(self):
+        val1 = self._date_get(self.entry1.get_text())
+        val2 = self._date_get(self.entry2.get_text())
+        if self.selected_oper_text == _('between'):
+            domain = ['&', (self.field_left, '>=', val1),(self.field_left, '<=', val2)]
+            return domain
+        elif self.selected_oper_text == _('exclude range'):
+            domain = ['|',(self.field_left, '<', val1),(self.field_left, '>', val2)]
+            return domain
+        elif self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            val1 = False
+        domain = [(self.field_left, self.selected_oper, val1)]
+        return domain
+
+    def set_visibility(self):
+        self.entry1.set_text(self.widget1.widget.initial_value)
+        self.entry2.set_text(self.widget2.widget.initial_value)
+        if self.selected_oper_text in [_('is Empty'), _('is not Empty')]:
+            self.widget.hide_all()
+        elif self.selected_oper_text in [_('is'), _('is not')]:
+            self.widget.show_all()
+            self.entry1.show()
+            self.entry2.hide()
+            self.label.hide()
+            self.eb1.show()
+            self.eb2.hide()
+        else:
+            self.widget.show_all()
+
+
+class selection(selection):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        selection_dict = {'selection':attrs.get('selection', {})}
+        super(selection,self).__init__(name, parent, selection_dict)
+        self.operators =  (['=', _('is')],
+                          ['<>',_('is not')])
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+
+    def _value_get(self):
+        key = self._selection.get(self.widget.child.get_text(), False)
+        return [(self.field_left, self.selected_oper,  key)]
+
+    def set_visibility(self):
+        self.widget.child.set_text('')
+        pass
+
+#
+class spinbutton(spinbutton):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        super(spinbutton,self).__init__(name, parent)
+        self.operators = (['=', _('is equal to')],
+                          ['<>',_('is not equal to')],
+                          ['>',_('greater than')],
+                          ['<',_('less than')],
+                          ['>=',_('greater than equal to')],
+                          ['<=',_('less than equal to')],
+                          ['*',_('between')],
+                          ['**',_('exclude range')])
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.spin1.connect('activate', search_callback)
+        self.spin2.connect('activate', search_callback)
+
+
+    def _value_get(self):
+        self.spin1.update()
+        self.spin2.update()
+        val1 = self.spin1.get_value()
+        val2 = self.spin2.get_value()
+        if self.selected_oper_text == _('between'):
+            domain = ['&', (self.field_left, '>=', val1),(self.field_left, '<=', val2)]
+            return domain
+        elif self.selected_oper_text == _('exclude range'):
+            domain = ['|',(self.field_left, '<', val1),(self.field_left, '>', val2)]
+            return domain
+        domain = [(self.field_left, self.selected_oper, val1)]
+        return domain
+
+    def set_visibility(self):
+        self.spin1.set_value(0.0)
+        self.spin2.set_value(0.0)
+        if self.selected_oper_text in [_('between'), _('exclude range')]:
+            self.widget.show_all()
+        else:
+            self.spin2.hide()
+            self.label.hide()
+
+class spinint(spinint):
+    def __init__(self, name, parent, attrs={}, search_callback=None):
+        super(spinint,self).__init__(name, parent)
+        self.operators = (['=', _('is equal to')],
+                          ['<>',_('is not equal to')],
+                          ['>',_('greater than')],
+                          ['<',_('less than')],
+                          ['>=',_('greater than equal to')],
+                          ['<=',_('less than equal to')],
+                          ['*',_('between')],
+                          ['**',_('exclude range')])
+        self.selected_oper = False
+        self.selected_oper_text = False
+        self.field_left = False
+        self.spin1.connect('activate', search_callback)
+        self.spin2.connect('activate', search_callback)
+
+    def _value_get(self):
+        self.spin1.update()
+        self.spin2.update()
+        val1 = self.spin1.get_value()
+        val2 = self.spin2.get_value()
+        if self.selected_oper_text == _('between'):
+            domain = ['&', (self.field_left, '>=', val1),(self.field_left, '<=', val2)]
+            return domain
+        elif self.selected_oper_text == _('exclude range'):
+            domain = ['|',(self.field_left, '<', val1),(self.field_left, '>', val2)]
+            return domain
+        domain = [(self.field_left, self.selected_oper, val1)]
+        return domain
+
+    def set_visibility(self):
+        val1 = self.spin1.set_value(0)
+        val2 = self.spin2.set_value(0)
+        if self.selected_oper_text in [_('between'), _('exclude range')]:
+            self.widget.show_all()
+        else:
+            self.spin2.hide()
+            self.label.hide()
+
+widgets_type = {
+    'date': calendar,
+    'datetime': datetime,
+    'float': spinbutton,
+    'integer': spinint,
+    'selection': selection,
+    'char': char,
+    'boolean': checkbox,
+    'text': char,
+    'many2one':many2one,
+    'one2many':one2many,
+    'many2many':many2many,
+    }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file

=== modified file 'bin/widget_search/date_widget.py'
--- bin/widget_search/date_widget.py	2011-01-31 14:48:39 +0000
+++ bin/widget_search/date_widget.py	2011-03-24 09:09:30 +0000
@@ -23,7 +23,7 @@
 import pango
 import gtk
 import re
-
+from datetime import datetime
 import tools
 import tools.datetime_util
 import time
@@ -38,8 +38,8 @@
         for key,val in tools.datetime_util.date_mapping.items():
             self.regex = self.regex.replace(key, val[1])
             self.initial_value = self.initial_value.replace(key, val[0])
-            
-        self.small_text = self.initial_value 
+
+        self.small_text = self.initial_value
         self.set_text(self.initial_value)
         self.regex = re.compile(self.regex)
 
@@ -73,13 +73,13 @@
                     ('%U',''), ('%W','')]:
             fmt = fmt.replace(x, y)
 
-        if (not (fmt.count('%Y') >= 1 and fmt.count('%m') >= 1 and fmt.count('%d') >= 1) or fmt.count('%x') >= 1) and (fmt.count('%H') == 0 and fmt.count('%M') == 0 and fmt.count('%S') == 0 and fmt.count('%X') == 0): 
-                
+        if (not (fmt.count('%Y') >= 1 and fmt.count('%m') >= 1 and fmt.count('%d') >= 1) or fmt.count('%x') >= 1) and (fmt.count('%H') == 0 and fmt.count('%M') == 0 and fmt.count('%S') == 0 and fmt.count('%X') == 0):
+
             return '%Y/%m/%d'
         elif not (fmt.count('%Y') >= 1 and fmt.count('%m') >= 1 and fmt.count('%d') >= 1) \
                 or (fmt.count('%x') >=1 or fmt.count('%c') >= 1):
             return '%Y/%m/%d %H:%M:%S'
-            
+
 
         return fmt
 
@@ -89,14 +89,14 @@
             return datetime.strptime(text, self.format)
         except:
             pass
-            
+
         try:
             return datetime.strptime(text, self.small_format)
         except:
             self.valid = False
             return False
-        
-        
+
+
     def _on_insert_text(self, editable, value, length, position):
         if not self._interactive_input:
             return
@@ -104,14 +104,14 @@
         self.stop_emission('insert-text')
         if self.mode_cmd:
             if self.callback: self.callback(value)
-            return 
-        
-        text = self.get_text()  
+            return
+
+        text = self.get_text()
         current_pos = self.get_position()
-        
+
         if(length + current_pos > len(text)):
             return
-        
+
         pos = (current_pos < 10  or text != self.initial_value) and current_pos or 0
 
         if length != 1:
@@ -156,7 +156,7 @@
         if self.mode_cmd:
             self.mode_cmd = False
             if self.callback_process: self.callback_process(False, self, False)
-            
+
     def _focus_in(self, args, args2):
         self.set_text(self.small_text)
         if self.mode_cmd:
@@ -170,10 +170,10 @@
             date = self.isvalid_date(text);
             if(date):
                 self.small_text = date.strftime(self.small_format)
-            
+
         finally:
             self._interactive_input = True
-            
+
     def date_set(self, dt):
         if dt:
             self.set_text( dt.strftime(self.format) )

=== modified file 'bin/widget_search/form.py'
--- bin/widget_search/form.py	2011-02-01 09:45:54 +0000
+++ bin/widget_search/form.py	2011-03-24 09:09:30 +0000
@@ -28,6 +28,7 @@
 import tools
 from lxml import etree
 import uuid
+import copy
 
 class _container(object):
     def __init__(self, max_width):
@@ -316,6 +317,7 @@
         self.show()
         for x in self.widgets.values():
             x[0].sig_activate(self.sig_activate)
+        self.invisible_widgets = []
 
     def xml_process(self,xml_arch):
         root = etree.fromstring(xml_arch)
@@ -364,15 +366,32 @@
     def remove_custom(self, button, panel):
         button.parent.destroy()
         # Removing the Destroyed widget from Domain calculation
-        for element in self.custom_widgets.keys():
-            if self.custom_widgets[element][0] == panel:
-                del self.custom_widgets[element]
-                break
+        ## also removing the field from the list of invisible fields
+        ## so that they dont reappear and as the childs are deleted for the panel
+        ## that has to be deleted we need to do a reverse process for removing the
+        ## the invisible fields from the list of invisible fields.
+        def process(widget):
+            if isinstance(widget, gtk.HBox):
+                for child in widget.get_children():
+                    process(child)
+            inv_childs = self.invisible_widgets
+            for inv_child in inv_childs:
+                if inv_child != widget:
+                    self.invisible_widgets.remove(inv_child)
+            return True
+
+        custom_panel = copy.copy(self.custom_widgets)
+        for key, wid in custom_panel.iteritems():
+            for child in wid[0].widget.get_children():
+                if not isinstance(child, (gtk.ComboBox, gtk.Button)):
+                    process(child)
+            if wid[0] == panel:
+               del self.custom_widgets[key]
         return True
 
     def add_custom(self, widget, table, fields):
         new_table = gtk.Table(1,1,False)
-        panel = widgets_type['custom_filter'][0]('', self.parent,{'fields':fields},call=self.remove_custom)
+        panel = widgets_type['custom_filter'][0]('', self.parent, fields, callback=self.remove_custom, search_callback=self.call[1])
         x =  self.rows
         new_table.attach(panel.widget,0, 1, x, x+1, xoptions=gtk.FILL, yoptions=gtk.FILL , ypadding=2, xpadding=0)
         panelx = 'panel' + str(x)
@@ -380,7 +399,29 @@
         self.custom_widgets[panelx] = (panel, new_table, 1)
         table.attach(new_table, 1, 9, x, x+1)
         self.rows += 1
+        ## Store the  widgets original visible attribute because as they are
+        ## attached to the table as a child widgets and the table.show_all() will
+        ## set all child widgets to visible inspite of their visibility is set to FALSE
+        ## so make them invisible again after the table.show_all()
+        def process(widget):
+            if isinstance(widget, gtk.HBox):
+                for sub_child in widget.get_children():
+                    process(sub_child)
+            if widget.get_visible():
+                if widget in self.invisible_widgets:
+                    self.invisible_widgets.remove(widget)
+            else:
+                if not widget in self.invisible_widgets:
+                    self.invisible_widgets.append(widget)
+            return True
+
+        for key, wid in self.custom_widgets.iteritems():
+            for child in wid[0].widget.get_children():
+                if not isinstance(child, (gtk.ComboBox, gtk.Button)):
+                    process(child)
         table.show_all()
+        for wid in self.invisible_widgets:
+            wid.set_visible(False)
         return panel
 
     def toggle(self, widget, event=None):
@@ -413,12 +454,16 @@
         if self.groupby:
             context.update({'group_by':self.groupby})
         if domain:
-            if len(domain)>1 and domain[-2] in ['&','|']:
-                if len(domain) == 2:
-                    domain = [domain[1]]
+            if '&' in domain or '|' in domain:
+                if domain[-2] in ['&','|']:
+                    pos = 2
+                elif len(domain) >= 4 and domain[-4] in ['&','|']:
+                    pos = 4
+                if len(domain) == 4 and domain[1] in ['&','|']:
+                    domain = domain[1:]
                 else:
-                    res1 = domain[:-2]
-                    res2 = domain[-1:]
+                    res1 = domain[:-pos]
+                    res2 = domain[-(pos-1):]
                     domain = res1 + res2
         return {'domain':domain, 'context':context}
 

=== modified file 'bin/widget_search/spinbutton.py'
--- bin/widget_search/spinbutton.py	2011-01-31 10:28:17 +0000
+++ bin/widget_search/spinbutton.py	2011-03-24 09:09:30 +0000
@@ -39,8 +39,8 @@
         self.spin1.connect('input', self.format_input)
         self.spin1.connect('output', self.format_output)
         self.widget.pack_start(self.spin1, expand=False, fill=True)
-
-        self.widget.pack_start(gtk.Label('-'), expand=False, fill=False)
+        self.label = gtk.Label('-')
+        self.widget.pack_start(self.label, expand=False, fill=False)
 
         adj2 = gtk.Adjustment(0.0, -sys.maxint, sys.maxint, 1.0, 5.0)
         self.spin2 = gtk.SpinButton(adj2, 1.0, digits=int(attrs.get('digits', (14, 2))[1]))

=== modified file 'bin/widget_search/spinint.py'
--- bin/widget_search/spinint.py	2011-01-31 10:28:17 +0000
+++ bin/widget_search/spinint.py	2011-03-24 09:09:30 +0000
@@ -43,8 +43,8 @@
         self.spin1.connect('input', self.format_input)
         self.spin1.connect('output', self.format_output)
         self.widget.pack_start(self.spin1, expand=False, fill=True)
-
-        self.widget.pack_start(gtk.Label('-'), expand=False, fill=False)
+        self.label = gtk.Label('-')
+        self.widget.pack_start(self.label, expand=False, fill=False)
 
         adj2 = gtk.Adjustment(0.0, 0.0, sys.maxint, 1.0, 5.0)
         self.spin2 = gtk.SpinButton(adj2, 1, digits=0)

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to