00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 from xml.parsers import expat
00031 
00032 import sys
00033 import gettext
00034 
00035 from CustomSearchFormWidget import *
00036 from SearchWidgetFactory import *
00037 from AbstractSearchWidget import *
00038 from Koo.Common import Common
00039 from Koo import Rpc
00040 
00041 from PyQt4.QtGui import *
00042 from PyQt4.QtCore import *
00043 from PyQt4.uic import *
00044 
00045 class SearchFormContainer( QWidget ):
00046         def __init__(self, parent):
00047                 QWidget.__init__( self, parent )
00048                 layout = QGridLayout( self )
00049                 layout.setSpacing( 0 )
00050                 layout.setContentsMargins( 0, 0, 0, 0 )
00051                 
00052                 self.col = 4
00053                 self.x = 0
00054                 self.y = 0
00055 
00056         def addWidget(self, widget, name=None):
00057                 if self.x + 1 > self.col:
00058                         self.x = 0
00059                         self.y = self.y + 1
00060 
00061                 
00062                 
00063                 widget.gridLine = self.y
00064                 if name:
00065                         label = QLabel( name )
00066                         label.gridLine = self.y
00067                         vbox = QVBoxLayout()
00068                         vbox.setSpacing( 0 )
00069                         vbox.setContentsMargins( 0, 0, 0, 0 )
00070                         vbox.addWidget( label, 0 )
00071                         vbox.addWidget( widget )
00072                         self.layout().addLayout( vbox, self.y, self.x )
00073                 else:
00074                         self.layout().addWidget( widget, self.y, self.x )
00075                 self.x = self.x + 1
00076 
00077 class SearchFormParser(object):
00078         def __init__(self, container, fields, model=''):
00079                 self.fields = fields
00080                 self.container = container
00081                 self.model = model
00082                 self.focusable = None
00083                 self.widgets = {}
00084 
00085         def _psr_start(self, name, attrs):
00086                 if name in ('form','tree','svg'):
00087                         self.title = attrs.get('string','Form')
00088                 elif name=='field':
00089                         select = attrs.get('select', False) or self.fields[attrs['name']].get('select', False)
00090                         if select:
00091                                 name = attrs['name']
00092                                 self.fields[name].update( attrs )
00093                                 self.fields[name]['model'] = self.model
00094 
00095                                 select = str(select)
00096                                 if select in self.widgets:
00097                                         self.widgets[ select ].append( name )
00098                                 else:
00099                                         self.widgets[ select ] = [ name ]
00100 
00101         def _psr_end(self, name):
00102                 pass
00103         def _psr_char(self, char):
00104                 pass
00105         def parse(self, xml_data):
00106                 psr = expat.ParserCreate()
00107                 psr.StartElementHandler = self._psr_start
00108                 psr.EndElementHandler = self._psr_end
00109                 psr.CharacterDataHandler = self._psr_char
00110                 self.widgetDict={}
00111                 psr.Parse(xml_data.encode('utf-8'))
00112 
00113                 fieldNames = set()
00114                 for line in sorted( self.widgets.keys() ):
00115                         for name in self.widgets[ line ]:
00116                                 
00117                                 
00118                                 if name in fieldNames:
00119                                         continue
00120                                 fieldNames.add( name )
00121 
00122                                 attributes = self.fields[name]
00123                                 type = attributes.get('widget', attributes['type'])
00124                                 widget = SearchWidgetFactory.create( type, name, self.container, attributes )
00125                                 if not widget:
00126                                         continue
00127                                 self.widgetDict[str(name)] = widget
00128                                 if 'string' in attributes:
00129                                         label = attributes['string']+' :'
00130                                 else:
00131                                         label = None
00132                                 self.container.addWidget( widget, label )
00133                                 if not self.focusable:
00134                                         self.focusable = widget
00135                 return self.widgetDict
00136 
00137 (SearchFormWidgetUi, SearchFormWidgetBase) = loadUiType( Common.uiPath('searchform.ui') )
00138 
00139 
00140 
00141 
00142 
00143 class SearchFormWidget(AbstractSearchWidget, SearchFormWidgetUi):
00144         
00145         def __init__(self, parent=None):
00146                 AbstractSearchWidget.__init__(self, '', parent)
00147                 SearchFormWidgetUi.__init__(self)
00148                 self.setupUi( self )
00149                 
00150                 self.model = None
00151                 self.widgets = {}
00152                 self.name = ''
00153                 self.focusable = True
00154                 self.expanded = True
00155                 self._loaded = False
00156 
00157                 self.connect( self.pushExpander, SIGNAL('clicked()'), self.toggleExpansion )
00158                 self.connect( self.pushClear, SIGNAL('clicked()'), self.clear )
00159                 self.connect( self.pushSearch, SIGNAL('clicked()'), self.search )
00160                 self.connect( self.pushSwitchView, SIGNAL('clicked()'), self.toggleView )
00161 
00162                 self.pushExpander.setEnabled( False )
00163                 self.pushClear.setEnabled( False )
00164                 self.pushSearch.setEnabled( False )
00165                 self.toggleView()
00166 
00167         
00168         def isLoaded(self):
00169                 return self._loaded
00170 
00171         
00172         def isEmpty(self):
00173                 if len(self.widgets):
00174                         return False
00175                 else:
00176                         return True
00177 
00178         
00179         
00180         
00181         
00182         def setup(self, xml, fields, model, domain):
00183                 
00184                 if self._loaded:
00185                         return 
00186 
00187                 self._loaded = True
00188                 self.pushExpander.setEnabled( True )
00189                 self.pushClear.setEnabled( True )
00190                 self.pushSearch.setEnabled( True )
00191 
00192                 parser = SearchFormParser(self.uiSimpleContainer, fields, model)
00193                 self.model = model
00194 
00195                 self.widgets = parser.parse(xml)
00196                 for widget in self.widgets.values():
00197                         self.connect( widget, SIGNAL('keyDownPressed()'), self, SIGNAL('keyDownPressed()') )
00198 
00199                 for x in domain:
00200                         if len(x) >= 2 and x[0] in self.widgets and x[1] == '=':
00201                                 self.widgets[ x[0] ].setEnabled( False )
00202 
00203                 
00204                 
00205                 self.pushExpander.hide()
00206                 for x in self.widgets.values():
00207                         if x.gridLine > 0:
00208                                 self.pushExpander.show()
00209                                 break
00210 
00211                 self.name = parser.title
00212                 self.focusable = parser.focusable
00213                 self.expanded = True
00214                 self.toggleExpansion()
00215 
00216                 self.uiCustomContainer.setup( fields, domain )
00217                 return 
00218 
00219         def keyPressEvent(self, event):
00220                 if event.key() in ( Qt.Key_Return, Qt.Key_Enter ):
00221                         self.search()
00222 
00223         def search(self):
00224                 if self.isCustomSearch():
00225                         
00226                         
00227                         
00228                         value = self.value()
00229                         proxy = Rpc.RpcProxy( self.model, useExecute=False )
00230                         try:
00231                                 proxy.search( value, 0, False, False, Rpc.session.context )
00232                         except Rpc.RpcException, e:
00233                                 number = 0
00234                                 for item in value:
00235                                         if not isinstance(item, tuple):
00236                                                 continue
00237 
00238                                         valid = True
00239                                         try:
00240                                                 self.uiCustomContainer.setItemValid
00241                                                 proxy.search( [item], 0, False, False, Rpc.session.context )
00242                                         except Rpc.RpcException, e:
00243                                                 valid = False
00244 
00245                                         self.uiCustomContainer.setItemValid(number, valid)
00246                                         number += 1
00247 
00248                                 QMessageBox.warning(self, _('Search Error'), _('Some items of custom search cannot be used. Please, change those in red and try again.'))
00249                                 return
00250 
00251                         self.uiCustomContainer.setAllItemsValid(True)
00252 
00253                 self.emit( SIGNAL('search()') )
00254 
00255 
00256 
00257         
00258         def showButtons(self):
00259                 self.pushClear.setVisible( True )
00260                 self.pushSearch.setVisible( True )
00261 
00262         
00263         def hideButtons(self):
00264                 self.pushClear.setVisible( False )
00265                 self.pushSearch.setVisible( False )
00266 
00267         def toggleExpansion(self):
00268                 layout = self.uiSimpleContainer.layout()
00269                 
00270                 childs = self.uiSimpleContainer.children()
00271                 for x in childs:
00272                         if x.isWidgetType() and x.gridLine > 0:
00273                                 if self.expanded:
00274                                         x.hide()
00275                                 else:
00276                                         x.show()
00277                 self.expanded = not self.expanded
00278                 if self.expanded:
00279                         self.pushExpander.setIcon( QIcon(':/images/up.png') )
00280                 else:
00281                         self.pushExpander.setIcon( QIcon(':/images/down.png') )
00282 
00283         def toggleView(self):
00284                 if self.pushSwitchView.isChecked():
00285                         self.uiSimpleContainer.hide()
00286                         self.pushExpander.hide()
00287                         self.uiCustomContainer.show()
00288                 else:
00289                         self.uiSimpleContainer.show()
00290                         self.pushExpander.show()
00291                         self.uiCustomContainer.hide()
00292 
00293         def setFocus(self):
00294                 if self.focusable:
00295                         self.focusable.setFocus()
00296                 else:
00297                         QWidget.setFocus(self)
00298 
00299         
00300         
00301         
00302         def clear(self):
00303                 if self.pushSwitchView.isChecked():
00304                         return self.uiCustomContainer.clear()
00305 
00306                 for x in self.widgets.values():
00307                         x.clear()
00308 
00309         
00310         
00311         
00312         
00313         def value(self, domain=[]):
00314                 if self.pushSwitchView.isChecked():
00315                         return self.uiCustomContainer.value( domain )
00316 
00317                 res = []
00318                 for x in self.widgets:
00319                         res += self.widgets[x].value()
00320                 v_keys = [x[0] for x in res]
00321                 for f in domain:
00322                         if f[0] not in v_keys:
00323                                 res.append(f)
00324                 return res
00325 
00326         def isCustomSearch(self):
00327                 return self.pushSwitchView.isChecked()
00328 
00329         
00330         
00331         
00332         
00333         
00334         
00335         
00336         
00337         
00338         def setValue(self, val):
00339                 for x in val:
00340                         if x in self.widgets:
00341                                 self.widgets[x].value = val[x]
00342