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 )