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 import gettext
00031 from xml.parsers import expat
00032 
00033 from Koo.Common import Api
00034 from Koo.Common import Common
00035 from Koo.Common import Debug
00036 from Koo.Common.ViewSettings import *
00037 from Koo.Common import Help
00038 from Koo import Rpc
00039 
00040 from Koo.Fields.FieldDelegateFactory import *
00041 
00042 from Koo.Model.KooModel import KooModel
00043 from Koo.Model.Group import *
00044 
00045 from PyQt4.QtCore import *
00046 from PyQt4.QtGui import *
00047 from PyQt4.uic import *
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 class TreeParser:
00062         def tagStart(self, name, attrs):
00063                 if name=='tree':
00064                         self.title = attrs.get('string',_('Tree'))
00065                         self.toolbar = bool(attrs.get('toolbar',False))
00066                 elif name=='field':
00067                         if 'icon' in attrs:
00068                                 self.fieldsOrder.append(str(attrs['icon']))
00069                         self.fieldsOrder.append(str(attrs['name']))
00070                 else:
00071                         Debug.error( 'unknown tag: ' + str(name) )
00072 
00073         
00074         
00075         
00076         def parse(self, xmlData):
00077                 self.fieldsOrder = []
00078 
00079                 psr = expat.ParserCreate()
00080                 psr.StartElementHandler = self.tagStart
00081                 psr.Parse(xmlData.encode('utf-8'))
00082 
00083 (TreeWidgetUi, TreeWidgetBase) = loadUiType( Common.uiPath('tree.ui') )
00084 
00085 
00086 class TreeWidget( QWidget, TreeWidgetUi ): 
00087         def __init__( self, view, model, domain=None, context=None, name=False, parent=None ):
00088                 QWidget.__init__(self,parent)
00089                 TreeWidgetUi.__init__(self)
00090                 self.setupUi( self )
00091 
00092                 if domain is None:
00093                         domain = []
00094                 if context is None:
00095                         context = {}
00096 
00097                 self.uiSplitter.setStretchFactor( 0, 0 )
00098                 self.uiSplitter.setStretchFactor( 1, 2 )
00099 
00100                 self.context = context
00101                 self.model = view['model']
00102                 if view.get('field_parent', False):
00103                         self.domain = []
00104                 else:
00105                         self.domain = domain
00106                 self.view = view
00107 
00108                 
00109                 
00110                 
00111                 self.childrenField = self.view['field_parent']
00112 
00113                 self.handlers = {
00114                         'Switch': self.editCurrentItem,
00115                         'Print': self.printCurrent,
00116                         'PrintHtml': self.printHtmlCurrent,
00117                         'Reload': self.reload,
00118                         'StoreViewSettings': self.storeViewState,
00119                 }
00120 
00121                 parser = TreeParser()
00122                 parser.parse( view['arch'] )
00123                 self.toolbar = parser.toolbar
00124 
00125                 
00126                 self.fields = Rpc.session.execute('/object', 'execute', self.model, 'fields_get', parser.fieldsOrder + [self.childrenField], self.context)
00127 
00128                 self.treeModel = KooModel( self )
00129                 self.treeModel.setFields( self.fields )
00130                 self.treeModel.setFieldsOrder( parser.fieldsOrder )
00131                 self.treeModel.setIconForField( 'icon', 'name')
00132                 self.treeModel.setChildrenForField( self.childrenField, parser.fieldsOrder[0] )
00133                 self.treeModel.setShowBackgroundColor( False )
00134                 if model == 'ir.ui.menu':
00135                         self.treeModel.setShowToolTips( False )
00136 
00137                 self.listModel = KooModel( self )
00138                 self.listModel.setMode( KooModel.ListMode )
00139                 self.listModel.setFields( self.fields )
00140                 if 'name' in parser.fieldsOrder:
00141                         self.listModel.setFieldsOrder( ['name'] )
00142                 else:
00143                         self.listModel.setFieldsOrder( parser.fieldsOrder )
00144                 self.listModel.setIconForField( 'icon', 'name' )
00145                 self.listModel.setShowBackgroundColor( False )
00146 
00147                 self.group = RecordGroup( self.model, self.fields, context = self.context )
00148                 self.group.setDomain( domain )
00149                 if self.toolbar:
00150                         self.listModel.setRecordGroup( self.group )
00151                 else:
00152                         self.treeModel.setRecordGroup( self.group )
00153 
00154                 self.listModelProxy = QSortFilterProxyModel( self )
00155                 self.listModelProxy.setSourceModel( self.listModel )
00156                 self.listModelProxy.setFilterKeyColumn( 0 )
00157                 self.listModelProxy.setFilterCaseSensitivity( Qt.CaseInsensitive )
00158                 self.listModelProxy.setFilterFixedString( "partner" )
00159 
00160                 self.uiTree.setModel( self.treeModel )
00161                 self.uiList.setModel( self.listModel )
00162 
00163                 self.connect(self.uiTree, SIGNAL('activated( QModelIndex )'), self.open )
00164 
00165                 for column in xrange(len(parser.fieldsOrder)):
00166                         fieldName = parser.fieldsOrder[column]
00167                         delegate = FieldDelegateFactory.create( self.fields[fieldName]['type'], self.uiTree, self.fields[fieldName] )
00168                         self.uiTree.setItemDelegateForColumn( column, delegate )
00169 
00170 
00171                 self.treeAllExpandedState = {}
00172                 self.treeState = {}
00173                 if self.toolbar:
00174                         
00175                         self.connect(self.uiTree,SIGNAL('expanded( QModelIndex )'), self.saveIndexState )
00176                         self.connect(self.uiTree,SIGNAL('collapsed( QModelIndex )'), self.saveIndexState )
00177 
00178                 self.connect(self.pushShortcuts, SIGNAL('clicked()'), self.editShortcuts)
00179                 self.connect(self.pushAddShortcut, SIGNAL('clicked()'), self.addShortcut)
00180                 self.connect(self.pushRemoveShortcut, SIGNAL('clicked()'), self.removeShortcut)
00181                 self.connect(self.pushExpand, SIGNAL('clicked()'), self.expand)
00182                 self.connect(self.uiShortcuts, SIGNAL('activated(QModelIndex)'), self.goToShortcut)
00183                 self.connect(self.uiList.selectionModel(),SIGNAL('currentChanged(QModelIndex, QModelIndex)'),self.mainMenuClicked)
00184 
00185                 if name:
00186                         self.name = name
00187                 else:
00188                         self.name = parser.title
00189                 
00190                 
00191                 if self.model == 'ir.ui.menu':
00192                         scFields = Rpc.session.execute('/object', 'execute', 'ir.ui.view_sc', 'fields_get', ['res_id', 'name'])
00193                         self.shortcutsGroup = RecordGroup( 'ir.ui.view_sc', scFields, context = self.context )
00194                         self.shortcutsGroup.setDomain( [('user_id','=',Rpc.session.uid), ('resource','=',model)] )
00195                         self.shortcutsModel = KooModel( self )
00196                         self.shortcutsModel.setMode( KooModel.ListMode )
00197                         self.shortcutsModel.setFields( scFields )
00198                         self.shortcutsModel.setFieldsOrder( ['name'] )
00199                         self.shortcutsModel.setRecordGroup( self.shortcutsGroup )
00200                         self.shortcutsModel.setShowBackgroundColor( False )
00201                         self.uiShortcuts.setModel( self.shortcutsModel )
00202                         self.uiShortcutsContainer.show()
00203                 else:
00204                         self.uiShortcutsContainer.hide()
00205                 
00206                 if not parser.toolbar:
00207                         self.uiList.hide()
00208                 else:
00209                         
00210                         self.uiList.setCurrentIndex( self.uiList.moveCursor( QAbstractItemView.MoveHome, Qt.NoModifier ) )
00211                         self.updateTree()
00212                 self.restoreViewState()
00213 
00214         def saveIndexState(self, index):
00215                 mainKey = self.uiList.currentIndex().row()
00216                 key = ( index.row(), index.column(), index.internalPointer() )
00217                 if not mainKey in self.treeState:
00218                         self.treeState[mainKey] = {}
00219                 self.treeState[mainKey][ key ] = self.uiTree.isExpanded( index )
00220 
00221         def restoreIndexStates(self):
00222                 mainKey = self.uiList.currentIndex().row()
00223                 if not mainKey in self.treeState:
00224                         return
00225                 subtree = self.treeState[ mainKey ]
00226                 for key, value in subtree.iteritems():
00227                         index = self.treeModel.createIndex( key[0], key[1], key[2] )
00228                         self.uiTree.setExpanded( index, value )
00229 
00230         def updateTree(self):
00231                 item = self.uiList.currentIndex()
00232                 if not item.isValid():
00233                         return
00234                 id = item.data( Qt.UserRole ).toInt()[0]
00235                 if not id:
00236                         return
00237                 m = self.group[ id ]
00238                 group = m.value( self.childrenField )
00239                 group.addFields( self.group.fields )
00240                 self.treeModel.setRecordGroup( group )
00241         
00242         def mainMenuClicked( self, currentIndex, previousIndex ):
00243                 if self.toolbar:
00244                         self.treeAllExpandedState[ self.listModel.id( previousIndex ) ] = self.pushExpand.isChecked()
00245                 self.updateTree()
00246                 if self.toolbar:
00247                         self.setAllExpanded( self.treeAllExpandedState.get( self.listModel.id( currentIndex ), False ) )
00248                         self.restoreIndexStates()
00249 
00250         def setAllExpanded(self, value):
00251                 self.pushExpand.setChecked( value )
00252                 if value:
00253                         self.uiTree.expandAll()
00254                         self.pushExpand.setIcon( QIcon( ':/images/up.png' ) )
00255                 else:
00256                         self.uiTree.collapseAll()
00257                         self.pushExpand.setIcon( QIcon( ':/images/down.png' ) )
00258 
00259         def reload(self):
00260                 QApplication.setOverrideCursor( Qt.WaitCursor )
00261                 try:
00262                         self.group.update()
00263                         self.uiList.setCurrentIndex( self.uiList.moveCursor( QAbstractItemView.MoveHome, Qt.NoModifier ) )
00264                         self.treeAllExpandedState = {}
00265                         self.treeState = {}
00266                         self.updateTree()
00267                         
00268                         
00269                         
00270                         if self.model == 'ir.ui.menu':
00271                                 self.shortcutsGroup.update()
00272                                 self.emit( SIGNAL('shortcutsChanged'), self.model )
00273                 except Rpc.RpcException, e:
00274                         pass
00275                 QApplication.restoreOverrideCursor()
00276 
00277         
00278         
00279         
00280         def printCurrent(self):
00281                 self.executeAction(keyword='client_print_multi', report_type='html')
00282 
00283         def printHtmlCurrent(self):
00284                 self.executeAction(keyword='client_print_multi')
00285 
00286         def executeAction(self, keyword='tree_but_action', id=None, report_type='pdf'):
00287                 if id:
00288                         Api.instance.executeKeyword(keyword, {'model':self.model, 'id':id, 'report_type':report_type, 'ids': [id]}, self.context)
00289                 else:
00290                         QMessageBox.information( self, _('Information'), _('No resource selected!'))
00291 
00292         def open(self, idx):
00293                 id = self.treeModel.id( idx )
00294                 if id:
00295                         self.executeAction( 'tree_but_open', id )
00296 
00297         def editCurrentItem(self):
00298                 id = self.treeModel.id( self.uiTree.currentIndex() )
00299                 if id:
00300                         Api.instance.createWindow(None, self.model, id, self.domain)
00301                 else:
00302                         QMessageBox.information(self, _('Information'), _('No resource selected!'))
00303 
00304         def removeShortcut(self):
00305                 id = self.currentShortcutId()
00306                 if not id:
00307                         return
00308                 Rpc.session.execute('/object', 'execute', 'ir.ui.view_sc', 'unlink', [id], self.context)
00309                 self.shortcutsGroup.update()
00310                 self.emit(SIGNAL('shortcutsChanged'), self.model)
00311 
00312         def editShortcuts(self):
00313                 domain = [('user_id', '=', Rpc.session.uid), ('resource', '=', self.model)]
00314                 Api.instance.createWindow(None, 'ir.ui.view_sc', domain=domain, context=self.context, mode='tree,form')
00315 
00316         def addShortcut(self):
00317                 id = self.treeModel.id( self.uiTree.currentIndex() )
00318                 if id == None:
00319                         QMessageBox.information( self, _('No item selected'), _('Please select an element from the tree to add a shortcut to it.') )
00320                         return
00321                 res = Rpc.session.execute('/object', 'execute', self.model, 'name_get', [id], Rpc.session.context)
00322                 for (id,name) in res:
00323                         uid = Rpc.session.uid
00324                         Rpc.session.execute('/object', 'execute', 'ir.ui.view_sc', 'create', {'resource':self.model, 'user_id':uid, 'res_id':id, 'name':name}, self.context)
00325                 self.shortcutsGroup.update()
00326                 self.emit( SIGNAL('shortcutsChanged'), self.model )
00327 
00328         def goToShortcut(self, index):
00329                 id = self.currentShortcutId()
00330                 if not id:
00331                         return
00332                 m = self.shortcutsGroup[ id ]
00333                 
00334                 
00335                 
00336                 id = self.shortcutsGroup.fieldObjects[ 'res_id' ].get( m )
00337                 if not id:
00338                         return
00339                 self.executeAction('tree_but_open', id)
00340 
00341         def expand(self):
00342                 if self.toolbar:
00343                         
00344                         
00345                         
00346                         mainKey = self.uiList.currentIndex().row()
00347                         if mainKey in self.treeState:
00348                                 del self.treeState[ mainKey ]
00349                 if self.pushExpand.isChecked():
00350                         self.uiTree.expandAll()
00351                         self.pushExpand.setIcon( QIcon( ':/images/up.png' ) )
00352                 else:
00353                         self.uiTree.collapseAll()
00354                         self.pushExpand.setIcon( QIcon( ':/images/down.png' ) )
00355 
00356         def currentShortcutId(self):
00357                 item = self.uiShortcuts.currentIndex()
00358                 if not item.isValid():
00359                         return None
00360                 id = item.data( Qt.UserRole ).toInt()[0]
00361                 return id
00362 
00363         
00364         def canClose(self):
00365                 self.storeViewState()
00366                 return True
00367         
00368         def storeViewState(self):
00369                 id = self.view['view_id']
00370                 if not id:
00371                         return
00372                 header = self.uiTree.header()
00373                 ViewSettings.store( id, str( header.saveState().toBase64() ) )
00374                 
00375         def restoreViewState(self):
00376                 id = self.view['view_id']
00377                 if not id:
00378                         return
00379                 settings = ViewSettings.load( id )
00380                 if not settings:
00381                         return
00382                 header = self.uiTree.header()
00383                 header.restoreState( QByteArray.fromBase64( settings ) )
00384                 
00385         def actions(self):
00386                 return []
00387 
00388         def switchViewMenu(self):
00389                 return None
00390 
00391         def help(self, button):
00392                 if self.model != 'ir.ui.menu':
00393                         return
00394 
00395                 idx = self.uiTree.currentIndex()
00396                 record = self.treeModel.recordFromIndex( idx )
00397                 if not record:
00398                         return
00399 
00400                 QApplication.setOverrideCursor( Qt.WaitCursor )
00401                 helpWidget = Help.HelpWidget( button )
00402                 helpWidget.setLabel( record.value('name') )
00403                 helpWidget.setFilter( record.id )
00404                 helpWidget.setType( helpWidget.MenuType )
00405                 helpWidget.show()
00406                 QApplication.restoreOverrideCursor()
00407                 
00408