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 import re
00032 from Koo.Common import Common
00033 from Koo.Common import Numeric
00034 from Koo.Common import Api
00035 
00036 from Koo import Rpc
00037 from Koo.Model.Group import RecordGroup
00038 
00039 from PyQt4.QtGui import *
00040 from PyQt4.QtCore import *
00041 from PyQt4.uic import *
00042 from PyQt4.QtWebKit import *
00043 from PyQt4.QtNetwork import *
00044 
00045 
00046 (FullTextSearchDialogUi, FullTextSearchDialogBase) = loadUiType( Common.uiPath('full_text_search.ui') )
00047 
00048 
00049 
00050 
00051 
00052 class FullTextSearchDialog( QDialog, FullTextSearchDialogUi ):
00053         def __init__(self, parent = None):
00054                 QDialog.__init__( self, parent )
00055                 FullTextSearchDialogUi.__init__( self )
00056                 self.setupUi( self )
00057                 
00058                 self.setModal( True )
00059 
00060                 self.result = None
00061 
00062                 self.setQueriesEnabled( False, _('Loading...') )
00063 
00064                 self.title = _('Full Text Search')
00065                 self.title_results = _('Full Text Search (%%d result(s))')
00066 
00067                 self.setWindowTitle( self.title )
00068                 self.uiWeb.page().setLinkDelegationPolicy( QWebPage.DelegateAllLinks )
00069                 self.connect( self.uiWeb, SIGNAL('linkClicked(QUrl)'), self.open )
00070 
00071                 self.shortcuts = {}
00072                 self.related = []
00073                 self.limit = 10 
00074                 self.offset = 0
00075                 self.pushNext.setEnabled( False )
00076                 self.pushPrevious.setEnabled( False )
00077 
00078                 self.connect( self.uiHelp, SIGNAL('linkActivated(QString)'), self.showHelp )
00079                 self.connect( self.pushClose, SIGNAL( "clicked()"), self.accept )
00080                 self.connect( self.pushFind, SIGNAL( "clicked()"), self.find )
00081                 self.connect( self.pushPrevious, SIGNAL( "clicked()" ), self.previous )
00082                 self.connect( self.pushNext, SIGNAL( "clicked()" ), self.next )
00083                 self.show()
00084 
00085                 QApplication.setOverrideCursor( Qt.WaitCursor )
00086                 QTimer.singleShot( 0, self.initGui )
00087 
00088         def showHelp(self, link):
00089                 QApplication.postEvent( self.sender(), QEvent( QEvent.WhatsThis ) )
00090 
00091         def initGui(self):
00092                 try:
00093                         answer = Rpc.session.call('/fulltextsearch', 'indexedModels', Rpc.session.context )
00094                         self.uiModel.addItem( _('(Everywhere)'), QVariant( False ) )    
00095                         for x in answer:
00096                                 self.uiModel.addItem( x['name'], QVariant( x['id'] ) )
00097                         if len(answer) == 0:
00098                                 self.setQueriesEnabled( False, _('<b>Full text search is not configured.</b><br/>Go to <i>Administration - Configuration - Full Text Search - Indexes</i>. Then add the fields you want to be indexed and finally use <i>Update Full Text Search</i>.') )
00099                                 QApplication.restoreOverrideCursor()
00100                                 return
00101                 except:
00102                         self.setQueriesEnabled( False, _('<b>Full text search module not installed.</b><br/>Go to <i>Administration - Modules administration - Uninstalled Modules</i> and add the <i>full_text_search</i> module.') )
00103                         QApplication.restoreOverrideCursor()
00104                         return
00105                 self.setQueriesEnabled( True )
00106                 self.uiText.setFocus()
00107                 if QApplication.keyboardModifiers() & Qt.AltModifier:
00108                         clipboard = QApplication.clipboard()
00109                         if clipboard.supportsFindBuffer():
00110                                 text = clipboard.text( QClipboard.FindBuffer )
00111                         elif clipboard.supportsSelection():
00112                                 text = clipboard.text( QClipboard.Selection )
00113                         else:
00114                                 text = clipboard.text( QClipboard.Clipboard )
00115                         self.uiText.setText( text )
00116                         self.find()
00117                 QApplication.restoreOverrideCursor()
00118 
00119         def setQueriesEnabled(self, value, text = ''): 
00120                 self.uiModel.setEnabled( value )
00121                 self.pushFind.setEnabled( value )
00122                 self.uiText.setEnabled( value )
00123                 self.uiWeb.page().mainFrame().setHtml( "<span style='font-size: large'>%s</span>" % text )
00124 
00125         def textToQuery(self):
00126                 q = unicode( self.uiText.text() ).strip()
00127                 return re.sub(' +', '|', q)
00128 
00129         def query(self):
00130                 QApplication.setOverrideCursor( Qt.WaitCursor )
00131                 if self.uiModel.currentIndex() == 0:
00132                         model = False
00133                 else:
00134                         model = unicode( self.uiModel.itemData( self.uiModel.currentIndex() ).toString() )
00135                 
00136                 answer = Rpc.session.execute('/fulltextsearch', 'search', self.textToQuery(), self.limit+1, self.offset , model, Rpc.session.context)
00137                 if len(answer) < self.limit:
00138                         self.pushNext.setEnabled( False )
00139                 else:
00140                         
00141                         answer = answer[:-1]
00142                         self.pushNext.setEnabled( True )
00143                 if self.offset == 0:
00144                         self.pushPrevious.setEnabled( False )
00145                 else:
00146                         self.pushPrevious.setEnabled( True )
00147                 self.showResults( answer )
00148                 QApplication.restoreOverrideCursor()
00149 
00150         def showResults(self, answer):
00151                 for shortcut in self.shortcuts.keys():
00152                         shortcut.setParent( None )
00153                 self.shortcuts = {}
00154                 number = 1
00155                 page = ''
00156                 for item in answer:
00157                         
00158                         related = Rpc.session.execute('/object', 'execute', 'ir.values', 'get', 'action', 'client_action_relate', [(item['model_name'], False)], False, Rpc.session.context)
00159                         actions = [x[2] for x in related]
00160                         block = []
00161                         related = ''
00162                         for action in actions:
00163                                 f = lambda action: lambda: self.executeRelation(action)
00164                                 action['model_name'] = item['model_name']
00165                                 self.related.append( action )
00166                                 block.append( "<a href='relate/%d/%d'>%s</a>" % ( len(self.related)-1, item['id'], action['name'] ) )
00167                                 if len(block) == 3:
00168                                         related += '<div style="padding-left: 40px">%s</div>' % ' - '.join( block )
00169                                         block = []
00170                         if block:
00171                                 related += '<div style="padding-left: 40px">%s</div>' % ' - '.join( block )
00172 
00173                         if related:
00174                                 related = '<div style="padding-top: 5px">%s</div>' % related
00175 
00176                         
00177                         url = 'open/%s/%s' % ( item['model_name'], item['id'] )
00178 
00179                         
00180                         
00181                         if number <= 10:
00182                                 self.shortcut = QShortcut( self )
00183                                 self.shortcut.setKey( 'Ctrl+%s' % number )
00184                                 self.shortcut.setContext( Qt.WidgetWithChildrenShortcut )
00185                                 self.connect( self.shortcut, SIGNAL('activated()'), self.openShortcut )
00186                                 self.shortcuts[ self.shortcut ] = url
00187                                 shortcut = ' - <span style="color: green; font-size: medium">[Ctrl+%d]</span>' % ( number % 10 )
00188                         else:
00189                                 shortcut = ''
00190                         number += 1
00191 
00192                         
00193                         page += """
00194                                 <div style="padding: 5px; font-size: large">
00195                                 <a href="%(url)s">%(model_label)s: %(name)s</a>  %(shortcut)s - <span style="font-size: medium">[ %(ranking).2f ]</span></a>
00196                                 <div style="font-size: medium">%(headline)s</div>
00197                                 <div style="font-size: medium">%(related)s</div>
00198                                 </div>""" % {
00199                                 'url': url,
00200                                 'model_label': item['model_label'],
00201                                 'name': item['name'],
00202                                 'shortcut': shortcut,
00203                                 'ranking': item['ranking'],
00204                                 'headline': item['headline'],
00205                                 'related': related,
00206                         }
00207 
00208                 page = '<html>%s</html>' % page
00209                 self.uiWeb.page().mainFrame().setHtml( page )
00210                 
00211                 
00212         def previous(self):
00213                 self.offset = max(0, self.offset - self.limit )
00214                 self.query()
00215                 
00216         def next(self):
00217                 self.offset = self.offset + self.limit
00218                 self.query()
00219 
00220         def find(self):
00221                 self.offset = 0
00222                 self.query()
00223 
00224         def openShortcut( self ):
00225                 self.open( self.shortcuts[ self.sender() ] )
00226 
00227         def open( self, url ):
00228                 QApplication.setOverrideCursor( Qt.WaitCursor )
00229                 if isinstance( url, QUrl ):
00230                         url = unicode( url.toString() )
00231                 url = url.split('/')
00232                 if url[0] == 'open':
00233                         model = url[1]
00234                         id = int(url[2])
00235 
00236                         if model == 'ir.ui.menu':
00237                                 Api.instance.executeKeyword('tree_but_open', {
00238                                         'model': model, 
00239                                         'id': id, 
00240                                         'report_type': 'pdf', 
00241                                         'ids': [id]
00242                                 }, Rpc.session.context)
00243                         else:
00244                                 Api.instance.createWindow(None, model, id, view_type='form', mode='form,tree')
00245                 elif url[0] == 'relate':
00246                         action = int(url[1])
00247                         id = int(url[2])
00248                         self.executeRelation( self.related[ action ], id )
00249                 QApplication.restoreOverrideCursor()
00250                 self.accept()
00251         
00252         def executeRelation(self, action, id):
00253                 group = RecordGroup( action['model_name'] )
00254                 group.load( [id] )
00255                 record = group.modelByIndex( 0 )
00256                 action['domain'] = record.evaluateExpression( action['domain'], checkLoad=False)
00257                 action['context'] = str( record.evaluateExpression( action['context'], checkLoad=False) )
00258                 Api.instance.executeAction( action )
00259 
00260