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