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 import gettext
00030
00031 from Koo.Common import Api
00032 from Koo.Common import Common
00033 from Koo.Common import Shortcuts
00034
00035 from Koo.Screen.Screen import Screen
00036 from Koo.Screen.ScreenDialog import ScreenDialog
00037 from Koo.Model.Group import RecordGroup
00038
00039 from Koo.Dialogs.SearchDialog import SearchDialog
00040 from Koo import Rpc
00041
00042 from Koo.Fields.AbstractFieldWidget import *
00043 from Koo.Fields.AbstractFieldDelegate import *
00044 from PyQt4.QtCore import *
00045 from PyQt4.QtGui import *
00046 from PyQt4.uic import *
00047
00048
00049 (ManyToOneFieldWidgetUi, ManyToOneFieldWidgetBase ) = loadUiType( Common.uiPath('many2one.ui') )
00050
00051 class ManyToOneFieldWidget(AbstractFieldWidget, ManyToOneFieldWidgetUi):
00052 def __init__(self, parent, model, attrs={}):
00053 AbstractFieldWidget.__init__(self, parent, model, attrs)
00054 ManyToOneFieldWidgetUi.__init__(self)
00055 self.setupUi(self)
00056
00057 self.uiText.installEventFilter( self )
00058 self.connect( self.uiText, SIGNAL( "editingFinished()" ), self.match )
00059 self.connect( self.pushNew, SIGNAL( "clicked()" ), self.new )
00060 self.connect( self.pushOpen, SIGNAL( "clicked()" ), self.open )
00061 self.connect( self.pushClear, SIGNAL( "clicked()" ), self.clear )
00062
00063 self.setFocusProxy( self.uiText )
00064
00065
00066 self.scNew = QShortcut( self.uiText )
00067 self.scNew.setKey( Shortcuts.CreateInField )
00068 self.scNew.setContext( Qt.WidgetShortcut )
00069 self.connect( self.scNew, SIGNAL('activated()'), self.new )
00070
00071 self.scSearch = QShortcut( self.uiText )
00072 self.scSearch.setKey( Shortcuts.SearchInField )
00073 self.scSearch.setContext( Qt.WidgetShortcut )
00074 self.connect( self.scSearch, SIGNAL('activated()'), self.open )
00075
00076 self.searching = False
00077
00078
00079
00080
00081 self.menuLoaded = False
00082 self.newMenuEntries = []
00083 self.newMenuEntries.append((_('Open'), lambda: self.open(), False))
00084 self.newMenuEntries.append((None, None, None))
00085 self.newMenuEntries.append((_('Action'), lambda: self.executeAction('client_action_multi'), False))
00086 self.newMenuEntries.append((_('Report'), lambda: self.executeAction('client_print_multi'), False))
00087 self.newMenuEntries.append((None, None, None))
00088
00089 def initGui( self ):
00090 QTimer.singleShot( 0, self.delayedInitGui )
00091
00092 def delayedInitGui( self ):
00093
00094 if self.attrs.get('completion',False):
00095 ids = Rpc.session.execute('/object', 'execute', self.attrs['relation'], 'name_search', '', [], 'ilike', Rpc.session.context, False)
00096 if ids:
00097 self.loadCompletion( ids, self.attrs )
00098
00099 def loadCompletion(self,ids,attrs):
00100 self.completion = QCompleter()
00101 self.completion.setCaseSensitivity( Qt.CaseInsensitive )
00102 self.uiText.setCompleter( self.completion )
00103 liststore = []
00104 for i,word in enumerate( ids ):
00105 if word[1][0] == '[':
00106 i = word[1].find( ']')
00107 s = word[1][1:i]
00108 s2 = word[1][i+2:]
00109 liststore.append( s2 )
00110 else:
00111 liststore.append( word[1] )
00112 self.completion.setModel( QStringListModel( liststore ) )
00113 self.completion.setCompletionColumn( 0 )
00114
00115 def clear( self ):
00116
00117
00118
00119 self.view.store()
00120
00121 if self.record:
00122 self.record.setValue( self.name, False )
00123 self.uiText.clear()
00124 self.uiText.setToolTip('')
00125 self.pushOpen.setIcon( QIcon( ":/images/find.png"))
00126 self.pushOpen.setToolTip( _("Search") )
00127
00128 def setReadOnly(self, value):
00129 AbstractFieldWidget.setReadOnly(self, value)
00130 self.uiText.setReadOnly( value )
00131 self.pushNew.setEnabled( not value )
00132 self.pushClear.setEnabled( not value )
00133 if self.record and self.record.value(self.name):
00134 self.pushOpen.setEnabled( True )
00135 else:
00136 self.pushOpen.setEnabled( not value )
00137
00138 def colorWidget(self):
00139 return self.uiText
00140
00141 def match(self):
00142 if self.searching:
00143 return
00144 if not self.record:
00145 return
00146 name = unicode( self.uiText.text() )
00147 if name.strip() == '':
00148 self.record.setValue( self.name, False )
00149 self.showValue()
00150 return
00151 if name == self.record.value(self.name):
00152 return
00153
00154
00155 self.searching = True
00156 self.search( name )
00157 self.searching = False
00158
00159 def open(self):
00160
00161
00162
00163 self.view.store()
00164
00165 if self.record.value(self.name):
00166
00167
00168
00169 if QApplication.keyboardModifiers() & Qt.ControlModifier:
00170 model = self.attrs['relation']
00171 id = self.record.get()[self.name]
00172 if QApplication.keyboardModifiers() & Qt.ShiftModifier:
00173 target = 'background'
00174 else:
00175 target = 'current'
00176 Api.instance.createWindow(False, model, id, [('id','=',id)], 'form', mode='form,tree', target=target)
00177 else:
00178 dialog = ScreenDialog( self )
00179 dialog.setAttributes( self.attrs )
00180 dialog.setup( self.attrs['relation'], self.record.get()[self.name] )
00181 if dialog.exec_() == QDialog.Accepted:
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if not self.isReadOnly():
00192 if dialog.record and dialog.record[0] == self.record.get()[self.name]:
00193 self.record.setValue(self.name, False)
00194 self.record.setValue(self.name, dialog.record)
00195 self.display()
00196 else:
00197 text = unicode( self.uiText.text() )
00198 if text.strip() == '':
00199 self.search('')
00200
00201
00202
00203
00204
00205 def search(self, name):
00206 domain = self.record.domain( self.name )
00207 context = self.record.fieldContext( self.name )
00208 ids = Rpc.session.execute('/object', 'execute', self.attrs['relation'], 'name_search', name, domain, 'ilike', context, False)
00209 if ids and len(ids)==1:
00210 self.record.setValue( self.name, ids[0] )
00211 self.display()
00212 else:
00213 dialog = SearchDialog(self.attrs['relation'], sel_multi=False, ids=[x[0] for x in ids], context=context, domain=domain, parent=self)
00214 if dialog.exec_() == QDialog.Accepted and dialog.result:
00215 id = dialog.result[0]
00216 name = Rpc.session.execute('/object', 'execute', self.attrs['relation'], 'name_get', [id], context)[0]
00217 self.record.setValue(self.name, name)
00218 self.display()
00219 else:
00220 self.clear()
00221
00222 def new(self):
00223 dialog = ScreenDialog(self)
00224 dialog.setAttributes( self.attrs )
00225 dialog.setContext( self.record.fieldContext( self.name ) )
00226 dialog.setDomain( self.record.domain(self.name) )
00227 dialog.setup( self.attrs['relation'] )
00228 if dialog.exec_() == QDialog.Accepted:
00229 self.record.setValue(self.name, dialog.record)
00230 self.display()
00231
00232 def storeValue(self):
00233 if self.uiText.hasFocus():
00234
00235
00236
00237 self.match()
00238
00239 def reset(self):
00240 self.uiText.clear()
00241 self.uiText.setToolTip('')
00242
00243 def showValue(self):
00244 res = self.record.value(self.name)
00245 if res:
00246 self.uiText.setCursorPosition( 0 )
00247 self.uiText.setText( res )
00248 self.uiText.setToolTip( res )
00249 self.pushOpen.setIcon( QIcon( ":/images/folder.png"))
00250 self.pushOpen.setToolTip( _("Open") )
00251
00252
00253 self.pushOpen.setEnabled( True )
00254 else:
00255 self.uiText.clear()
00256 self.uiText.setToolTip('')
00257 self.pushOpen.setIcon( QIcon( ":/images/find.png"))
00258 self.pushOpen.setToolTip( _("Search") )
00259
00260 self.pushOpen.setEnabled( not self.isReadOnly() )
00261
00262 def menuEntries(self):
00263 if not self.menuLoaded:
00264 related = Rpc.session.execute('/object', 'execute', 'ir.values', 'get', 'action', 'client_action_relate', [(self.attrs['relation'], False)], False, Rpc.session.context)
00265 actions = [x[2] for x in related]
00266 for action in actions:
00267 f = lambda action: lambda: self.executeRelation(action)
00268 self.newMenuEntries.append(('... '+ action['name'], f(action), False))
00269 self.menuLoaded = True
00270
00271
00272 value = self.record.value(self.name)
00273 if value:
00274 value = True
00275 else:
00276 value = False
00277 currentEntries = []
00278 for x in self.newMenuEntries:
00279 currentEntries.append( (x[0], x[1], value) )
00280 return currentEntries
00281
00282 def executeRelation(self, action):
00283 id = self.record.get()[self.name]
00284 group = RecordGroup( self.attrs['relation'] )
00285 group.load( [id] )
00286 record = group.modelByIndex( 0 )
00287 action['domain'] = record.evaluateExpression( action['domain'], checkLoad=False)
00288 action['context'] = str( record.evaluateExpression( action['context'], checkLoad=False) )
00289 Api.instance.executeAction( action )
00290
00291 def executeAction(self, type):
00292 id = self.record.get()[self.name]
00293 Api.instance.executeKeyword(type, {
00294 'model':self.attrs['relation'],
00295 'id': id or False,
00296 'ids':[id],
00297 'report_type': 'pdf'
00298 }, Rpc.session.context)
00299
00300 class ManyToOneFieldDelegate( AbstractFieldDelegate ):
00301 def __init__(self, parent, attributes):
00302 AbstractFieldDelegate.__init__(self, parent, attributes)
00303 self.currentEditor = None
00304 self.currentValue = None
00305
00306 def menuEntries(self, record):
00307 self.record = record
00308
00309 newMenuEntries = []
00310 newMenuEntries.append((_('Open'), lambda: self.open(), False))
00311 newMenuEntries.append((None, None, None))
00312 newMenuEntries.append((_('Action'), lambda: self.executeAction(record, 'client_action_multi'), False))
00313 newMenuEntries.append((_('Report'), lambda: self.executeAction(record, 'client_print_multi'), False))
00314 newMenuEntries.append((None, None, None))
00315 related = Rpc.session.execute('/object', 'execute', 'ir.values', 'get', 'action', 'client_action_relate', [(self.attributes['relation'], False)], False, Rpc.session.context)
00316 actions = [x[2] for x in related]
00317 for action in actions:
00318 f = lambda action: lambda: self.executeRelation(record, action)
00319 newMenuEntries.append(('... '+ action['name'], f(action), False))
00320
00321
00322 value = record.value(self.name)
00323 if value:
00324 value = True
00325 else:
00326 value = False
00327 currentEntries = []
00328 for x in newMenuEntries:
00329 currentEntries.append( (x[0], x[1], value) )
00330 return currentEntries
00331
00332 def executeRelation(self, record, action):
00333 id = record.get()[self.name]
00334 group = RecordGroup( self.attributes['relation'] )
00335 group.load( [id] )
00336 record = group.modelByIndex( 0 )
00337 action['domain'] = record.evaluateExpression( action['domain'], checkLoad=False)
00338 action['context'] = str( record.evaluateExpression( action['context'], checkLoad=False) )
00339 Api.instance.executeAction( action )
00340
00341 def executeAction(self, record, type):
00342 id = record.get()[self.name]
00343 Api.instance.executeKeyword(type, {
00344 'model': self.attributes['relation'],
00345 'id': id or False,
00346 'ids': [id],
00347 'report_type': 'pdf'
00348 }, Rpc.session.context)
00349
00350 def createEditor(self, parent, option, index):
00351 widget = AbstractFieldDelegate.createEditor(self, parent, option, index)
00352 if widget:
00353
00354 self.scNew = QShortcut( widget )
00355 self.scNew.setContext( Qt.WidgetShortcut )
00356 self.scNew.setKey( Shortcuts.CreateInField )
00357 self.connect( self.scNew, SIGNAL('activated()'), self.new )
00358
00359 self.scSearch = QShortcut( widget )
00360 self.scSearch.setContext( Qt.WidgetShortcut )
00361 self.scSearch.setKey( Shortcuts.SearchInField )
00362 self.connect( self.scSearch, SIGNAL('activated()'), self.open )
00363 self.currentEditor = widget
00364
00365 self.record = index.model().recordFromIndex( index )
00366 return widget
00367
00368 def open(self):
00369
00370
00371
00372
00373
00374 if self.record.value(self.name):
00375
00376
00377
00378 if QApplication.keyboardModifiers() & Qt.ControlModifier:
00379 model = self.attributes['relation']
00380 id = self.record.get()[self.name]
00381 Api.instance.createWindow(False, model, id, [], 'form', mode='form,tree')
00382 else:
00383 dialog = ScreenDialog( self.parent() )
00384 dialog.setAttributes( self.attributes )
00385 dialog.setContext( self.record.fieldContext( self.name ) )
00386 dialog.setDomain( self.record.domain(self.name) )
00387 dialog.setup( self.attributes['relation'], self.record.get()[self.name] )
00388 if dialog.exec_() == QDialog.Accepted:
00389 self.record.setValue(self.name, dialog.record)
00390 else:
00391 self.search('')
00392
00393
00394
00395
00396
00397 def search(self, name):
00398 domain = self.record.domain( self.name )
00399 context = self.record.context()
00400 ids = Rpc.session.execute('/object', 'execute', self.attributes['relation'], 'name_search', name, domain, 'ilike', context, False)
00401 if ids and len(ids)==1:
00402 self.record.setValue( self.name, ids[0] )
00403 else:
00404 dialog = SearchDialog(self.attributes['relation'], sel_multi=False, ids=[x[0] for x in ids], context=context, domain=domain)
00405 if dialog.exec_() == QDialog.Accepted and dialog.result:
00406 id = dialog.result[0]
00407 name = Rpc.session.execute('/object', 'execute', self.attributes['relation'], 'name_get', [id], Rpc.session.context)[0]
00408 self.record.setValue(self.name, name)
00409
00410 def new(self):
00411 dialog = ScreenDialog( self.currentEditor )
00412 dialog.setAttributes( self.attributes )
00413 dialog.setContext( self.record.fieldContext( self.name ) )
00414 dialog.setDomain( self.record.domain(self.name) )
00415 dialog.setup( self.attributes['relation'] )
00416 if dialog.exec_() == QDialog.Accepted:
00417 self.record.setValue(self.name, dialog.record)
00418
00419 def setModelData(self, editor, kooModel, index):
00420
00421 model = kooModel.recordFromIndex( index )
00422
00423 if not unicode(editor.text()):
00424 model.setValue( self.name, False )
00425 return
00426
00427 if unicode( kooModel.data( index, Qt.DisplayRole ).toString() ) == unicode( editor.text() ):
00428 return
00429
00430 domain = model.domain( self.name )
00431 context = model.context()
00432 ids = Rpc.session.execute('/object', 'execute', self.attributes['relation'], 'name_search', unicode( editor.text() ), domain, 'ilike', context, False)
00433 if ids and len(ids)==1:
00434 model.setValue( self.name, ids[0] )
00435 else:
00436 dialog = SearchDialog(self.attributes['relation'], sel_multi=False, ids=[x[0] for x in ids], context=context, domain=domain)
00437 if dialog.exec_() == QDialog.Accepted and dialog.result:
00438 id = dialog.result[0]
00439 name = Rpc.session.execute('/object', 'execute', self.attributes['relation'], 'name_get', [id], Rpc.session.context)[0]
00440
00441
00442
00443
00444
00445
00446 model.setValue( self.name, name )