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