root/branch/twedit/findandreplacedlg.py

Revision 1591, 63.4 kB (checked in by mswat, 16 months ago)

converted print statements into dbgMsg with switchable debug output option

Line 
1import re
2from PyQt4.QtCore import *
3from PyQt4.QtGui import *
4import PyQt4.QtCore as QtCore
5# import ui_findandreplacedlg
6
7import os
8from PyQt4.QtCore import *
9from PyQt4.QtGui import *
10# import ui_findandreplacedlg
11import ui_findinfilesdlg
12
13ALL_IN_FILES=0
14ALL_IN_ALL_OPEN_DOCS=1
15ALL_IN_CURRENT_DOC=2
16
17MAC = "qt_mac_set_native_menubar" in dir()
18class FindInFilesResults:
19    def __init__(self,_fileName="",_textToFind=""):
20        self.fileName=_fileName
21        self.textToFind=_textToFind
22        self.lineOccurences=[] # format of each list element is [lineNumber, lineText]
23        self.lastLineAdded=-1
24        self.totalHits=0
25    def addLineWithText(self, _lineNumber,_text):
26        if self.lastLineAdded!=_lineNumber:
27            self.lineOccurences.append([_lineNumber,_text])
28            self.lastLineAdded=_lineNumber
29           
30        self.totalHits+=1
31       
32    def lastLineNumberAdded(self):
33        return 
34    #this function will properly format find in files result so that they can be properly interpretted by the lexer
35    #have to make lexer more robust though...
36    def produceSummaryRepr(self,findInFilesResultsList,_textToFind=""):
37        findInFileResultRepr="" 
38        allHits=0
39        numberOfFiles=len(findInFilesResultsList)
40        for findInFileResult in findInFilesResultsList:
41            allHits+=findInFileResult.totalHits
42           
43           
44            findInFileResultRepr+=findInFileResult.__str__()
45        hitsString="hits"
46        if allHits==1:   
47            hitString="hit"
48        filesString="files"
49        if numberOfFiles==1:
50            filesString="file"
51       
52        headerFindInFileResultRepr="Search \""+str(_textToFind)+"\" ("+str(allHits)+" "+ hitsString+" in "+str(numberOfFiles)+" " +filesString+")\n"       
53            # print findInFileResult
54        # print findInFileResultRepr
55       
56        return headerFindInFileResultRepr+findInFileResultRepr
57    def __str__(self):
58        # header="Search \""+str(self.textToFind)+"\"\n"
59        # rep=header
60        rep="  File: "+os.path.abspath(str(self.fileName)) # "normalizing" file name to make sure \ and / are used in a consistent manner
61        if self.totalHits==1:
62            rep+=" (1 hit)"
63        else:   
64            rep+=" ("+str(self.totalHits)+" hits)"
65        rep+="\n"
66        for lineData in self.lineOccurences:
67            rep+="    Line "+str(lineData[0])+":    "+str(lineData[1])
68        return rep   
69           
70   
71class FindAndReplaceHistory:
72    def __init__(self, _historyLength=20):   
73        self.findHistory=QStringList()
74        self.replaceHistory=QStringList()
75        self.historyLength=_historyLength
76        self.textToFind=""
77        self.replaceText=""
78        self.wo=False # words only
79        self.re=False # regular experessions flag
80        self.cs=False # case sensitive flag
81        self.wrap=True # start from the beginnig after reaching the end of text
82        self.syntaxIndex=0
83        self.inSelection=False
84        self.inAllSubfolders=False
85        self.opacity=75
86        self.opacityOnLosingFocus=True
87        self.opacityAlways=False
88        self.transparencyEnable=True
89       
90
91        # self.findHistoryIF=QStringList()
92        # self.replaceHistoryIF=QStringList()
93        self.filtersHistoryIF=QStringList()
94        self.directoryHistoryIF=QStringList()       
95        self.textToFindIF=""
96        self.replaceTextIF=""
97        self.filtersIF=""
98        self.directoryIF=""
99       
100       
101
102       
103    def newSearchParameters(self,_text,_re,_cs,_wo,_wrap,_inSelection):
104        flag=False
105        if self.textToFind!=_text:
106            self.textToFind = _text       
107            self.findHistory.prepend(self.textToFind)
108            self.findHistory.removeDuplicates()
109            if self.findHistory.count()>=self.historyLength:
110                self.findHistory.removeAt(self.findHistory.count() - 1)
111                # looks like this does not work in PyQt4
112                # self.findHistory.removeLast()
113               
114            # print self.findHistory
115            flag=True
116        if self.re!=_re:
117            self.re=_re
118            flag=True
119        if self.cs!=_cs:
120            self.cs=_cs
121            flag=True
122        if self.wo!=_wo:
123            self.wo=_wo
124            flag=True           
125        if self.wrap!=_wrap:
126            self.wrap=_wrap
127            flag=True
128        if self.inSelection!=_inSelection:
129            self.inSelection=_inSelection
130            flag=True
131           
132        return flag   
133    def newSearchParametersIF(self,_text,_filters,_directory):
134        flag=False
135        if self.textToFindIF!=_text:
136            self.textToFindIF = _text       
137            self.findHistory.prepend(self.textToFindIF)
138            self.findHistory.removeDuplicates()
139            if self.findHistory.count()>=self.historyLength:
140                self.findHistory.removeLast()
141               
142            flag=True   
143           
144        if self.filtersIF!=_filters:
145            self.filtersIF = _filters       
146            self.filtersHistoryIF.prepend(self.filtersIF)
147            self.filtersHistoryIF.removeDuplicates()
148            if self.filtersHistoryIF.count()>=self.historyLength:
149                self.filtersHistoryIF.removeLast()
150               
151            flag=True
152           
153            # print self.findHistory
154        if self.directoryIF!=_directory:
155            self.directoryIF = _directory       
156            self.directoryHistoryIF.prepend(self.directoryIF)
157            self.directoryHistoryIF.removeDuplicates()
158            if self.directoryHistoryIF.count()>=self.historyLength:
159                self.directoryHistoryIF.removeLast()
160            flag=True
161            # print self.findHistory
162        # for in files operations we always do search regardless if parameters change or not
163        flag=True     
164        return flag         
165         
166       
167    # def newSearchParametersIF(self,_text,_filters,_directory):
168        # flag=False
169        # if self.textToFindIF!=_text:
170            # self.textToFindIF = _text       
171            # self.findHistoryIF.prepend(self.textToFindIF)
172            # self.findHistoryIF.removeDuplicates()
173            # if self.findHistoryIF.count()>=self.historyLength:
174                # self.findHistoryIF.removeLast()
175               
176        # if self.filtersIF!=_filters:
177            # self.filtersIF = _filters       
178            # self.filtersHistoryIF.prepend(self.filtersIF)
179            # self.filtersHistoryIF.removeDuplicates()
180            # if self.filtersHistoryIF.count()>=self.historyLength:
181                # self.filtersHistoryIF.removeLast()
182            # # print self.findHistory
183        # if self.directoryIF!=_directory:
184            # self.directoryIF = _directory       
185            # self.directoryHistoryIF.prepend(self.directoryIF)
186            # self.directoryHistoryIF.removeDuplicates()
187            # if self.directoryHistoryIF.count()>=self.historyLength:
188                # self.directoryHistoryIF.removeLast()
189            # # print self.findHistory
190           
191        # flag=True
192       
193        # if self.re!=_re:
194            # self.re=_re
195            # flag=True
196        # if self.cs!=_cs:
197            # self.cs=_cs
198            # flag=True
199        # if self.wo!=_wo:
200            # self.wo=_wo
201            # flag=True           
202        # if self.wrap!=_wrap:
203            # self.wrap=_wrap
204            # flag=True
205        # # if self.inSelection!=_inSelection:
206            # # self.inSelection=_inSelection
207            # # flag=True
208           
209        # return flag   
210
211    def newReplaceParameters(self,_text,_replaceText,_re,_cs,_wo,_wrap,_inSelection):
212        flag=self.newSearchParameters(_text,_re,_cs,_wo,_wrap,_inSelection)
213       
214        if self.replaceText!=_replaceText:
215            self.replaceText=_replaceText
216           
217            self.replaceHistory.prepend(self.replaceText)
218            self.replaceHistory.removeDuplicates()
219            if self.replaceHistory.count()>=self.historyLength:
220                self.replaceHistory.removeLast()
221               
222            # print self.findHistory
223            flag=True
224
225        return flag   
226       
227    def newReplaceParametersIF(self,_text,_replaceText,_filters,_directory):
228        flag=self.newSearchParametersIF(_text,_filters,_directory)
229       
230        if self.replaceTextIF!=_replaceText:
231            self.replaceTextIF=_replaceText
232           
233            self.replaceHistory.prepend(self.replaceTextIF)
234            self.replaceHistory.removeDuplicates()
235            if self.replaceHistory.count()>=self.historyLength:
236                self.replaceHistory.removeLast()
237               
238            # print self.findHistory
239            flag=True
240
241        return flag 
242    # def newReplaceParametersIF(self,_text,_replaceText,_filters,_directory):
243        # flag=self.newSearchParametersIF(_text,_filters,_directory)
244       
245        # if self.replaceTextIF!=_replaceText:
246            # self.replaceTextIF=_replaceText
247           
248            # self.replaceHistoryIF.prepend(self.replaceTextIF)
249            # self.replaceHistoryIF.removeDuplicates()
250            # if self.replaceHistoryIF.count()>=self.historyLength:
251                # self.replaceHistoryIF.removeLast()
252               
253            # # print self.findHistory
254            # flag=True
255
256        # return flag         
257class ClickToFocusEventFilter(QObject):
258    def __init___(self,_qLineEdit):
259        QObject.__init__(self)
260        self.qLineEdit=_qLineEdit
261       
262    def eventFilter(self,  obj,  event):
263        print "INSIDE EVENT FILTER ",event.type()
264        if event.type() == QEvent.FocusIn:
265            self.qLineEdit.selectAll()
266            # if event.key() == Qt.Key_Delete:
267                # self.delkeyPressed.emit()
268                # print 'delkey pressed'
269            return True
270        return False
271   
272class QLineEditCustom(QLineEdit):
273    def __init__(self,_parent=None):
274        QLineEdit.__init__(self,_parent)
275        self.focusInCalled=False
276        # have to monitor cursor position because qLineEdit inside QComboBox behaves weirdly - after each typed character the cursor is moved to the end of the word making it hard to type inside the line
277        self.textEdited.connect(self.monitorCursor)
278        self.cursorPositionChanged.connect(self.repositionCursor)
279        self.pos=-1
280       
281    # seems the solution is to eat MouseButtonPress and MouseButtonRelease events...
282    # http://www.qtcentre.org/threads/10539-QLineEdit-selectAll%28%29-in-eventFilter
283    # to highlight content of QLine edit we need to implement focusInEvent and also change behavior of mousePressEvent
284    # when mousePressEvent is called right after focusIn we do nothing otherwise we use default mousePress Event
285   
286   
287   
288    def mousePressEvent(self,event): # this event handler is called second
289           
290        # print "self.focusInCalled=",self.focusInCalled
291        if self.focusInCalled:
292            self.focusInCalled=False           
293        else:
294            QLineEdit.mousePressEvent(self,event)
295     
296
297    def focusInEvent(self,event): # this event handler is called first
298       
299
300        self.selectAll()
301        self.focusInCalled=True
302       
303    def focusOutEvent(self,event):
304        self.deselect()
305        self.focusInCalled=False
306
307    def monitorCursor(self,_str):
308        self.pos=self.cursorPosition()
309
310       
311    def repositionCursor(self,_oldPos,_newPos):
312        # print "repositionCursor=",(_oldPos,_newPos)
313        if self.pos!=-1:
314            self.setCursorPosition(self.pos)
315            self.pos=-1
316
317       
318class FindAndReplaceDlg(QDialog,ui_findinfilesdlg.Ui_FindInFiles):
319    #signals
320    searchingSignal = QtCore.pyqtSignal( ('char*',))
321    searchingAllInAllOpenDocsSignal = QtCore.pyqtSignal( ('char*','char*','char*','int',)) # text, filters,directory, search mode
322    replacingSignal = QtCore.pyqtSignal( ('char*','char*',))
323    replacingAllSignal = QtCore.pyqtSignal( ('char*','char*',bool))   
324    replacingAllInOpenDocsSignal = QtCore.pyqtSignal( ('char*','char*','char*','char*','int',))  #text,replaceText, filters,directory. replace mode 
325    searchingSignalIF = QtCore.pyqtSignal( ('char*','char*','char*',)) # text, filters,directory
326    replacingSignalIF = QtCore.pyqtSignal( ('char*','char*','char*','char*')) # text,replaceText, filters,directory
327   
328    def __init__(self, text="", parent=None):
329        super(FindAndReplaceDlg, self).__init__(parent)
330        self.editorWindow=parent
331        self.__text = unicode(text)
332        self.__index = 0
333        self.setupUi(self)
334        self.findLineEdit=QLineEditCustom()
335        self.findComboBox.setLineEdit(self.findLineEdit)
336        self.findComboBox.completer().setCaseSensitivity(1)
337        self.replaceLineEdit=QLineEditCustom()
338        self.replaceComboBox.setLineEdit(self.replaceLineEdit)
339        self.replaceComboBox.completer().setCaseSensitivity(1)
340        self.setWindowFlags(Qt.Drawer) # dialogs without context help - only close button exists
341        self.findAndReaplceHistory=None
342       
343       
344        # IF stands for "in files"
345        self.findLineEditIF=QLineEditCustom()
346        self.findComboBoxIF.setLineEdit(self.findLineEditIF)
347        self.findComboBoxIF.completer().setCaseSensitivity(1)
348        self.replaceLineEditIF=QLineEditCustom()
349        self.replaceComboBoxIF.setLineEdit(self.replaceLineEditIF)
350        self.replaceComboBoxIF.completer().setCaseSensitivity(1)
351
352        self.filtersLineEditIF=QLineEditCustom()
353        self.filtersComboBoxIF.setLineEdit(self.filtersLineEditIF)
354        self.filtersComboBoxIF.completer().setCaseSensitivity(1)
355       
356        self.directoryLineEditIF=QLineEditCustom()
357        self.directoryComboBoxIF.setLineEdit(self.directoryLineEditIF)
358        self.directoryComboBoxIF.completer().setCaseSensitivity(1)
359       
360        # self.findComboBox.setCompleter(0) # disallow word completion
361        # synchronizing find and replace boxes on two tabs
362        self.connect(self.findLineEdit,SIGNAL("textChanged(const QString &)"),self.findLineEditIF,SLOT("setText(const QString &)"))
363        self.connect(self.findLineEditIF,SIGNAL("textChanged(const QString &)"),self.findLineEdit,SLOT("setText(const QString &)"))
364        self.connect(self.replaceLineEdit,SIGNAL("textChanged(const QString &)"),self.replaceLineEditIF,SLOT("setText(const QString &)"))
365        self.connect(self.replaceLineEditIF,SIGNAL("textChanged(const QString &)"),self.replaceLineEdit,SLOT("setText(const QString &)"))
366        #synchronizing check boxes
367        self.connect(self.wholeCheckBox,SIGNAL("toggled(bool)"),self.wholeCheckBoxIF, SLOT("setChecked(bool)"))
368        self.connect(self.wholeCheckBoxIF,SIGNAL("toggled(bool)"),self.wholeCheckBox, SLOT("setChecked(bool)"))
369        self.connect(self.caseCheckBox,SIGNAL("toggled(bool)"),self.caseCheckBoxIF, SLOT("setChecked(bool)"))
370        self.connect(self.caseCheckBoxIF,SIGNAL("toggled(bool)"),self.caseCheckBox, SLOT("setChecked(bool)"))
371       
372        self.connect(self.tabWidget,SIGNAL("currentChanged(int)"),self.tabChanged)
373        self.connect(self.alwaysRButton,SIGNAL("toggled(bool)"),self.alwaysRButtonToggled)
374        self.connect(self.onLosingFocusRButton,SIGNAL("toggled(bool)"),self.onLosingFocusRButtonToggled)
375       
376        self.connect(self.transparencyGroupBox,SIGNAL("toggled(bool)"),self.transparencyGroupBoxToggled)
377       
378        #synchronizing syntax boxes
379        self.connect(self.syntaxComboBox,SIGNAL("activated(int)"),self.syntaxComboBoxIF, SLOT("setCurrentIndex(int)"))
380        self.connect(self.syntaxComboBoxIF,SIGNAL("activated(int)"),self.syntaxComboBox, SLOT("setCurrentIndex(int)"))
381       
382        # self.connect(self.replaceLineEdit,SIGNAL("clicked()"),self.replaceLineEditIF,SLOT("selectAll()"))
383        # self.connect(self.replaceLineEdit,SIGNAL("    cursorPositionChanged(int,int)"),self.replaceSlot)
384       
385        # self.connect(self.replaceComboBox,SIGNAL("clicked()"),self.replaceSlot)
386       
387       
388        # self.replaceLineEdit.clicked.connect(self.replaceSlot())
389       
390        # self.replaceComboBox.setCompleter(0) # disallow word completion
391        # self.setWindowOpacity(0.5)
392        if not MAC:
393            # # self.findButton.setFocusPolicy(Qt.NoFocus)
394            self.replaceButton.setFocusPolicy(Qt.NoFocus)
395            self.replaceAllButton.setFocusPolicy(Qt.NoFocus)
396            self.closeButton.setFocusPolicy(Qt.NoFocus)
397        self.updateUi()
398       
399    def tabChanged(self,idx):
400        title=self.tabWidget.tabText(idx)
401        print "TITLE=",title
402        self.setWindowTitle(title)
403   
404    def changeEvent(self,event):
405        if event.type()==QEvent.ActivationChange:
406            if self.transparencyGroupBox.isChecked() and self.onLosingFocusRButton.isChecked():
407                if self.isActiveWindow():
408                    self.setWindowOpacity(1.0)
409                else:
410                    self.setWindowOpacity(self.transparencySlider.sliderPosition()/100.0)
411
412    def setFindAndReaplceHistory(self,_frh):
413        self.findAndReaplceHistory=_frh
414   
415    def showEvent(self, event):
416        self.findLineEdit.setFocus(True)
417        QDialog.showEvent(self,event) # necesary to move dialog to the correct position - we do it only if we override show event
418   
419    def closeEvent(self, event):
420        print "CLOSE EVENT FOR FIND DIALOG"
421        self.editorWindow.findDialogForm=None
422        frh=self.findAndReaplceHistory
423        frh.wo=self.wholeCheckBox.isChecked()
424        frh.cs=self.caseCheckBox.isChecked()
425       
426        frh.syntaxIndex=self.syntaxComboBoxIF.currentIndex()
427       
428        frh.inSelection=self.inSelectionBox.isChecked()
429        frh.inAllSubfolders=self.inAllSubFoldersCheckBoxIF.isChecked()
430       
431        frh.transparencyEnable=self.transparencyGroupBox.isChecked()
432        frh.opacityOnLosingFocus=self.onLosingFocusRButton.isChecked()
433        frh.opacityAlways=self.alwaysRButton.isChecked()
434        frh.opacity=self.transparencySlider.sliderPosition()   
435       
436       
437    def initializeDialog(self,_frh):
438        # if _frh.re:
439            # self.syntaxComboBox.setCurrentIndex(1) # selecting Regular Expression syntax
440        # else:
441            # self.syntaxComboBox.setCurrentIndex(0) # selecting literal string syntax
442           
443        if _frh.cs:
444            self.caseCheckBox.setChecked(True)
445        else:
446            self.caseCheckBox.setChecked(False)
447           
448        if _frh.wo:
449            self.wholeCheckBox.setChecked(True)
450        else:
451            self.wholeCheckBox.setChecked(False)   
452        self.initializeAllSearchLists(_frh)
453       
454        #initializing syntax index
455        self.syntaxComboBox.setCurrentIndex(_frh.syntaxIndex)
456        self.syntaxComboBoxIF.setCurrentIndex(_frh.syntaxIndex) #have to manually change current index both syntax combo boxes
457       
458       
459        #initializing searchModifiers settings
460        self.inSelectionBox.setChecked(_frh.inSelection)
461        self.inAllSubFoldersCheckBoxIF.setChecked(_frh.inAllSubfolders)
462       
463        #initializing transparency settings       
464        self.transparencyGroupBox.setChecked(_frh.transparencyEnable)
465        self.onLosingFocusRButton.setChecked(_frh.opacityOnLosingFocus)
466        self.alwaysRButton.setChecked(_frh.opacityAlways)
467        self.transparencySlider.setSliderPosition(_frh.opacity)
468       
469        # #setting opacity
470        # if _frh.transparencyEnable and _frh.opacityAlways:
471            # self.setWindowOpacity(_frh.opacity/100.0)
472
473    def alwaysRButtonToggled(self,_flag):
474        if self.transparencyGroupBox.isChecked() and _flag:
475            self.setWindowOpacity(self.transparencySlider.sliderPosition()/100.0)
476           
477    def onLosingFocusRButtonToggled(self,_flag):
478        if _flag:
479            self.setWindowOpacity(1.0)
480       
481    def transparencyGroupBoxToggled(self,_flag):
482        if _flag:
483            if self.alwaysRButton.isChecked():
484                self.alwaysRButtonToggled(_flag)
485        else:   
486            self.setWindowOpacity(1.0)   
487           
488    def initializeSearchLists(self,_frh):       
489        self.findComboBox.clear()
490        self.replaceComboBox.clear()
491        self.findComboBoxIF.clear()
492        self.replaceComboBoxIF.clear()
493       
494        self.findComboBox.addItems(_frh.findHistory)
495        self.replaceComboBox.addItems(_frh.replaceHistory)       
496        self.findComboBoxIF.addItems(_frh.findHistory)
497        self.replaceComboBoxIF.addItems(_frh.replaceHistory)       
498       
499    def initializeAllSearchLists(self,_frh):       
500        self.initializeSearchLists(_frh)
501        self.directoryComboBoxIF.clear()
502        self.filtersComboBoxIF.clear()
503        self.directoryComboBoxIF.addItems(_frh.directoryHistoryIF)
504        self.filtersComboBoxIF.addItems(_frh.filtersHistoryIF)
505       
506    def findLineEditProcess(self,_text):
507        print "clicked Find Line Edit"
508    # @pyqtSignature("QString")
509    # def on_findComboBox_textEdited(self, text):
510        # print "FIND COMBO BOX EDITED"
511        # self.__index = 0
512        # self.updateUi()
513
514    # @pyqtSignature("")
515    # def on_findComboBox_clicked(self, text):
516        # print "FIND COMBO BOX EDITED"
517        # self.__index = 0
518        # self.updateUi()       
519
520    # def makeRegex(self):
521        # findText = unicode(self.findLineEdit.text())
522        # if unicode(self.syntaxComboBox.currentText()) == "Literal":
523            # findText = re.escape(findText)
524        # flags = re.MULTILINE|re.DOTALL|re.UNICODE
525        # if not self.caseCheckBox.isChecked():
526            # flags |= re.IGNORECASE
527        # if self.wholeCheckBox.isChecked():
528            # findText = r"\b%s\b" % findText
529        # return re.compile(findText, flags)
530
531    # not including @pyqtSignature("") causes multiple calls to this fcn
532    @pyqtSignature("")
533    def on_findNextButton_clicked(self):
534        # print "this is on findNext button clicked"
535        self.searchingSignal.emit(self.findComboBox.lineEdit().text())
536        return
537       
538    @pyqtSignature("")   
539    def on_findAllInOpenDocsButton_clicked(self):       
540        self.searchingAllInAllOpenDocsSignal.emit(self.findComboBox.lineEdit().text(),'','',ALL_IN_ALL_OPEN_DOCS)   
541        return
542       
543    @pyqtSignature("")   
544    def on_findAllInCurrentDocButton_clicked(self):
545        self.searchingAllInAllOpenDocsSignal.emit(self.findComboBox.lineEdit().text(),'','',ALL_IN_CURRENT_DOC)     
546        return
547       
548    @pyqtSignature("")       
549    def on_replaceAllInOpenDocsButton_clicked(self):
550        self.replacingAllInOpenDocsSignal.emit(self.findComboBox.lineEdit().text(),self.replaceComboBox.lineEdit().text(),'','',ALL_IN_ALL_OPEN_DOCS)
551        return
552       
553    @pyqtSignature("")
554    def on_findCPB_clicked(self):
555        # print "this is on findNext button clicked" 
556         
557        self.findAndReaplceHistory.findHistory.clear()
558        self.findComboBox.clear()
559        self.findComboBoxIF.clear()
560       
561    @pyqtSignature("")
562    def on_replaceCPB_clicked(self):
563        print "CLEAR REAPLCE HISTORY button clicked"       
564        self.findAndReaplceHistory.replaceHistory.clear()
565        self.replaceComboBox.clear()
566        self.replaceComboBoxIF.clear()
567       
568    @pyqtSignature("")     
569    def on_filtersCPB_clicked(self):
570        # print "this is on findNext button clicked"       
571        self.findAndReaplceHistory.filtersHistoryIF.clear()
572        self.filtersComboBoxIF.clear()
573       
574    @pyqtSignature("")             
575    def on_directoryCPB_clicked(self):
576        # print "this is on findNext button clicked"       
577        self.findAndReaplceHistory.directoryHistoryIF.clear()
578        self.directoryComboBoxIF.clear()
579
580       
581    # def findNext(self,_text):
582        # print "findNext = ",_text
583        # editor=self.editorWindow.editTab.currentWidget()
584        # if _text!=self.textToFind:
585            # self.textToFind=_text
586            # editor.findFirst(self.textToFind,False,True,False,True)
587        # else:
588            # editor.findNext()
589       
590    # @pyqtSignature("")
591    # def on_findButton_clicked(self):
592        # print "this is on find buttin clicked" 
593        # return
594        # self.searchingSignal.emit(self.findComboBox.lineEdit().text())
595        # if self.findComboBox.lineEdit():
596            # if self.findComboBox.lineEdit().text():
597                # print "got text to find ", self.findComboBox.lineEdit().text()
598                # self.searchingSignal.emit(self.findComboBox.lineEdit().text())
599                # # self.emit(SIGNAL("searching"),self.findComboBox.lineEdit().text())
600        # # regex = self.makeRegex()
601        # # match = regex.search(self.__text, self.__index)
602        # # if match is not None:
603            # # self.__index = match.end()
604            # # self.emit(SIGNAL("found"), match.start())
605        # # else:
606            # # self.emit(SIGNAL("notfound"))
607       
608       
609    @pyqtSignature("")
610    def on_replaceButton_clicked(self):
611        # print "this is on replace buttin clicked"
612        self.replacingSignal.emit(self.findComboBox.lineEdit().text(),self.replaceComboBox.lineEdit().text())
613        return
614   
615        print "this is on replace buttin clicked" 
616        return
617        regex = self.makeRegex()
618        self.__text = regex.sub(unicode(self.replaceLineEdit.text()),
619                                self.__text, 1)
620       
621
622    @pyqtSignature("")
623    def on_replaceAllButton_clicked(self):
624        print "this is on replaceAll buttin clicked"
625        self.replacingAllSignal.emit(self.findComboBox.lineEdit().text(),self.replaceComboBox.lineEdit().text(),self.inSelectionBox.isChecked())
626        return
627        regex = self.makeRegex()
628        self.__text = regex.sub(unicode(self.replaceLineEdit.text()),
629                                self.__text)
630       
631
632    def updateUi(self):
633        # if self.findComboBox.lineEdit():
634            # print "got text to find ", self.findComboBox.lineEdit().text()
635       
636        pass
637        # enable = not self.findLineEdit.text().isEmpty()
638        # self.findButton.setEnabled(enable)
639        # self.replaceButton.setEnabled(enable)
640        # self.replaceAllButton.setEnabled(enable)
641
642    # def findText(self):
643        # if self.findComboBox.lineEdit():
644            # return self.findComboBox.lineEdit().text()
645
646    # def setFindText(self,_text):
647        # if self.findComboBox.lineEdit():
648            # return self.findComboBox.lineEdit().setText(_text)
649
650    # def initializeForm(self, _findAndReplaceHistory):
651        # for t in _findAndReplaceHistory.findHistory:
652            # self.findComboBox.insertItem(self.findComboBox.size(),t)
653           
654    def text(self):
655        return self.__text
656       
657    @pyqtSignature("")
658    def on_pickDirectoryButtonIF_clicked(self):
659        print "this is on pick directory button clicked"
660        directory=QFileDialog.getExistingDirectory ( self, "Look for files in the directory...")
661        print "directory=",directory
662        self.directoryLineEditIF.setText(directory)
663        # dialog=QFileDialog(self)
664        # dialog.setFileMode(QFileDialog.DirectoryOnly)
665        # dialog.setViewMode(QFileDialog.List)
666        # dialog.show()
667       
668        # self.searchingSignal.emit(self.findComboBox.lineEdit().text())
669        return
670    @pyqtSignature("")
671    def on_findAllButtonIF_clicked(self):       
672        self.searchingSignalIF.emit(self.findComboBoxIF.lineEdit().text(),self.filtersComboBoxIF.lineEdit().text(),self.directoryComboBoxIF.lineEdit().text())
673       
674    @pyqtSignature("")
675    def on_replaceButtonIF_clicked(self):       
676        self.replacingSignalIF.emit(self.findComboBoxIF.lineEdit().text(),self.replaceComboBoxIF.lineEdit().text(),self.filtersComboBoxIF.lineEdit().text(),self.directoryComboBoxIF.lineEdit().text())
677       
678       
679# class FindDock
680import sys
681from PyQt4.Qsci import *
682from PyQt4 import Qsci
683from PyQt4 import QtGui
684# from PyQt4.Qsci.QsciScintilla import *
685# NOTICE: complete scintilla documentation can be found here:
686# http://www.scintilla.org/ScintillaDoc.htm
687class FindDisplayWidget(QsciScintilla):
688    """
689    Class providing a specialized text edit for displaying logging information.
690    """
691    def __init__(self, parent = None):
692        """
693        Constructor
694       
695        @param parent reference to the parent widget (QWidget) - here it is EditorWindow class
696        """
697        self.editorWindow=parent
698        QsciScintilla.__init__(self,parent)
699        # # self.setFolding(5)
700        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
701        # self.setMarginSensitivity(3,True)
702        lexer=QsciLexerPython()
703        print lexer.keywords(1),"\n\n\n\n"
704        findInFilesLexer=FindInFilesLexer(self)
705        self.setLexer(findInFilesLexer)
706       
707        self.setReadOnly(True)
708        self.setCaretLineVisible(True)
709       
710        self.setCaretLineBackgroundColor(QtGui.QColor('#E0E0F8')) #current line has this color
711        self.setSelectionBackgroundColor(QtGui.QColor('#E0E0F8')) # any selection in the current line due to double click has the same color too       
712        #connecting SCN_DOUBLECLICK(int,int,int) to editor double-click
713        #notice  QsciScintilla.SCN_DOUBLECLICK(int,int,int) is not the right name       
714        self.connect(self, SIGNAL("SCN_DOUBLECLICK(int,int,int)"), self.onDoubleClick)
715       
716        GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
717        SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
718        HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
719        LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
720        NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
721        WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
722       
723        headerLevel = LEVELBASE | HEADERFLAG
724        lineStart=1       
725        lineEnd=3
726
727        self.SendScintilla(QsciScintilla.SCI_SETCARETSTYLE, QsciScintilla.CARETSTYLE_INVISIBLE) # make caret invisible
728       
729
730        self.lineNumberExtractRegex=re.compile('^[\s]*Line[\s]*([0-9]*)')
731        self.fileNameWithSearchTextExtractRegex=re.compile('^[\s]*File:[\s]*([\S][\s\S]*)\(')
732       
733        print "marginSensitivity=",self.marginSensitivity(0)
734
735    def addNewFindInFilesResults(self, _str):
736        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)# stray fold character workaround
737        self.insertAt(_str,0,0)
738        # self.append(_str)
739       
740    # context menu handling
741    def contextMenuEvent(self,event):
742        menu=QMenu(self)
743        copyAct=menu.addAction("Copy")
744        selectAllAct=menu.addAction("Select All")
745        clearAllAct=menu.addAction("Clear All")
746        self.connect(copyAct,SIGNAL("triggered()"),self.copy)
747        self.connect(selectAllAct,SIGNAL("triggered()"),self.selectAll)
748        self.connect(clearAllAct,SIGNAL("triggered()"),self.clearAll)
749       
750        menu.exec_(event.globalPos())
751       
752    def clearAll(self):
753        # self.clearFolds()
754        self.clear()
755        # SCI=self.SendScintilla
756        # HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG       
757        # LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
758        # SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
759        # headerLevel = LEVELBASE | HEADERFLAG
760        # SCI(SETFOLDLEVEL, 0, headerLevel)
761                       
762        #
763        #
764        self.setFolding(QsciScintilla.NoFoldStyle) # stray fold character workaround
765        # self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
766       
767    def onMarginClick(self,_pos,_modifier, _margin):
768        print "_pos:",_pos," modifier:",_modifier," _margin:",_margin
769        lineClick = self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, _pos)
770        print "lineClick=",lineClick
771        levelClick = self.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, lineClick)
772        print "levelClick=",levelClick
773        if levelClick & QsciScintilla.SC_FOLDLEVELHEADERFLAG:
774            print "Clicked Fold Header"
775            self.SendScintilla(QsciScintilla.SCI_TOGGLEFOLD, lineClick)
776
777    def onDoubleClick(self,_position,_line,_modifiers):
778        print "position=",_position," line=",_line," modifiers=",_modifiers
779        lineText=str(self.text(_line))
780        print "line text=",lineText
781        lineNumberGroups=self.lineNumberExtractRegex.search(lineText)
782        lineNumber=-1
783        lineNumberWithFileName=-1
784        try:
785            if lineNumberGroups:
786                lineNumber=int(lineNumberGroups.group(1))
787                print "Searched text at line=",lineNumber
788                lineNumberWithFileName = self.SendScintilla(QsciScintilla.SCI_GETFOLDPARENT, _line)   
789        except IndexError,e:
790           
791            print "Line number not found"
792
793        if lineNumberWithFileName>=0:
794            print "THIS IS LINE WITH FILE NAME:"
795            lineWithFileName= str(self.text(lineNumberWithFileName))
796           
797            print lineWithFileName
798            fileNameGroups=self.fileNameWithSearchTextExtractRegex.search(lineWithFileName)
799            if fileNameGroups:
800                try:
801                    fileNameWithSearchedText=fileNameGroups.group(1)
802                    fileNameWithSearchedText.strip() # removing trailing white spaces
803                    # "normalizing" file name to make sure \ and / are used in a consistent manner
804                    fileNameWithSearchedText=os.path.abspath(fileNameWithSearchedText)
805                    print "FILE NAME WITH SEARCHED TEXT:",fileNameWithSearchedText
806                    self.editorWindow.loadFile(fileNameWithSearchedText)
807                    currentEditorTab=self.editorWindow.editTab.currentWidget()
808                    currentEditorTab.setCursorPosition(lineNumber,0)
809                    currentEditorTab.ensureCursorVisible()
810                    currentEditorTab.SendScintilla(QsciScintilla.SCI_SETFOCUS,True)
811                except IndexError,e:
812                    print "Could not extract file name"
813           
814# lineWithFileNameText ="  File: C:/Program Files/twedit/tw edit.py (8 hits)"   
815# lineWithFileNameGroups=re.search('^[\s]*File:[\s]*([\S][\s\S]*)\(',lineWithFileNameText)
816# print lineWithFileNameGroups
817# if lineWithFileNameGroups:
818    # print "group 0=",lineWithFileNameGroups.group(0)
819    # print "group 1=",lineWithFileNameGroups.group(1)       
820        # figuring out the file name
821        # using http://www.scintilla.org/ScintillaDoc.html#SCI_GETFOLDPARENT
822       
823       
824           
825           
826        # self.foldLine(0)
827        # self.foldAll()
828    # def __handleShowContextMenu(self, coord):
829        # """
830        # Private slot to show the context menu.
831       
832        # @param coord the position of the mouse pointer (QPoint)
833        # """
834        # print "Context Menu"
835        # # coord = self.mapToGlobal(coord)
836        # # self.__menu.popup(coord)
837       
838       
839class CustomLexer(QsciLexerCustom):
840    def __init__(self, parent):
841        Qsci.QsciLexerCustom.__init__(self, parent)
842        self._styles = {
843            0: 'Default',
844            1: 'Comment',
845            2: 'Key',
846            3: 'Assignment',
847            4: 'Value',
848            }
849        for key,value in self._styles.iteritems():
850            setattr(self, value, key)
851        self.editorWidget=parent
852    def description(self, style):
853        return self._styles.get(style, '')
854
855    def defaultColor(self, style):
856        if style == self.Default:
857            return QtGui.QColor('#000000')
858        elif style == self.Comment:
859            return QtGui.QColor('#C0C0C0')
860        elif style == self.Key:
861            return QtGui.QColor('#0000CC')
862        elif style == self.Assignment:
863            return QtGui.QColor('#CC0000')
864        elif style == self.Value:
865            return QtGui.QColor('#00CC00')
866        return Qsci.QsciLexerCustom.defaultColor(self, style)
867    def keywords(self,i):
868        return "fcn"   
869    def styleText(self, start, end):
870        editor = self.editor()
871        if editor is None:
872            return
873
874        # scintilla works with encoded bytes, not decoded characters.
875        # this matters if the source contains non-ascii characters and
876        # a multi-byte encoding is used (e.g. utf-8)
877        source = ''
878        if end > editor.length():
879            end = editor.length()
880        if end > start:
881            if sys.hexversion >= 0x02060000:
882                # faster when styling big files, but needs python 2.6
883                source = bytearray(end - start)
884                editor.SendScintilla(
885                    editor.SCI_GETTEXTRANGE, start, end, source)
886            else:
887                source = unicode(editor.text()
888                                ).encode('utf-8')[start:end]
889        if not source:
890            return
891
892        # the line index will also be needed to implement folding
893        index = editor.SendScintilla(editor.SCI_LINEFROMPOSITION, start)
894        if index > 0:
895            # the previous state may be needed for multi-line styling
896            pos = editor.SendScintilla(
897                      editor.SCI_GETLINEENDPOSITION, index - 1)
898            state = editor.SendScintilla(editor.SCI_GETSTYLEAT, pos)
899        else:
900            state = self.Default
901
902        set_style = self.setStyling
903        self.startStyling(start, 0x1f)
904       
905        # SCI = self.SendScintilla
906        SCI=self.editorWidget.SendScintilla
907        GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
908        SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
909        HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
910        LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
911        NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
912        WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
913        # scintilla always asks to style whole lines
914        for line in source.splitlines(True):
915            length = len(line)
916            if line.startswith('#'):
917                state = self.Comment
918                print "STYLING COMMENT"
919            else:
920                # the following will style lines like "x = 0"
921                pos = line.find('=')
922                if pos > 0:
923                    set_style(pos, self.Key)#styling LHS pos is the length of styled text
924                    set_style(1, self.Assignment)#styling = 1 is the length of styled text
925                    length = length - pos - 1 # Value styling is applied to RHS
926                    state = self.Value
927                else:
928                    state = self.Default
929            set_style(length, state)
930            # folding implementation goes here
931            # headerLevel = LEVELBASE | HEADERFLAG
932            # print "HEADER LEVEL",headerLevel
933           
934            # if index==0:
935                # SCI(SETFOLDLEVEL, index, headerLevel)
936            # else:
937                # SCI(SETFOLDLEVEL, index, LEVELBASE+1)
938            index += 1
939           
940# Folding is sensitive to new lines - works fin if there is no new empty lines
941# have to make sure that Search,Line, File at the beginning of the line do not have to include certain number fo leading spaces
942# to make lexer work properly
943
944# IMPORTANT. by default Lexer will process only visible text so if there is a state you want to pas from line to line you
945# have to store it in class variable or have a way to restore previous state  (here we use self.searchText) as a state variable to hold value of the searched text for each line.
946
947class FindInFilesLexer(QsciLexerCustom):
948    def __init__(self, parent):
949        Qsci.QsciLexerCustom.__init__(self, parent)
950        self._styles = {
951            0: 'Default',
952            1: 'SearchInfo',
953            2: 'FileInfo',
954            3: 'LineInfo',
955            4: 'TextToFind'
956            }
957        for key,value in self._styles.iteritems():
958            setattr(self, value, key)
959        self.editorWidget=parent
960        self.colorizeEntireLineStates=[self.SearchInfo,self.FileInfo]
961       
962        self.baseFont=Qsci.QsciLexerCustom.defaultFont(self, 0)
963        self.baseFontBold=QFont(self.baseFont)       
964        self.baseFontBold.setBold(True)
965        self.searchText=""
966       
967    def description(self, style):
968        return self._styles.get(style, '')
969    #used by QsciLexer to style font colors
970    def defaultColor(self, style):
971        if style == self.Default:
972            return QtGui.QColor('#000000')
973        elif style == self.SearchInfo:
974            return QtGui.QColor('#0404B4')
975        elif style == self.FileInfo:
976            return QtGui.QColor('#04B404')
977        elif style == self.LineInfo:   
978            return QtGui.QColor('#000000')           
979        elif style == self.TextToFind:
980            return QtGui.QColor('#FF0000')
981           
982        return Qsci.QsciLexerCustom.defaultColor(self, style)
983       
984    #used by QsciLexer to style font properties   
985    def defaultFont(self, style):
986
987       
988        if style == self.Default:
989            return self.baseFont
990        elif style == self.SearchInfo:
991            # baseFont.setBold(True)
992            return self.baseFontBold
993        elif style == self.FileInfo:
994            return self.baseFontBold
995 
996        return Qsci.QsciLexerCustom.defaultFont(self, style) 
997       
998    #used by QsciLexer to style paper properties (background color)
999    def defaultPaper(self, style):
1000
1001        if style == self.Default:
1002            return QtGui.QColor('#FFFFFF')
1003        elif style == self.SearchInfo:           
1004            return QtGui.QColor('#A9D0F5')
1005        elif style == self.FileInfo:
1006            return QtGui.QColor('#E0F8E0')
1007        elif style == self.TextToFind:
1008            return QtGui.QColor('#F2F5A9')
1009 
1010        return Qsci.QsciLexerCustom.defaultPaper(self, style)   
1011       
1012    # To colorize entire line containit Search or File info we use  defaultEolFill fcn   
1013    def defaultEolFill(self, style):
1014    # This allowed to colorize all the background of a line.
1015        if style in self.colorizeEntireLineStates:
1016            return True
1017        return QsciLexerCustom.defaultEolFill(self, style) 
1018       
1019    def styleText(self, start, end):
1020        editor = self.editor()
1021        if editor is None:
1022            return
1023
1024        # scintilla works with encoded bytes, not decoded characters.
1025        # this matters if the source contains non-ascii characters and
1026        # a multi-byte encoding is used (e.g. utf-8)
1027        source = ''
1028        if end > editor.length():
1029            end = editor.length()
1030        if end > start:
1031            if sys.hexversion >= 0x02060000:
1032                # faster when styling big files, but needs python 2.6
1033                source = bytearray(end - start)
1034                editor.SendScintilla(
1035                    editor.SCI_GETTEXTRANGE, start, end, source)
1036            else:
1037                # source = unicode(editor.text()
1038                                # ).encode('utf-8')[start:end]
1039                source=unicode(editor.text()).encode('utf-8') # scanning entire text is way more efficient that doing it on demand especially when folding top level text (Search)               
1040        if not source:
1041            return
1042           
1043       
1044       
1045       
1046        # the line index will also be needed to implement folding
1047        index = editor.SendScintilla(editor.SCI_LINEFROMPOSITION, start)
1048        if index > 0:
1049            # the previous state may be needed for multi-line styling
1050            pos = editor.SendScintilla(
1051                      editor.SCI_GETLINEENDPOSITION, index - 1)
1052            state = editor.SendScintilla(editor.SCI_GETSTYLEAT, pos)
1053        else:
1054            state = self.Default
1055
1056        set_style = self.setStyling
1057        self.startStyling(start, 0x1f)
1058       
1059        # SCI = self.SendScintilla
1060        SCI=self.editorWidget.SendScintilla
1061        GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
1062        SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
1063        HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
1064        LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
1065        NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
1066        WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
1067        # scintilla always asks to style whole lines
1068       
1069        for line in source.splitlines(True):
1070            length = len(line)
1071            # print "line=",line
1072            # print line
1073            if line.startswith('\n'):
1074                style=self.Default
1075                print "GOT EMPTY LINE"
1076                # sys.exit()
1077            else:   
1078                if line.startswith('Search'):
1079                    state = self.SearchInfo
1080                   
1081                    searchGroups =re.search('"([\s\S]*)"', line) # we have to use search instead of match - match matches onle beginning of the string , search searches through entire string
1082
1083                   
1084                    # print "searchGroups=",searchGroups
1085                   
1086                    try:
1087                   
1088                        if searchGroups:                       
1089                            # print searchGroups.group(1)
1090                            self.searchText=searchGroups.group(1)
1091                           
1092                            # print "self.searchText=",self.searchText
1093                    except IndexError,e:
1094                        self.searchText=""
1095                        print "COULD NOT EXTRACT TEXT"
1096                       
1097                           
1098                           
1099                # elif line.startswith('  File'):
1100                elif line.startswith('  F'):
1101                    state = self.FileInfo
1102                   
1103                # elif line.startswith('    Line'):   
1104                elif line.startswith('   '):
1105               
1106                   
1107                    if self.searchText!="":
1108                        # print "self.searchText=",self.searchText
1109                        searchTextLength=len(self.searchText)
1110                        # pos = line.find(self.searchText)
1111                        # set_style(pos, self.LineInfo) # styling begining of the line
1112                        # set_style(searchTextLength, self.TextToFind) # styling searchText of the line
1113                        # length = length - pos - searchTextLength  # Default styling is applied to RHS
1114                        # state = self.SearchInfo
1115                        # print "LENGTH=",length
1116                       
1117                        # length = length - pos
1118                        # print "line=",line
1119                        startPos=0
1120                        # string line is not use to output to the screen it is local to this fcn therefore it is safe to use lower
1121                        pos = line.lower().find(self.searchText.lower())
1122                        while pos!=-1:
1123                       
1124                            set_style(pos-startPos, self.LineInfo) # styling begining of the line
1125                            set_style(searchTextLength, self.TextToFind) # styling searchText of the line
1126                            startPos=pos+searchTextLength
1127                            pos = line.find(self.searchText,startPos)
1128                            state = self.LineInfo
1129                           
1130                       
1131                        state = self.LineInfo
1132                        length=length-startPos # last value startPos if startPos point to the location right after last found searchText - to continue styling we tell lexer to style reminder of the line (length-startPos) with LineInfo style
1133                    else:
1134                        print "DID NOT FIND SEARCH TEXT"
1135                        # state = self.Default
1136                        state = self.LineInfo
1137                   
1138                    # # the following will style lines like "x = 0"
1139                   
1140                    # pos = line.find('\tFile')
1141                   
1142                    # if pos > 0:
1143                        # set_style(pos, self.SearchInfo) #styling LHS pos is the length of styled text
1144                        # set_style(1, self.FileInfo)#styling = 1 is the length of styled text
1145                        # length = length - pos - 1
1146                        # state = self.SearchInfo
1147                    # else:
1148                        # state = self.Default
1149                else:
1150                    # state = self.Default
1151                    state = self.LineInfo
1152               
1153            set_style(length, state)
1154            # folding implementation goes here
1155            headerLevel = LEVELBASE | HEADERFLAG
1156            # print "HEADER LEVEL",headerLevel
1157           
1158            # if index==0:
1159            if state==self.SearchInfo:
1160                SCI(SETFOLDLEVEL, index, headerLevel)
1161            elif state==self.FileInfo:   
1162                SCI(SETFOLDLEVEL, index, headerLevel+1) # this subheader - inside header for SearchInfo style - have to add +1 to folding level
1163            elif state==self.LineInfo:
1164                SCI(SETFOLDLEVEL, index, LEVELBASE+2) # this is non-header fold line - since it is inside header level and headerLevel +1 i had to add +3 to the  LEVELBASE+2
1165            else:               
1166                SCI(SETFOLDLEVEL, index, LEVELBASE+2) # this is non-header fold line - since it is inside header level and headerLevel +1 i had to add +3 to the  LEVELBASE+2
1167               
1168            index += 1
1169           
1170class ConfigLexer(QsciLexerCustom):
1171    def __init__(self, parent):
1172        QsciLexerCustom.__init__(self, parent)
1173        self._styles = {
1174            0: 'Default',
1175            1: 'MultiLinesComment_Start',
1176            2: 'MultiLinesComment',
1177            3: 'MultiLinesComment_End',
1178            4: 'SingleLineComment'
1179            }
1180        for key,value in self._styles.iteritems():
1181            setattr(self, value, key)
1182        self._foldcompact = True
1183        self.__comment = [self.MultiLinesComment,
1184                          self.MultiLinesComment_End,
1185                          self.MultiLinesComment_Start,
1186                          self.SingleLineComment]
1187
1188    def foldCompact(self):
1189        return self._foldcompact
1190
1191    def setFoldCompact(self, enable):
1192        self._foldcompact = bool(enable)
1193
1194    def language(self):
1195        return 'Config Files'
1196
1197    def description(self, style):
1198        return self._styles.get(style, '')
1199
1200    def defaultColor(self, style):
1201        if style == self.Default:
1202            return QColor('#000000')
1203        elif style in self.__comment:
1204            return QColor('#A0A0A0')
1205        return QsciLexerCustom.defaultColor(self, style)
1206
1207    def defaultFont(self, style):
1208        if style in self.__comment:
1209            if sys.platform in ('win32', 'cygwin'):
1210                return QFont('Comic Sans MS', 9, QFont.Bold)
1211            return QFont('Bitstream Vera Serif', 9, QFont.Bold)
1212        return QsciLexerCustom.defaultFont(self, style)
1213
1214    def defaultPaper(self, style):
1215# Here we change the color of the background.
1216# We want to colorize all the background of the line.
1217# This is done by using the following method defaultEolFill() .
1218        if style in self.__comment:
1219            return QColor('#FFEECC')
1220        return QsciLexerCustom.defaultPaper(self, style)
1221
1222    def defaultEolFill(self, style):
1223# This allowed to colorize all the background of a line.
1224        if style in self.__comment:
1225            return True
1226        return QsciLexerCustom.defaultEolFill(self, style)
1227
1228    def styleText(self, start, end):
1229        editor = self.editor()
1230        if editor is None:
1231            return
1232
1233        SCI = editor.SendScintilla
1234        GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
1235        SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
1236        HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
1237        LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
1238        NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
1239        WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
1240        set_style = self.setStyling
1241
1242        source = ''
1243        if end > editor.length():
1244            end = editor.length()
1245        if end > start:
1246            source = bytearray(end - start)
1247            SCI(QsciScintilla.SCI_GETTEXTRANGE, start, end, source)
1248        if not source:
1249            return
1250
1251        compact = self.foldCompact()
1252
1253        index = SCI(QsciScintilla.SCI_LINEFROMPOSITION, start)
1254        if index > 0:
1255            pos = SCI(QsciScintilla.SCI_GETLINEENDPOSITION, index - 1)
1256            prevState = SCI(QsciScintilla.SCI_GETSTYLEAT, pos)
1257        else:
1258            prevState = self.Default
1259
1260        self.startStyling(start, 0x1f)
1261
1262        for line in source.splitlines(True):
1263# Try to uncomment the following line to see in the console
1264# how Scintiallla works. You have to think in terms of isolated
1265# lines rather than globally on the whole text.
1266#            print line
1267
1268            length = len(line)
1269# We must take care of empty lines.
1270# This is done here.
1271            if length == 1:
1272                if prevState == self.MultiLinesComment or prevState == self.MultiLinesComment_Start:
1273                    newState = self.MultiLinesComment
1274                else:
1275                    newState = self.Default
1276# We work with a non empty line.
1277            else:
1278                if line.startswith('/*'):
1279                    newState = self.MultiLinesComment_Start
1280                elif line.startswith('*/'):
1281                    if prevState == self.MultiLinesComment or prevState == self.MultiLinesComment_Start:
1282                        newState = self.MultiLinesComment_End
1283                    else:
1284                        newState = self.Default
1285                elif line.startswith('//'):
1286                    if prevState == self.MultiLinesComment or prevState == self.MultiLinesComment_Start:
1287                        newState = self.MultiLinesComment
1288                    else:
1289                        newState = self.SingleLineComment
1290                elif prevState == self.MultiLinesComment or prevState == self.MultiLinesComment_Start:
1291                    newState = self.MultiLinesComment
1292                else:             
1293                    newState = self.Default
1294
1295            set_style(length, newState)
1296# Definition of the folding.
1297# Documentation : http://scintilla.sourceforge.net/ScintillaDoc.html#Folding
1298            if newState == self.MultiLinesComment_Start:
1299                if prevState == self.MultiLinesComment:
1300                    level = LEVELBASE + 1
1301                else:
1302                    level = LEVELBASE | HEADERFLAG
1303            elif newState == self.MultiLinesComment or newState == self.MultiLinesComment_End:
1304                level = LEVELBASE + 1
1305            else:
1306                level = LEVELBASE
1307
1308            SCI(SETFOLDLEVEL, index, level)
1309
1310            pos = SCI(QsciScintilla.SCI_GETLINEENDPOSITION, index)
1311            prevState = SCI(QsciScintilla.SCI_GETSTYLEAT, pos)
1312
1313            index += 1
1314       
1315"""
1316Old code with comments and extra stuff
1317class FindDisplayWidget(QsciScintilla):
1318    \"""
1319    Class providing a specialized text edit for displaying logging information.
1320    \"""
1321    def __init__(self, parent = None):
1322        \"""
1323        Constructor
1324       
1325        @param parent reference to the parent widget (QWidget)
1326        \"""
1327        QsciScintilla.__init__(self,parent)
1328        # self.setFolding(5)
1329        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
1330        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDER, QsciScintilla.SC_MARK_PLUS)
1331        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDEROPEN, QsciScintilla.SC_MARK_MINUS)
1332        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDEREND, QsciScintilla.SC_MARK_EMPTY)
1333        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL, QsciScintilla.SC_MARK_EMPTY)
1334
1335        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDEROPENMID, QsciScintilla.SC_MARK_EMPTY);
1336        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDERSUB, QsciScintilla.SC_MARK_EMPTY);
1337        # self.SendScintilla(QsciScintilla.SCI_MARKERDEFINE, QsciScintilla.SC_MARKNUM_FOLDERTAIL, QsciScintilla.SC_MARK_EMPTY);
1338
1339        # self.SendScintilla(QsciScintilla.SCI_SETMARGINWIDTHN, QsciScintilla.MARGIN_SCRIPT_FOLD_INDEX, 0);
1340        # self.SendScintilla(QsciScintilla.SCI_SETMARGINTYPEN,  QsciScintilla.MARGIN_SCRIPT_FOLD_INDEX, QsciScintilla.SC_MARGIN_SYMBOL);
1341        # self.SendScintilla(QsciScintilla.SCI_SETMARGINMASKN, QsciScintilla.MARGIN_SCRIPT_FOLD_INDEX, QsciScintilla.SC_MASK_FOLDERS);
1342        # self.SendScintilla(QsciScintilla.SCI_SETMARGINWIDTHN, QsciScintilla.MARGIN_SCRIPT_FOLD_INDEX, 20);
1343
1344       
1345        # SCI = self.SendScintilla
1346        # GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
1347        # SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
1348        # HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
1349        # LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
1350        # NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
1351        # WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
1352        # set_style = self.setStyling
1353       
1354        # self.SendScintilla(QsciScintilla.SCI_TOGGLEFOLD, 0, 0)
1355        # self.setMarginSensitivity(0,True)
1356        # self.setMarginSensitivity(1,True)
1357        # self.setMarginSensitivity(2,True)
1358        self.setMarginSensitivity(3,True)
1359        # self.setMarginSensitivity(4,True)
1360        # self.setMarginSensitivity(5,True)
1361       
1362        # self.connect(self,SIGNAL(QsciScintilla.SCN_MARGINCLICK("int,int,int")),self.onMarginClick)
1363       
1364       
1365        # QtCore.QObject.connect(self, QtCore.SIGNAL("QsciScintilla.SCN_MARGINCLICK(int,int,int)"), self.onMarginClick)
1366       
1367        #connecting SCN_MARGINCLICK(int,int,int) to margin click
1368        #notice  QsciScintilla.SCN_MARGINCLICK(int,int,int) is not the right name
1369        #
1370        # self.connect(self, SIGNAL("SCN_MARGINCLICK(int,int,int)"), self.onMarginClick)
1371       
1372        # self.connect( QtCore.SIGNAL("QsciScintilla.SCN_MARGINCLICK(int,int,int)"), self.onMarginClick)
1373        # QsciScintilla.SCN_MARGINCLICK.connect(self.onMarginClick)
1374        # print dir(QsciScintilla.SCN_MARGINCLICK)
1375        #qscintilla cpp
1376        # self.marginClicked.connect(self.onMarginClick)
1377       
1378        # margin=2
1379        # mask = self.SendScintilla(QsciScintilla.SCI_GETMODEVENTMASK)
1380       
1381        # self.SendScintilla(QsciScintilla.SCI_SETMODEVENTMASK, mask | QsciScintilla.SC_MOD_CHANGEFOLD);
1382
1383        # self.SendScintilla(QsciScintilla.SCI_SETFOLDFLAGS, QsciScintilla.SC_FOLDFLAG_LINEAFTER_CONTRACTED);
1384
1385        # self.SendScintilla(QsciScintilla.SCI_SETMARGINTYPEN, margin, QsciScintilla.SC_MARGIN_SYMBOL);
1386        # self.SendScintilla(QsciScintilla.SCI_SETMARGINMASKN, margin, QsciScintilla.SC_MASK_FOLDERS);
1387        # self.SendScintilla(QsciScintilla.SCI_SETMARGINSENSITIVEN, margin, 1);       
1388       
1389        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPEN, QsciScintilla.SC_MARK_BOXMINUS);
1390        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDER, QsciScintilla.SC_MARK_BOXPLUS);
1391        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERSUB, QsciScintilla.SC_MARK_VLINE);
1392        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERTAIL, QsciScintilla.SC_MARK_LCORNER);
1393        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEREND, QsciScintilla.SC_MARK_BOXPLUSCONNECTED);
1394        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDEROPENMID, SQsciScintilla.C_MARK_BOXMINUSCONNECTED);
1395        # self.setFoldMarker(QsciScintilla.SC_MARKNUM_FOLDERMIDTAIL, QsciScintilla.SC_MARK_TCORNER);       
1396       
1397       
1398       
1399       
1400        # self.setText("Line 1\nLine2\nLine3\nLine4\nLine5\nLine6\n")
1401        lexer=QsciLexerPython()
1402        print lexer.keywords(1),"\n\n\n\n"
1403        # self.setLexer(QsciLexerPython())
1404
1405        # lexerCustom=CustomLexer(self)
1406        # self.setLexer(lexerCustom)
1407       
1408        findInFilesLexer=FindInFilesLexer(self)
1409        self.setLexer(findInFilesLexer)
1410       
1411        self.setReadOnly(True)
1412       
1413        self.connect(self, SIGNAL("SCN_DOUBLECLICK(int,int,int)"), self.onDoubleClick)
1414       
1415        # self.setText("Search \"DUPA\"\n  File C:\\document.txt\n    Line 85:   DUPA is DUPA is DUPA DUPA\n    Line 88: DUPA IS 2 DUPA\n    Line 89: DUPA IS 2 DUPA\n    Line 89: SUPA IS 2 SUPA\nSearch \"DUPA\"\n  File C:\\document.txt\n    Line 85:   DUPA is DUPA is DUPA DUPA\n    Line 88: DUPA IS 2 DUPA\n    Line 89: DUPA IS 2 DUPA\n    Line 89: SUPA IS 2 SUPA\n")
1416
1417        # newText=QString("Search \"ZUPA\"\n  File C:\\document.txt\n    Line 85:   ZUPA is ZUPA is ZUPA ZUPA\n    Line 88: ZUPA IS 2 ZUPA\n    Line 89: ZUPA IS 2 ZUPA\n    Line 89: SUPA IS 2 SUPA\nSearch \"ZUPA\"\n  File C:\\document.txt\n    Line 85:   ZUPA is ZUPA is ZUPA ZUPA\n    Line 88: ZUPA IS 2 ZUPA\n    Line 89: ZUPA IS 2 ZUPA\n    Line 89: SUPA IS 2 SUPA\n")
1418        # self.insertAt(newText,0,0)   
1419        # self.append(newText) 
1420        GETFOLDLEVEL = QsciScintilla.SCI_GETFOLDLEVEL
1421        SETFOLDLEVEL = QsciScintilla.SCI_SETFOLDLEVEL
1422        HEADERFLAG = QsciScintilla.SC_FOLDLEVELHEADERFLAG
1423        LEVELBASE = QsciScintilla.SC_FOLDLEVELBASE
1424        NUMBERMASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK
1425        WHITEFLAG = QsciScintilla.SC_FOLDLEVELWHITEFLAG
1426       
1427        headerLevel = LEVELBASE | HEADERFLAG
1428        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 0,headerLevel)
1429        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 1,1025)
1430        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 2,1025)
1431        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 3,1025)
1432        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 4,1025)
1433        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 5,9217)
1434        # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 6,1025)
1435        # # self.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 0,QsciScintilla.SC_FOLDLEVELBASE)
1436        # self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, 0, 0);
1437       
1438        lineStart=1       
1439        lineEnd=3
1440        # self.SendScintilla(QsciScintilla.SCI_HIDELINES, lineStart, lineEnd)
1441        # self.SendScintilla(QsciScintilla.SCI_SETFOLDEXPANDED,1, False)
1442        # self.SendScintilla(QsciScintilla.SCI_TOGGLEFOLD,0)
1443        # self.SendScintilla(QsciScintilla.SCI_TOGGLEFOLD,0)
1444       
1445        # SCI_HIDELINES(int lineStart, int lineEnd)
1446        self.lineNumberExtractRegex=re.compile('^[\s]*Line[\s]*([0-9]*)')
1447        self.fileNameWithSearchTextExtractRegex=re.compile('^[\s]*File:[\s]*([\S][\s\S]*)\(')
1448       
1449        print "marginSensitivity=",self.marginSensitivity(0)
1450        # sys.exit()
1451        print 0x00fff
1452        print 0x00400
1453        # sys.exit()
1454       
1455        # QTextEdit.__init__(self, parent)
1456        # self.setAcceptRichText(False)
1457        # self.setLineWrapMode(QTextEdit.NoWrap)
1458        # self.setReadOnly(True)
1459        # self.setFrameStyle(QFrame.NoFrame)
1460       
1461        # # Why do I need this? create the context menu
1462        # # self.__menu = QMenu(self)
1463        # # self.__menu.addAction(self.trUtf8('Clear'), self.clear)
1464        # # self.__menu.addAction(self.trUtf8('Copy'), self.copy)
1465        # # self.__menu.addSeparator()
1466        # # self.__menu.addAction(self.trUtf8('Select All'), self.selectAll)
1467
1468        # self.setContextMenuPolicy(Qt.CustomContextMenu)
1469        # self.connect(self, SIGNAL("customContextMenuRequested(const QPoint &)"),
1470            # self.__handleShowContextMenu)
1471
1472"""
Note: See TracBrowser for help on using the browser.