root/branch/twedit/EditorWindow.py

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

converted print statements into dbgMsg with switchable debug output option

Line 
1"""
2TO DO:
3* window menu
4* help menu
5* expand guessLexer function to include more languages
6* implement file change autosensing
7* list of recent files
8* proper command line handling
9* replace lock files with named mutex on windows and pid search in unix
10* write keyboard shortcut editor widget
11* write lexers for additional languages - extend CustomLexer class
12* handle undo better
13* deal with write protected, hidden, or non-standard files
14* have to find better way to check if a given file is open
15* saveAs dialog should automatically pick extension based on current extension of edited file
16* add printing capabilities
17* add EOL conversion
18* add text encodings
19* add auto completion
20* website
21* help menu
22* find in files should display message - "assembling file list", "searching files"
23* margin click to bookmark/unbookmark
24* easy map from/to tab to/from document name
25* remove dbgMsg(statements )
26* lexer in find in files has to scan entire text before displaying it - otherwise gui may become unresponsive on fold text
27* change name to twedit++
28* cursor change on ? click # done using QtDrawer and setWindowFlags
29* add context menu
30* check what happens if there is python error during binary file execution - perhaps use try /except in the main script to catch any errors in the
31* for new documents save as dialog should open up in directory of the previous widget - if this is not available then default path
32* recent file list may be storing too many elements when destroying tabs before exiting
33* add new function add new document (it inintializes fileDict. ) and avoid maniulating file dict directly
34* figure out how to display binary files including control characters
35* add context menu to clear find in files dialog
36* add fold all/unfoldall - have to change existing toggle fold all
37* python indentation does not work correctly after enter - sohuld assume indent of the previous line - maybe have to do it with API
38 * NOTICE findNext()
39          replace() does not work you have to use findFirst with arguments   
40 
41 * add context menus to tabs (close, delete, rename etc...)
42  * context menu to for editor
43  * Default editor should be removed anyway the moment we open any new file
44  * groups brackets ( ) in regex string have to be escaped - e.g. \(.*\) - have to fix it to make sure you can put regular brackets
45 
46 """
47
48from PyQt4.QtCore import *
49from PyQt4.QtGui import *
50from PyQt4.QtNetwork import *
51from PyQt4.Qsci import *
52
53from PyQt4 import QtCore, QtGui
54import os
55   
56# import application_rc
57import twedit_rc
58import os
59
60from findandreplacedlg import FindAndReplaceDlg
61from findandreplacedlg import FindAndReplaceHistory
62from findandreplacedlg import FindInFilesResults
63from findandreplacedlg import FindDisplayWidget
64from gotolinedlg import GoToLineDlg
65from Configuration import Configuration
66from configurationdlg import ConfigurationDlg
67from LanguageManager import LanguageManager
68from CycleTabsPopup import CycleTabsPopup
69from CycleTabsPopup import CycleTabFileList
70from QsciScintillaCustom import QsciScintillaCustom
71from PrinterTwedit import PrinterTwedit
72
73from DataSocketCommunicators import FileNameReceiver
74import Encoding
75
76import re
77from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF32   
78coding_regexps = [
79    (2, re.compile(r'''coding[:=]\s*([-\w_.]+)''')),
80    (1, re.compile(r'''<\?xml.*\bencoding\s*=\s*['"]([-\w_.]+)['"]\?>''')),
81]     
82
83from findandreplacedlg import ALL_IN_FILES , ALL_IN_ALL_OPEN_DOCS , ALL_IN_CURRENT_DOC
84
85
86from Messaging import stdMsg, dbgMsg, errMsg, setDebugging
87
88
89
90class ChangedTextHandler:
91    def __init__(self,_editor,_editorWindow):
92        self.editor=_editor
93        self.editorWindow=_editorWindow
94       
95    def handleChangedText(self):
96       
97        self.editorWindow.updateTextSizeLabel()
98        # dbgMsg("text in editir ",self.editor, "has changed")
99        # index=self.editorWindow.editTab.indexOf(self.editor)
100        # dbgMsg("isModified=",self.editor.isModified())
101       
102        # self.editorWindow.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-edited.png'))
103        # self.editorWindow.checkActions()
104       
105    def handleModificationChanged(self,m):
106        self.editorWindow.setWindowModified(m)
107        if m: #document has been modified
108            index=self.editorWindow.editTab.indexOf(self.editor)
109            self.editorWindow.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-edited.png'))
110           
111        else: #document has been restored to original state
112            index=self.editorWindow.editTab.indexOf(self.editor)
113            self.editorWindow.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))
114        self.editorWindow.checkActions()
115       
116   
117class EditorWindow(QMainWindow):
118   
119    def __init__(self):
120        super(EditorWindow, self).__init__()
121        self.setWindowIcon(QtGui.QIcon(":/icons/twedit-icon.png"))
122        self.extensionLanguageMap={".py":"Python",
123        ".pyw":"Python",
124        ".xml":"XML",
125        ".c":"C",
126        ".cpp":"C",
127        ".cc":"C",
128        ".cxx":"C",
129        ".h":"C",
130        ".hxx":"C",
131        ".hpp":"C",
132        ".cmake":"CMake",
133        ".cs":"C#",       
134        ".css":"CSS",
135        ".d":"D",
136        ".diff":"Diff",
137        ".patch":"Diff",
138        ".pas":"Pascal",
139        ".inc":"Pascal",
140        ".pl":"Perl",
141        ".rb":"Ruby",
142        ".rbw":"Ruby",
143        ".f":"Fortran77",
144        ".F":"Fortran77",
145        ".f90":"Fortran",
146        ".F90":"Fortran",
147        ".java":"Java",
148        ".js":"JavaScript",
149        ".lua":"Lua",
150        ".ps":"PostScript",
151        ".properties":"Properties",
152        ".pov":"POV",
153        ".cir":"Spice",
154        ".sql":"SQL",
155        ".tcl":"TCL",
156        ".v":"Verilog",
157        ".vhd":"VHDL",
158        ".vhdl":"VHDL",
159        ".yml":"YML",
160        ".bat":"Batch",
161        ".sh":"Bash",
162        ".html":"HTML",
163        ".tex":"TeX"
164        }
165
166        self.fileDialogFilters,self.filterExtensionsDict = self.prepareFileDialogFilters(self.extensionLanguageMap)
167       
168        self.findDialogForm=None # reference to findDialogForm - we check if current value is non-None to make sure we can create an instance. Multiple instances are disallowed
169       
170       
171       
172        # self.udpSocket=QUdpSocket()
173        # # self.udpSocket.bind(QHostAddress.LocalHost,47405)
174        # self.udpSocket.bind(QHostAddress.LocalHost,47405)
175       
176        # self.udpSocket.readyRead.connect(self.readPendingDatagram)
177       
178        self.fileNameReceiver=FileNameReceiver(self)
179       
180        self.fileNameReceiver.newlyReadFileName.connect(self.processNewlyReadFileName)
181       
182        self.textSizeLabel=QLabel("SIZE LABEL")
183        self.currentPositionLabel=QLabel("CURRENT POSITION")
184        self.encodingLabel=QLabel("Encoding")
185       
186        self.statusBar().addPermanentWidget(self.textSizeLabel)
187        self.statusBar().addPermanentWidget(self.currentPositionLabel)
188        self.statusBar().addPermanentWidget(self.encodingLabel)
189       
190        self.deactivateChangeSensing=False
191       
192       
193       
194        self.curFile = ''
195        self.configuration=Configuration()
196       
197        self.zoomRange=self.configuration.setting("ZoomRange")
198       
199        # self.textEdit = QsciScintillaCustom()
200        self.resize(self.configuration.setting("InitialSize"))
201        self.move(self.configuration.setting("InitialPosition"))
202        self.editTab=QTabWidget()
203        self.editTab.setTabsClosable(True)
204        self.editTab.setMovable(True)
205        self.setCentralWidget(self.editTab)
206
207       
208        textEditLocal=QsciScintillaCustom()
209        self.defaultEditor=textEditLocal
210        self.textChangedHandlers={}
211       
212        self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),"New Document "+str(self.editTab.count()+1))
213   
214       
215       
216       
217       
218        textEditLocal.setFocus(True)
219
220        self.textToFind=""
221        # dbgMsg("QsciScintilla.SC_MARK_SHORTARROW=",QsciScintilla.SC_MARK_SHORTARROW)
222       
223        self.setEditorProperties(textEditLocal)
224        # fetching bookmark Mask
225        textEditLocal.markerAdd(0,self.lineBookmark)
226        self.bookmarkMask=textEditLocal.markersAtLine(0)
227        textEditLocal.markerDelete(0)
228        self.indendationGuidesColor=QColor("silver")
229       
230        self.findAndReplaceHistory=FindAndReplaceHistory()
231        self.restoreFindAndReplaceHistory(self.findAndReplaceHistory)
232       
233        self.commentStyleDict={self.editTab.currentWidget():['','']}
234       
235        # self.loadFile("D:\Program Files\ScintillaPy\editor.py")               
236        # self.loadFile("D:\Program Files\ScintillaPy\cellsort_2D.xml")           
237        # self.loadFile("C:\Project_install\ScintillaPy\importer.py")         
238
239       
240        dbgMsg("textEditLocal.braceMatching()=",textEditLocal.braceMatching())
241
242        self.createActions()
243        self.createMenus()
244        self.createToolBars()
245        self.createStatusBar()
246       
247        self.languageManager=LanguageManager(self)
248        self.languageManager.createActions()
249
250       
251        # setting up dock window to display Find in files results
252        self.findDock=self.__createDockWindow("Find Results")
253        self.findDisplayWidget=FindDisplayWidget(self)
254        # self.findDock.setWidget(self.findDisplayWidget)
255        self.__setupDockWindow(self.findDock, Qt.BottomDockWidgetArea, self.findDisplayWidget, self.trUtf8("Find In Files Results"))
256       
257        # self.showFindInFilesDockAct.trigger() # calling toggle does not emit triggered signal and thus action slot is not called. calling trigger does the trick
258       
259        # self.readSettings()
260
261        # self.textEdit.document().contentsChanged.connect(self.documentWasModified)
262
263        self.setCurrentFile('')
264        self.setUnifiedTitleAndToolBarOnMac(True)
265       
266        # self.fileDict={self.editTab.currentWidget():['',0]} # we will store information about editor, file name, modificationtime and encoding in a dictionary:
267        self.fileDict={} # we will store information about editor, file name, modificationtime and encoding in a dictionary:
268        #{key=editorwidget: [fileName,modificationTime,encoding]}
269        self.setPropertiesInEditorList(self.editTab.currentWidget(),'',0)
270        # ,'utf-8'
271       
272        self.textChangedHandlers[textEditLocal]=ChangedTextHandler(textEditLocal,self)
273        # self.editTab.widget(0).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)
274        self.editTab.widget(0).modificationChanged.connect(self.textChangedHandlers[textEditLocal].handleModificationChanged)
275        self.editTab.widget(0).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)
276        self.editTab.widget(0).cursorPositionChanged.connect(self.handleCursorPositionChanged)
277       
278        if self.configuration.setting("RestoreTabsOnStartup"):
279            self.restoreTabs()
280       
281       
282       
283        # self.maybeSaveExternal(self.editTab.currentWidget())
284
285        self.lastFileOpenPath=""
286        self.ctrlTabShortcut=QShortcut(QKeySequence("Ctrl+Tab") ,self)
287        self.connect( self.ctrlTabShortcut, SIGNAL("activated()"), self.cycleTabs )
288        self.ctrlPressed=False # used as a flag to display list of open tabs during cycling
289        self.cycleTabsFlag=False
290        self.cycleTabsPopup=None
291        self.cycleTabFilesList=CycleTabFileList(self)
292   
293    # fcns for accessing/manipulating dictionary storing tab/editor information
294    def getEditorList(self):
295        return self.fileDict.keys()
296       
297    def getCurrentDocumentName(self):
298        # editor=self.editTab.currentWidget()
299        return self.getEditorFileName(self.editTab.currentWidget())
300       
301    def checkIfEditorExists(self,_editor):
302        try:
303            self.fileDict[_editor]
304            return True
305        except KeyError:
306            return False
307       
308    def getEditorFileName(self,_editor):
309        try:
310            return self.fileDict[_editor][0]
311        except (KeyError,IndexError):
312            return ''
313           
314    def getEditorFileModificationTime(self,_editor):
315        try:
316            return self.fileDict[_editor][1]
317        except (KeyError,IndexError):
318            return 0
319           
320    def getEditorFileEncoding(self,_editor):
321        try:
322            return self.fileDict[_editor][2]
323        except (KeyError,IndexError):
324            return '' 
325           
326    def removeEditor(self,_editor):
327        try:
328            del self.fileDict[_editor]
329        except KeyError:
330            pass
331           
332    def setEditorFileName(self,_editor,_name):
333        try:
334            self.fileDict[_editor][0]=_name
335        except (KeyError,IndexError):
336            pass
337           
338    def setEditorFileModificationTime(self,_editor,_time):
339        try:
340            self.fileDict[_editor][1]=_time
341        except (KeyError,IndexError):
342            pass
343           
344    def setEditorFileEncoding(self,_editor,_encoding):
345        try:
346            self.fileDict[_editor][2]=_encoding
347        except (KeyError,IndexError):
348            pass           
349           
350    def setPropertiesInEditorList(self,_editor,_fileName='',_modificationTime=0,_encoding=''):       
351        try:
352            self.fileDict[_editor][0]=_fileName
353            self.fileDict[_editor][1]=_modificationTime
354            self.fileDict[_editor][2]=_encoding
355        except KeyError:
356            self.fileDict[_editor]=[_fileName,_modificationTime,_encoding]
357        except IndexError:
358            pass
359                   
360    def getPropertiesFromEditorList(self,_editor):
361        try:
362            return self.fileDict[_editor]
363        except KeyError:
364            return ('',0,'')
365       
366    # fcns dealing with status bar
367    def handleCursorPositionChanged(self,_line,_index):
368        self.currentPositionLabel.setText("Ln : %s  Col : %s"%(_line,_index))
369       
370    def updateTextSizeLabel(self):
371        editor=self.editTab.currentWidget()
372        try:# incase editor is None
373            self.textSizeLabel.setText("Length : %s  lines : %s"%(editor.length(),editor.lines()))
374        except:
375            pass
376    def updateEncodingLabel(self):
377        editor=self.editTab.currentWidget()
378        try:
379            self.encodingLabel.setText(Encoding.normalizeEncodingName(self.getEditorFileEncoding(editor)))
380           
381        except KeyError:
382            self.encodingLabel.setText("Unknown encoding")
383   
384    def prepareFileDialogFilters(self,_extensionLanguageMap):
385        filterList=QString()
386        filterDict={}
387        for extension, language in _extensionLanguageMap.iteritems():
388            dbgMsg("extension=",extension," language=",language)
389            try:
390                filterDict[language]=filterDict[language]+" *"+extension
391            except KeyError:
392                filterDict[language]="*"+extension
393       
394        keysSorted=filterDict.keys()
395        keysSorted.sort()   
396       
397        # filterDict={} # reassign filter dict
398       
399        for language in keysSorted:           
400            if language=="C":               
401                filterList.append("C/C++"+" file ("+filterDict[language]+")\n")
402                continue
403            if language=="CMake":                               
404                filterList.append(language+" file ("+filterDict[language]+" CMakeLists.*)\n")
405                continue
406               
407            filterList.append(language+" file ("+filterDict[language]+")\n")   
408       
409        filterList.insert(0,"Text file (*.txt)\n")           
410        filterList.insert(0,"All files (*.*)\n")   
411        return filterList,filterDict     
412   
413    def getCurrentFilterString(self,_extension):
414        currentFilter=""
415        language=""
416        if _extension==".txt":
417            return "Text file (*.txt)"
418        try:
419            language=self.extensionLanguageMap[_extension]
420               
421        except KeyError:
422            return currentFilter
423           
424        try:
425            if language=="C":       
426                currentFilter="C/C++"+" file ("+self.filterExtensionsDict[language]+")"
427            else:
428                currentFilter=language+" file ("+self.filterExtensionsDict[language]+")"
429            return currentFilter
430        except KeyError:
431            return currentFilter
432       
433    def getFileNameToEditorWidgetMap(self):
434        openFileDict={}
435        # key is QScintilla widget
436        for key in self.fileDict.keys():
437            if self.fileDict[key][0]!='':
438                openFileDict[self.fileDict[key][0]]=key
439            else:
440                documentName=self.editTab.tabText(self.editTab.indexOf(key))
441                if documentName!='':
442                    openFileDict[documentName]=key
443        return openFileDict       
444               
445    def cycleTabs(self):
446        dbgMsg("CYCLE TABS")
447        if not self.cycleTabsFlag: # first time entering cycle tabs - prepare list of files
448            self.cycleTabsFlag=True
449            # self.tabFileNamesDict=self.getFileNameToEditorWidgetMap()
450            dbgMsg("Preparing list of Tabs")
451           
452            self.cycleTabsPopup=CycleTabsPopup(self)           
453            self.cycleTabFilesList.initializeTabFileList()
454           
455        # if self.tabFileNamesDict: 
456        if self.cycleTabFilesList: 
457           
458            # openFileNames=self.tabFileNamesDict.keys()
459            # dbgMsg("fileNames=",openFileNames)
460            # self.cycleTabsPopup.initializeContent(openFileNames)
461            self.cycleTabFilesList.initializeTabFileList()
462            self.cycleTabsPopup.initializeContent(self.cycleTabFilesList)
463           
464            #setting position of the popup cycle tabs window
465            # geom=self.geometry()
466            # geom_x=geom.x()
467            # geom_y=geom.y()
468            # geom_width=geom.width()
469            # geom_height=geom.height()
470            # dbgMsg("geom_width=",geom_width," geom_height=",geom_height," geom_x=",geom_x," geom_y=",geom_y)
471           
472           
473           
474            self.cycleTabsPopup.move(0,0) #always position popup at (0,0) then calculate required shift
475            self.cycleTabsPopup.adjustSize()
476            # popupPos=self.cycleTabsPopup.pos()
477           
478           
479            #setting position of the popup cycle tabs window
480            geom=self.geometry()           
481            pGeom=self.cycleTabsPopup.geometry()
482            # dbgMsg("pGeom_width=",pGeom.width()," pgeom_height=",pGeom.height()," geom_x=",pGeom.x()," geom_y=",pGeom.y())
483           
484            pCentered_x=geom.x()+(geom.width()-pGeom.width())/2
485            pCentered_y=geom.y()+(geom.height()-pGeom.height())/2
486            # dbgMsg("pCentered_x=",pCentered_x," pCentered_y=",pCentered_y)
487           
488            # dbgMsg("popupPos=",str(popupPos)+"\n\n\n\n")
489           
490            # self.cycleTabsPopup.move(pCentered_x,pCentered_y)
491            # movePos=self.cycleTabsPopup.mapToGlobal(QPoint(500,500))
492            # movePos=self.cycleTabsPopup.mapToGlobal(QPoint(pCentered_x,pCentered_y))
493            # dbgMsg("movePos=",str(movePos))
494            # self.cycleTabsPopup.move(500,500)
495            # self.cycleTabsPopup.move(self.cycleTabsPopup.mapToParent(QPoint(500,500)))
496           
497            # dbgMsg("MOVING TO pCentered_x=",pCentered_x," pCentered_y=",pCentered_y)
498            self.cycleTabsPopup.move(pCentered_x,pCentered_y)
499           
500            # self.cycleTabsPopup.move(640,700)
501           
502            pGeom=self.cycleTabsPopup.geometry()
503            # dbgMsg("AFTER MOVE pGeom_width=",pGeom.width()," pgeom_height=",pGeom.height()," geom_x=",pGeom.x()," geom_y=",pGeom.y()            )
504            # self.cycleTabsPopup.move(2*geom_width/2,2*geom_height/2)
505            # self.cycleTabsPopup.repaint()
506            self.cycleTabsPopup.show()
507           
508           
509            dbgMsg("self.cycleTabsPopup.pos()=",str(self.cycleTabsPopup.pos())+"\n\n\n\n")
510           
511        # if self.ctrlPressed:
512           
513    def keyPressEvent(self, event):
514        if event.key()==Qt.Key_Control:
515            dbgMsg("CTRL key pressed")
516            self.ctrlPressed=True
517        # if event.modifiers()==Qt.CtrlModifier:
518            # dbgMsg("CTRL key pressed")
519            self.ctrlPressed=True
520            # if event.key():
521                # dbgMsg("TAB PRESSED ",event.key())
522               
523    def keyReleaseEvent(self, event):
524        if event.key()==Qt.Key_Control:
525            dbgMsg("CTRL RELEASED")
526            self.ctrlPressed=False
527            if self.cycleTabsFlag: # release cycleTabs flag and switch to new tab
528                self.cycleTabsFlag=False
529                # self.tabFileNamesDict=None
530                # self.cycleTabFilesList=None
531                self.cycleTabsPopup.close()
532                self.cycleTabsPopup=None
533           
534        # if event.modifiers()==Qt.ShiftModifier:
535            # dbgMsg("CTRL key released")
536            # self.ctrlPressed=False
537       
538    # def fcn():
539       
540   
541       
542    # def folding(self):
543        # editor=self.editTab.currentWidget()
544        # lvl = editor.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, 1)
545       
546        # dbgMsg("FOLDING:")
547        # dbgMsg("foldLevel for line 0 is: ", lvl & QsciScintilla.SC_FOLDLEVELNUMBERMASK)
548        # dbgMsg("raw fold level:",lvl)
549        # dbgMsg(lvl & QsciScintilla.SC_FOLDLEVELHEADERFLAG)
550        # lvl1 = editor.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, 4)
551        # dbgMsg("foldLevel for line 13 is: ", lvl1)
552        # dbgMsg(lvl1 & QsciScintilla.SC_FOLDLEVELHEADERFLAG        )
553        # editor.SendScintilla(QsciScintilla.SCI_SETFOLDLEVEL, 7,9217)
554        # # editor.setMarginSensitivity(1,True)
555        # # editor.marginClicked.connect(self.onMarginClick)
556        # # editor.SendScintilla(QsciScintilla.SCI_GETFOLDEXPANDED, line)
557       
558    def onMarginClick(self,_margin,_line, _state):
559        dbgMsg("_margin:",_margin," line:",_line," _state:",_state)
560       
561    def processCommandLine(self):
562        dbgMsg("\n\n\n\n\n PROCESSING CMD LINE")
563        import os
564        for fileName in self.argv:
565            dbgMsg("THIS IS THE FILE TO BE OPEN:", os.path.abspath(fileName))
566            self.loadFile(os.path.abspath(fileName))
567        self.activateWindow()
568           
569       
570   
571    # def readPendingDatagram(self):
572        # dbgMsg("READING PENDING DATAGRAM")
573        # while self.udpSocket.hasPendingDatagrams():
574            # datagram, host, port = self.udpSocket.readDatagram(self.udpSocket.pendingDatagramSize())
575
576            # try:
577                # # Python v3.
578                # datagram = str(datagram, encoding='ascii')
579            # except TypeError:
580                # # Python v2.
581                # pass
582            # dbgMsg("Received datagram: "+datagram)
583            # self.loadFile(os.path.abspath(datagram))
584           
585           
586            # the correct order - accordging to qt website
587            # self.show()
588            # self.raise_()
589            # self.activateWindow()
590           
591           
592
593    def processNewlyReadFileName(self,_fileName):
594        dbgMsg("processNewlyReadFileName fileName=",_fileName)
595        self.loadFile(os.path.abspath(_fileName))
596       
597       
598    def wheelEvent(self, event):
599       
600        dbgMsg("WHEEL EVENT")
601        if qApp.keyboardModifiers()==Qt.ControlModifier:
602            editor=self.editTab.currentWidget()
603           
604            if event.delta()>0:
605                self.zoomIn()
606            else:
607                self.zoomOut()
608               
609            dbgMsg("WHEEL EVENT WITH CTRL")
610        # else:
611            # dbgMsg("IGNORING WHEEL EVENT")
612            # event.ignore()
613            # dbgMsg(self.zoomRange)
614               
615        # if Qt.ControlModifier:
616            # dbgMsg("GOT WHEEL EVENT")
617            # keyboardState=qApp.keyboardModifiers()
618            # dbgMsg(keyboardState==Qt.ControlModifier)
619           
620    def restoreTabs(self):
621        fileList=self.configuration.setting("ListOfOpenFiles")
622        for i in range(fileList.count()):
623            # dbgMsg("RESTORING FILE ", fileList[i])
624            self.loadFile(fileList[i], True)
625           
626        currentTabIndex=self.configuration.setting("CurrentTabIndex")
627        self.editTab.setCurrentIndex(currentTabIndex)       
628         
629    def setArgv(self,_argv):
630        dbgMsg("\n\n\n command line arguments",_argv)
631        self.argv=_argv
632       
633
634   
635    def closeEvent(self, event):
636        # dbgMsg("HAVE THE FOLLOWING DOCUMENTS")
637        openFilesToRestore={}
638        self.deactivateChangeSensing=True
639       
640        # determining index of the current tab       
641       
642        self.configuration.setSetting("CurrentTabIndex",self.editTab.currentIndex())
643       
644        # only file names which are assigned prior to closing are being stored
645        dbgMsg("\n\n\n self.getEditorList()=",self.getEditorList())
646        # dbgMsg("self.fileDict=",self.fileDict)
647        for editor in self.getEditorList():           
648            dbgMsg("OPEN FILE NAME=",self.getEditorFileName(editor))
649            if not self.getEditorFileName(editor)=='':
650                openFilesToRestore[self.editTab.indexOf(editor)]=self.getEditorFileName(editor) # saving file name and position of the tab
651        dbgMsg(" \n\n\n\n openFilesToRestore=",openFilesToRestore)
652        for editor in self.getEditorList():
653                # tabIndex=self.editTab.indexOf(editor)
654                # dbgMsg("CLOSING DOCUMENT TITLE ",self.editTab.tabText(tabIndex))
655
656            # else:
657                # dbgMsg("CLOSING DOCUMENT TITLE ",self.fileDict[editor][0])
658           
659            self.editTab.setCurrentWidget(editor)
660           
661            self.closeTab()
662           
663            # if self.maybeSave():
664                # pass
665           
666                # self.writeSettings()
667        self.deactivateChangeSensing=False
668       
669       
670        #saving open file names to restore
671        self.saveSettingsOpenFilesToRestore(openFilesToRestore)
672        # saving find and replace history
673        self.saveSettingsFindAndReplaceHistory(self.findAndReplaceHistory)
674       
675        self.configuration.setSetting("InitialSize",self.size())
676        # self.configuration.setSetting("InitialState",self.saveState()) #  state of docking windows and their position 
677        self.configuration.setSetting("InitialPosition",self.pos())
678
679        event.accept()
680   
681    def saveSettingsOpenFilesToRestore(self,openFilesToRestore):
682       
683        keys=openFilesToRestore.keys()
684        keys.sort() # sorting by the tab number
685        fileNamesSorted=[openFilesToRestore[key] for key in keys]
686        fileList=QStringList()
687        dbgMsg(dir(fileList))
688        for fileName in fileNamesSorted:
689            fileList.append(fileName)
690        dbgMsg("saving fileList.count()=",fileList.count()    )
691        self.configuration.setSetting("ListOfOpenFiles",fileList)
692       
693        dbgMsg("saveSettingsOpenFilesToRestore")
694       
695    def restoreFindAndReplaceHistory(self,_frh):
696       
697        findHistoryList=self.configuration.setting("FRFindHistory")
698        for i in range(findHistoryList.count()):
699            _frh.findHistory.append(findHistoryList[i])
700           
701        replaceHistoryList=self.configuration.setting("FRReplaceHistory")           
702        for i in range(replaceHistoryList.count()):
703            _frh.replaceHistory.append(replaceHistoryList[i])
704           
705        filtersHistoryList=self.configuration.setting("FRFiltersHistory")                       
706        for i in range(filtersHistoryList.count()):
707            _frh.filtersHistoryIF.append(filtersHistoryList[i])
708           
709        directoryHistoryList=self.configuration.setting("FRDirectoryHistory")                       
710        for i in range(directoryHistoryList.count()):
711            _frh.directoryHistoryIF.append(directoryHistoryList[i])
712       
713        _frh.syntaxIndex=self.configuration.setting("FRSyntaxIndex")       
714        _frh.inSelection=self.configuration.setting("FRInSelection")
715        _frh.inAllSubfolders=self.configuration.setting("FRInAllSubfolders")
716        _frh.opacity=self.configuration.setting("FROpacity")
717        _frh.transparencyEnable=self.configuration.setting("FRTransparencyEnable")       
718        _frh.opacityOnLosingFocus=self.configuration.setting("FROnLosingFocus")       
719        _frh.opacityAlways=self.configuration.setting("FRAlways")
720       
721
722
723       
724       
725    def saveSettingsFindAndReplaceHistory(self,_frh):
726       
727       
728        findHistoryList=QStringList()       
729        for findText in _frh.findHistory:
730            findHistoryList.append(findText)
731        self.configuration.setSetting("FRFindHistory",findHistoryList)
732       
733        replaceHistoryList=QStringList()       
734        for replaceText in _frh.replaceHistory:
735            replaceHistoryList.append(replaceText)
736        self.configuration.setSetting("FRReplaceHistory",replaceHistoryList)
737       
738        filtersHistoryList=QStringList()       
739        for filtersText in _frh.filtersHistoryIF:
740            filtersHistoryList.append(filtersText)
741        self.configuration.setSetting("FRFiltersHistory",filtersHistoryList)
742       
743        directoryHistoryList=QStringList()       
744        for directoryText in _frh.directoryHistoryIF:
745            directoryHistoryList.append(directoryText)
746        self.configuration.setSetting("FRDirectoryHistory",directoryHistoryList)
747       
748       
749        self.configuration.setSetting("FRSyntaxIndex",_frh.syntaxIndex)
750       
751        self.configuration.setSetting("FRInSelection",_frh.inSelection)
752        self.configuration.setSetting("FRInAllSubfolders",_frh.inAllSubfolders)       
753        self.configuration.setSetting("FROpacity",_frh.opacity)
754        self.configuration.setSetting("FRTransparencyEnable",_frh.transparencyEnable)       
755        self.configuration.setSetting("FROnLosingFocus",_frh.opacityOnLosingFocus)       
756        self.configuration.setSetting("FRAlways",_frh.opacityAlways) 
757       
758        dbgMsg("saveSettingsFindAndReplaceHistory"      )
759       
760    # QChangeEvent detects changes in application status such as e.g. being ectivated or not see qt docuentation for more
761    # see also QEvent documentation for list of type of events
762    # event.type() prints numeric value of gien event
763    def changeEvent(self,event):
764        if self.deactivateChangeSensing:
765            return
766        dbgMsg("THIS IS CHANGE EVENT ",event.type())
767        if event.type()==QEvent.ActivationChange:
768            dbgMsg("application focus has changed")
769            dbgMsg("isActiveWindow()=",self.isActiveWindow())
770            if self.isActiveWindow():
771                self.deactivateChangeSensing=True
772                self.checkIfDocumentsWereModified()
773                self.deactivateChangeSensing=False
774            # dbgMsg(self.isActivated())
775           
776    def checkIfDocumentsWereModified(self):
777        for editor in self.getEditorList():
778            fileName=self.getEditorFileName(editor)
779            if fileName!='' and os.path.getmtime(fileName)>self.getEditorFileModificationTime(editor):
780                dbgMsg("DOCUMENT ",fileName, " was modified")
781                reloadFlag=self.maybeReload(editor)
782                if not reloadFlag:
783                    self.setEditorFileModificationTime(editor,os.path.getmtime(fileName))
784                    # self.fileDict[tab][1]=os.path.getmtime(self.fileDict[tab][0])
785                dbgMsg("reloadFlag=",reloadFlag)
786   
787        # for editor in self.getEditorList():
788            # if self.fileDict[tab][0]!='' and os.path.getmtime(self.fileDict[tab][0])>self.fileDict[tab][1]:
789                # dbgMsg("DOCUMENT ",self.fileDict[tab][0], " was modified")
790                # reloadFlag=self.maybeReload(tab)
791                # if not reloadFlag:
792                    # self.fileDict[tab][1]=os.path.getmtime(self.fileDict[tab][0])
793                # dbgMsg("reloadFlag=",reloadFlag)
794               
795       
796       
797    # def paintEvent(self,event):
798        # dbgMsg("paint event")
799
800    # def showEvent(self,event):
801        # dbgMsg("THIS IS SHOW EVENT")
802    # def focusInEvent(self,event):
803        # dbgMsg("GOT FOCUS")
804        # event.accept()
805    # def mouseMoveEvent(self, event):
806        # dbgMsg("Mouse Move Event")
807       
808    def setEditorProperties(self,_editor):
809        # _editor.setMarginLineNumbers(1, self.configuration.setting("DisplayLineNumbers"))
810        # _editor.setMarginWidth(1,QString('0'*7))   
811       
812        # useTabSpaces=self.configuration.setting("UseTabSpaces")
813       
814       
815        # _editor.setIndentationsUseTabs(not useTabSpaces)
816        # if useTabSpaces:
817            # _editor.setIndentationWidth(self.configuration.setting("TabSpaces"))                   
818        # else:
819            # _editor.setIndentationWidth(0)#If width is 0 then the value returned by tabWidth() is used                   
820        # self.lineBookmark = _editor.markerDefine(QsciScintilla.SC_MARK_SHORTARROW) #All editors tab share same markers       
821        # # _editor.setMarginMarkerMask(2,QsciScintilla.SC_MARK_SHORTARROW) # mask has to correspond to marker number returned by markerDefine or it has to simply be 0 not sure
822        # _editor.setMarginMarkerMask(2,QsciScintilla.SC_MARK_SHORTARROW) # mask has to correspond to marker number returned by markerDefine or it has to simply be 0 not sure
823       
824        #lines are displayed on margin 0
825        _editor.setMarginLineNumbers(0, self.configuration.setting("DisplayLineNumbers"))
826        _editor.setMarginWidth(0,QString('0'*8))     
827       
828        useTabSpaces=self.configuration.setting("UseTabSpaces")
829       
830       
831        _editor.setIndentationsUseTabs(not useTabSpaces)
832        if useTabSpaces:
833            _editor.setIndentationWidth(self.configuration.setting("TabSpaces"))                   
834        else:
835            _editor.setIndentationWidth(0)#If width is 0 then the value returned by tabWidth() is used                   
836        self.lineBookmark = _editor.markerDefine(QsciScintilla.SC_MARK_SHORTARROW) #All editors tab share same markers       
837        # _editor.setMarginMarkerMask(2,QsciScintilla.SC_MARK_SHORTARROW) # mask has to correspond to marker number returned by markerDefine or it has to simply be 0 not sure
838       
839        #Bookmarks are displayed on margin 1 but I have to pass 2 to set mask for margin 1 
840        _editor.setMarginMarkerMask(2,QsciScintilla.SC_MARK_SHORTARROW) # mask has to correspond to marker number returned by markerDefine or it has to simply be 0 not sure
841       
842        # dbgMsg("MASK 0=",_editor.marginMarkerMask(0))
843        # dbgMsg("MASK 1=",_editor.marginMarkerMask(1))
844        # dbgMsg("MASK 2=",_editor.marginMarkerMask(2))
845        #enable bookmarking by click
846        _editor.setMarginSensitivity(1,True)       
847        _editor.marginClicked.connect(self.marginClickedHandler)
848       
849        _editor.setMarkerBackgroundColor(QColor("lightsteelblue"), self.lineBookmark)
850       
851        if self.configuration.setting("FoldText"):
852            _editor.setFolding(QsciScintilla.BoxedTreeFoldStyle)
853        else:
854            _editor.setFolding(QsciScintilla.NoFoldStyle)
855        _editor.setCaretLineVisible(True)
856        _editor.setCaretLineBackgroundColor(QtGui.QColor('#EFEFFB'))       
857        # _editor.modificationChanged.connect(self.modificationChangedSlot)
858       
859        # _editor.setEolMode(QsciScintilla.EolWindows) # SETTING EOL TO WINDOWS MESSES THINGS UP AS SAVE FCN (MOST LIKELY)ADS EXTRA CR SIGNS -
860        # _editor.setEolMode(QsciScintilla.EolUnix) # SETTING EOL TO WINDOWS MESSES THINGS UP AS SAVE FCN (MOST LIKELY)ADS EXTRA CR SIGNS -
861        # _editor.setEolMode(QsciScintilla.EolMac) # SETTING EOL TO WINDOWS MESSES THINGS UP AS SAVE FCN (MOST LIKELY)ADS EXTRA CR SIGNS -
862        # _editor.setUtf8(True) # using UTF-8 encoding
863       
864       
865        displayWhitespace=self.configuration.setting("DisplayWhitespace")
866        if displayWhitespace:
867            _editor.setWhitespaceVisibility(QsciScintilla.SCWS_VISIBLEALWAYS)
868        else:
869            _editor.setWhitespaceVisibility(QsciScintilla.SCWS_INVISIBLE)
870
871        displayEol=self.configuration.setting("DisplayEOL")
872        _editor.setEolVisibility(displayEol)
873
874        wrapLines=self.configuration.setting("WrapLines")
875        showWrapSymbol=self.configuration.setting("ShowWrapSymbol")
876       
877        if wrapLines:
878            _editor.setWrapMode(QsciScintilla.WrapWord)
879            if showWrapSymbol:
880                _editor.setWrapVisualFlags(QsciScintilla.WrapFlagByText)
881            # else:
882           
883        # else:
884            # self.editTab.widget(i).setWrapMode(QsciScintilla.WrapNone)
885           
886       
887    # def configureWrapLines(self,_flag):
888        # numberOfDocuments=self.editTab.count()
889        # for i in  range(numberOfDocuments):
890            # if _flag:           
891                # self.editTab.widget(i).setWrapMode(QsciScintilla.WrapWord)
892            # else:
893                # self.editTab.widget(i).setWrapMode(QsciScintilla.WrapNone)
894
895    # def configureShowWrapSymbol(self,_flag):
896        # numberOfDocuments=self.editTab.count()       
897        # for i in  range(numberOfDocuments):
898            # if _flag:           
899                # self.editTab.widget(i).setWrapVisualFlags(QsciScintilla.WrapFlagByText)
900            # else:
901                # self.editTab.widget(i).setWrapVisualFlags(QsciScintilla.WrapFlagNone)       
902       
903        # dbgMsg("lineBookmark=",self.lineBookmark)
904       
905        #markers
906       
907        # self.warning = self.markerDefine(QPixmap(get_image_path('warning.png'),
908                                                 # 'png'))
909       
910    def modificationChangedSlot(self, _flag):
911        dbgMsg("THIS IS CHANGED DOCUMENT")
912       
913    # def blockComment(self):
914        # editor=self.editTab.currentWidget()       
915        # if not self.commentStyleDict[editor][0]: # this language does not allow comments
916            # return
917       
918        # commentStringBegin=self.commentStyleDict[editor][0]
919        # commentStringEnd=self.commentStyleDict[editor][1]
920
921       
922        # if editor.hasSelectedText():
923            # line_from, _index_from, line_to, _index_to = editor.getSelection()
924            # if _index_to==0: # do not comment last line if no character in this line is selected
925                # line_to-=1
926            # if commentStringEnd:# handling comments which require additions at the beginning and at the end of the line
927                # editor.beginUndoAction()           
928                # for l in range(line_from, line_to+1):
929                    # # if not editor.text(l).length():
930                    # if editor.text(l).trimmed().isEmpty(): # checking if the line contains non-white characters
931                        # continue
932                    # editor.insertAt( commentStringBegin , l, 0 )       
933                    # editor.insertAt( commentStringEnd , l, editor.lineLength(l)-1)       
934                # editor.endUndoAction()   
935            # else:# handling comments which require additions only at the beginning of the line
936                # editor.beginUndoAction()           
937                # for l in range(line_from, line_to+1):
938                    # if editor.text(l).trimmed().isEmpty(): # checking if the line contains non-white characters
939                        # continue               
940                    # editor.insertAt( commentStringBegin , l, 0 )       
941                # editor.endUndoAction()   
942            # if _index_to==0:
943                # line_to+=1           
944            # editor.setSelection(line_from, _index_from, line_to, _index_to)
945            # dbgMsg("SELECTED TEXT")
946        # else: # single line comments
947            # currentLine,currentColumn=editor.getCursorPosition()           
948            # if commentStringEnd: # handling comments which require additions at the beginning and at the end of the line               
949                # if not editor.text(currentLine).trimmed().isEmpty(): # checking if the line contains non-white characters
950                    # editor.beginUndoAction()           
951                    # editor.insertAt( commentStringBegin , currentLine, 0 ) 
952                    # dbgMsg("currentLineLength=",editor.text(currentLine).size())
953                    # dbgMsg("editor.text(currentLine)=",editor.text(currentLine),"|")
954                    # # we have to account for the fact the EOL character can be CR LF or CR or LF
955                    # eolPos=editor.text(currentLine).size()
956                    # lineText=editor.text(currentLine)
957                    # if lineText[eolPos-2]=="\r" or lineText[eolPos-2]=="\n":# second option is just in case - checking if we are dealign with CR LF or simple CR or LF end of line                   
958                        # editor.insertAt( commentStringEnd , currentLine, eolPos-2)                       
959                    # else:
960                        # editor.insertAt( commentStringEnd , currentLine, eolPos-1)
961                    # editor.endUndoAction()   
962            # else:# handling comments which require additions only at the beginning of the line
963                # if not editor.text(currentLine).trimmed().isEmpty(): # checking if the line contains non-white characters
964                    # editor.beginUndoAction()                           
965                    # editor.insertAt( commentStringBegin , currentLine, 0 )               
966                    # editor.endUndoAction()   
967                   
968    def blockComment(self):
969        editor=self.editTab.currentWidget()       
970        if not self.commentStyleDict[editor][0]: # this language does not allow comments
971            return
972       
973        commentStringBegin=self.commentStyleDict[editor][0]
974        commentStringEnd=self.commentStyleDict[editor][1]
975
976       
977        if editor.hasSelectedText():
978            line_from, index_from, line_to, index_to = editor.getSelection()
979            if index_to==0: # do not comment last line if no character in this line is selected
980                line_to-=1
981               
982            editor.endUndoAction()     
983            for l in range(line_from, line_to+1):
984                # dbgMsg("inside loop of single line comments=",l)
985                self.commentSingleLine(l,commentStringBegin,commentStringEnd)       
986            editor.endUndoAction()   
987               
988 
989            # dbgMsg("line_from, _index_from, line_to, _index_to=",line_from, index_from, line_to, index_to)
990            # restoring selection 
991            if index_to==0:
992                line_to+=1       
993                editor.setSelection(line_from, index_from+len(commentStringBegin), line_to, index_to)
994            else:
995                editor.setSelection(line_from, index_from+len(commentStringBegin), line_to, index_to+len(commentStringBegin))   
996           
997                         
998           
999 
1000        else: # single line comments
1001            currentLine,currentColumn=editor.getCursorPosition()           
1002            editor.beginUndoAction()                           
1003            self.commentSingleLine(currentLine,commentStringBegin,commentStringEnd)                   
1004            editor.endUndoAction()             
1005           
1006                   
1007    def commentSingleLine(self,currentLine,commentStringBegin,commentStringEnd):
1008        editor=self.editTab.currentWidget()
1009        # dbgMsg("trying to comment current line:",editor.text(currentLine))
1010        if commentStringEnd: # handling comments which require additions at the beginning and at the end of the line   
1011           
1012            if not editor.text(currentLine).trimmed().isEmpty(): # checking if the line contains non-white characters
1013                # editor.beginUndoAction()           
1014                editor.insertAt( commentStringBegin , currentLine, 0 ) 
1015                # dbgMsg("currentLineLength=",editor.text(currentLine).size())
1016                # dbgMsg("editor.text(currentLine)=",editor.text(currentLine),"|")
1017                # we have to account for the fact the EOL character can be CR LF or CR or LF
1018                eolPos=editor.text(currentLine).size()
1019                lineText=editor.text(currentLine)
1020                if lineText[eolPos-2]=="\r" or lineText[eolPos-2]=="\n":# second option is just in case - checking if we are dealign with CR LF or simple CR or LF end of line                   
1021                    editor.insertAt( commentStringEnd , currentLine, eolPos-2)                       
1022                else:
1023                    editor.insertAt( commentStringEnd , currentLine, eolPos-1)
1024                # editor.endUndoAction()   
1025        else:# handling comments which require additions only at the beginning of the line
1026            if not editor.text(currentLine).trimmed().isEmpty(): # checking if the line contains non-white characters
1027                # editor.beginUndoAction()                           
1028                editor.insertAt( commentStringBegin , currentLine, 0 )               
1029                # editor.endUndoAction()   
1030       
1031   
1032    def copy(self):
1033        editor=self.editTab.currentWidget()
1034        editor.copy()
1035       
1036    def cut(self):
1037        editor=self.editTab.currentWidget()
1038        editor.cut()
1039   
1040       
1041    def paste(self):
1042        editor=self.editTab.currentWidget()
1043        editor.paste()
1044       
1045    def increaseIndent(self):
1046        # editor=self.editTab.currentWidget()
1047        # line, index = editor.getCursorPosition()
1048        # editor.indent(line)
1049        editor=self.editTab.currentWidget()
1050        line, index = editor.getCursorPosition()
1051        if editor.hasSelectedText():
1052            line_from, index_from, line_to, index_to = editor.getSelection()
1053            if index_to == 0 :
1054                line_to -= 1       
1055            editor.beginUndoAction()
1056            for line in range(line_from, line_to+1):
1057       
1058                editor.indent(line)
1059            editor.endUndoAction()
1060        else: # here I sohuld insert indenttion inside the string in the current position
1061            tabString=""
1062            indentationWidth=1
1063            if editor.indentationsUseTabs():
1064                tabString="\t"
1065            else:
1066                indentationWidth=editor.indentationWidth()
1067                tabString=" "*indentationWidth
1068               
1069            editor.insertAt(tabString,line, index)
1070            editor.setCursorPosition(line,index+indentationWidth)
1071            # editor.indent(line)
1072            # dbgMsg("USING TABS TO INDENT=",editor.indentationsUseTabs() ,"tabWidth=",editor.tabWidth())
1073
1074    def decreaseIndent(self):
1075        editor=self.editTab.currentWidget()
1076        line, index = editor.getCursorPosition()
1077        if editor.hasSelectedText():
1078            line_from, index_from, line_to, index_to = editor.getSelection()
1079            if index_to == 0 :
1080                line_to -= 1       
1081            editor.beginUndoAction()
1082            for line in range(line_from, line_to+1):
1083       
1084                editor.unindent(line)
1085            editor.endUndoAction()
1086        else:
1087            editor.unindent(line)
1088           
1089    def blockUncomment(self):
1090        editor=self.editTab.currentWidget()
1091        if not self.commentStyleDict[editor][0]: # this language does not allow comments
1092            return           
1093           
1094        commentStringBegin=QString(self.commentStyleDict[editor][0])
1095        commentStringBeginTrunc=commentStringBegin.trimmed() # comments without white spaces
1096       
1097       
1098        if commentStringBeginTrunc=="REM":
1099            commentStringBeginTrunc=commentStringBegin # comments which begin with a word  - e.g. REM should not be truncated
1100       
1101        commentStringEnd=QString()
1102        if self.commentStyleDict[editor][1]:
1103            commentStringEnd=QString(self.commentStyleDict[editor][1])
1104        commentStringEndTrunc=commentStringEnd.trimmed()
1105       
1106       
1107        if editor.hasSelectedText():
1108            line_from, index_from, line_to, index_to = editor.getSelection()
1109            if index_to == 0 :
1110                line_to -= 1       
1111            firstLineBeginCommentLength=0
1112            lastLineBeginCommentLength=0           
1113           
1114            editor.beginUndoAction()
1115           
1116            for line in range(line_from, line_to+1):
1117           
1118                beginCommentLength,endCommentLength = self.uncommentLine(line,commentStringBegin,commentStringBeginTrunc,commentStringEnd,commentStringEndTrunc)
1119                if line==line_from:
1120                    firstLineBeginCommentLength=beginCommentLength
1121                if line==line_to:
1122                    lastLineBeginCommentLength=beginCommentLength
1123            editor.endUndoAction()
1124           
1125            # restoring selection 
1126            if index_to==0:
1127                line_to+=1       
1128                editor.setSelection(line_from, index_from-firstLineBeginCommentLength, line_to, index_to)
1129            else:
1130                editor.setSelection(line_from, index_from-firstLineBeginCommentLength, line_to, index_to-lastLineBeginCommentLength)
1131                # editor.setSelection(line_from, index_from+len(commentStringBegin), line_to, index_to+len(commentStringBegin))   
1132           
1133            # restoring selection               
1134            # editor.setSelection(line_from, index_from-firstLineBeginCommentLength, line_to, index_to-lastLineBeginCommentLength)
1135           
1136        else:
1137         
1138            # Uncomment current line
1139            line, index = editor.getCursorPosition()
1140            editor.beginUndoAction()           
1141            self.uncommentLine(line,commentStringBegin,commentStringBeginTrunc,commentStringEnd,commentStringEndTrunc)           
1142            editor.endUndoAction()
1143           
1144 
1145    # def uncommentLine(self,line,commentStringBegin,commentStringBeginTrunc,commentStringEnd,commentStringEndTrunc):
1146        # # line, index = editor.getCursorPosition()
1147        # editor=self.editTab.currentWidget()
1148        # commentsFound=False
1149       
1150        # lineText=editor.text(line)
1151        # origLineTextLength=lineText.length()
1152        # indexOf=lineText.indexOf(commentStringBegin)
1153
1154        # #processing begining of the line   
1155        # if indexOf != -1:
1156            # lineText.remove(indexOf,commentStringBegin.size())
1157            # commentsFound=True
1158
1159        # else:
1160            # indexOf=lineText.indexOf(commentStringBeginTrunc)
1161            # if indexOf != -1:
1162                # lineText.remove(indexOf,commentStringBeginTrunc.size())
1163                # commentsFound=True
1164               
1165        # if  commentStringEnd.size()  :
1166       
1167            # #processing begining of the line   
1168            # lastIndexOf=lineText.lastIndexOf(commentStringEnd)
1169            # if lastIndexOf!=-1 :
1170                # lineText.remove(lastIndexOf,commentStringEnd.size())
1171                # commentsFound=True
1172            # else:
1173                # lastIndexOf=lineText.lastIndexOf(commentStringEndTrunc)
1174                # if lastIndexOf!=-1 :
1175                    # lineText.remove(lastIndexOf,commentStringEndTrunc.size())
1176                    # commentsFound=True
1177                   
1178        # if commentsFound:
1179       
1180            # editor.setSelection(line,0,line,origLineTextLength)
1181            # editor.removeSelectedText()
1182            # editor.insertAt(lineText,line,0)       
1183           
1184    def uncommentLine(self,line,commentStringBegin,commentStringBeginTrunc,commentStringEnd,commentStringEndTrunc):
1185        # line, index = editor.getCursorPosition()
1186        editor=self.editTab.currentWidget()
1187        commentsFound=False
1188       
1189        lineText=editor.text(line)
1190        origLineTextLength=lineText.size()
1191        indexOf=lineText.indexOf(commentStringBegin)
1192       
1193        beginCommentLength=0
1194        endCommentLength=0
1195       
1196        #processing begining of the line   
1197        if indexOf != -1:
1198            lineText.remove(indexOf,commentStringBegin.size())
1199            beginCommentLength=commentStringBegin.size()
1200            commentsFound=True
1201
1202        else:
1203            indexOf=lineText.indexOf(commentStringBeginTrunc)
1204            if indexOf != -1:
1205                lineText.remove(indexOf,commentStringBeginTrunc.size())
1206                beginCommentLength=commentStringBeginTrunc.size()
1207                commentsFound=True
1208               
1209        if  commentStringEnd.size()  :
1210       
1211            #processing begining of the line   
1212            lastIndexOf=lineText.lastIndexOf(commentStringEnd)
1213            if lastIndexOf!=-1 :
1214                lineText.remove(lastIndexOf,commentStringEnd.size())
1215                endCommentLength=commentStringEnd.size()
1216                commentsFound=True
1217            else:
1218                lastIndexOf=lineText.lastIndexOf(commentStringEndTrunc)
1219                if lastIndexOf!=-1 :
1220                    lineText.remove(lastIndexOf,commentStringEndTrunc.size())
1221                    endCommentLength=commentStringEndTrunc.size()
1222                    commentsFound=True
1223                   
1224        if commentsFound:
1225            eolPos=lineText.size()           
1226            if lineText[eolPos-2]=="\r" or lineText[eolPos-2]=="\n":# second option is just in case - checking if we are dealign with CR LF or simple CR or LF end of line                                       
1227                editor.setSelection(line,0,line,origLineTextLength-1)
1228            else:
1229                editor.setSelection(line,0,line,origLineTextLength)
1230               
1231            editor.removeSelectedText()
1232           
1233            editor.insertAt(lineText,line,0)   
1234           
1235        return beginCommentLength,endCommentLength   
1236   
1237    def find(self):
1238
1239        if self.findDialogForm:
1240            self.findDialogForm.show()
1241            return
1242           
1243        self.findDialogForm = FindAndReplaceDlg("",self)
1244        self.findDialogForm.setFindAndReaplceHistory(self.findAndReplaceHistory)
1245       
1246        # putting highlighted text into findLineEdit
1247        editor=self.editTab.currentWidget()
1248       
1249
1250            # line_before, index_before = editor.getCursorPosition()
1251            # line_from, index_from, line_to, index_to = editor.getSelection()       
1252       
1253        # form.initializeForm(self.findAndReplaceHistory)
1254        # self.findAndReplaceHistory.newFindText(form.findText())
1255        # self.findDialogForm.searchingSignal.connect(self.findDialogForm.findNext)
1256        self.findDialogForm.searchingSignal.connect(self.findNext)
1257        self.findDialogForm.replacingSignal.connect(self.replaceNext)
1258        self.findDialogForm.replacingAllSignal.connect(self.replaceAll)
1259        self.findDialogForm.initializeDialog(self.findAndReplaceHistory)
1260       
1261        if editor.hasSelectedText():
1262            self.findDialogForm.findLineEdit.setText(editor.selectedText())       
1263       
1264        # find in files
1265        self.findDialogForm.searchingSignalIF.connect(self.findInFiles)
1266        self.findDialogForm.replacingSignalIF.connect(self.replaceInFiles)
1267        #find All in All open Docs
1268        self.findDialogForm.searchingAllInAllOpenDocsSignal.connect(self.findInFiles)
1269       
1270        #replace All in All open Docs
1271        self.findDialogForm.replacingAllInOpenDocsSignal.connect(self.replaceInFiles)
1272       
1273        # form.connect(form, form.searchingSignal, self.findNext)
1274        # form.connect(form, SIGNAL("notfound"), nomore)   
1275        self.findDialogForm.show()   
1276       
1277    def findInFiles(self,_text,_filters,_directory,_mode=ALL_IN_FILES):
1278        dbgMsg("findInFiles")
1279        # ALL_IN_FILES=0
1280        # ALL_IN_ALL_OPEN_DOCS=1
1281        # ALL_IN_CURRENT_DOC=2   
1282       
1283        dbgMsg("search parameters",_text," ", _filters," ",_directory)
1284
1285        reFlag=False
1286       
1287        if str(self.findDialogForm.syntaxComboBoxIF.currentText())=="Regular expression":
1288            reFlag=True       
1289           
1290        newSearchFlag=self.findAndReplaceHistory.newSearchParametersIF(_text,_filters,_directory)       
1291       
1292        self.findDialogForm.initializeAllSearchLists(self.findAndReplaceHistory)
1293       
1294        # self.findDialogForm.findComboBoxIF.clear()
1295        # self.findDialogForm.filtersComboBoxIF.clear()
1296        # self.findDialogForm.directoryComboBoxIF.clear()
1297        # self.findDialogForm.findComboBoxIF.addItems(self.findAndReplaceHistory.findHistoryIF)
1298        # self.findDialogForm.filtersComboBoxIF.addItems(self.findAndReplaceHistory.filtersHistoryIF)
1299        # self.findDialogForm.directoryComboBoxIF.addItems(self.findAndReplaceHistory.directoryHistoryIF)
1300       
1301        #constructing the list of files to be searched based on directory and filters input
1302       
1303        import fnmatch
1304        import os
1305        filters=str(_filters).split()
1306        dbgMsg(filters)
1307       
1308        matches = []
1309        if _mode==ALL_IN_FILES:
1310            for filter in filters:
1311                if self.findDialogForm.inAllSubFoldersCheckBoxIF.isChecked():
1312                    for root, dirnames, filenames in os.walk(str(_directory)):
1313                        for filename in fnmatch.filter(filenames, filter):
1314                            matches.append(os.path.join(root, filename))
1315                else:
1316                    root=str(_directory)
1317                    for filename in os.listdir(root):
1318                        if fnmatch.fnmatch(filename, filter):
1319                            matches.append(os.path.join(root, filename))
1320                       
1321
1322               
1323           
1324        # dbgMsg("matches=",matches)
1325       
1326        foundFiles=[]
1327       
1328        if _mode==ALL_IN_FILES:
1329            foundFiles=self.findFiles(matches,_text,reFlag)
1330        elif _mode==ALL_IN_ALL_OPEN_DOCS:
1331            foundFiles=self.findAllInOpenDocs(_text,reFlag)           
1332        elif _mode==ALL_IN_CURRENT_DOC:
1333            foundFiles=self.findAllInOpenDocs(_text,reFlag,True)
1334        else:
1335            return
1336           
1337        # dbgMsg("FOUND FILES",foundFiles)
1338        # for findInFileResult in foundFiles:
1339            # dbgMsg(findInFileResult.lineOccurences)
1340        # if len(foundFiles):
1341            # dbgMsg(foundFiles[0].produceSummaryRepr(foundFiles)    )
1342        findInFilesFormatter=FindInFilesResults()  # use  empty FindInFilesResults object as a formatter         
1343        self.findDisplayWidget.addNewFindInFilesResults(findInFilesFormatter.produceSummaryRepr(foundFiles,_text))
1344        if not self.showFindInFilesDockAct.isChecked():
1345            self.showFindInFilesDockAct.trigger() # calling toggle does not emit triggered signal and thus action slot is not called. calling trigger does the trick
1346           
1347        # findInFileResultRepr=""
1348        # totalhits=0
1349        # for findInFileResult in foundFiles:
1350            # findInFileResultRepr+="Search \""+str(findInFileResult.textToFind)+"\"\n"
1351            # totalHits+=findInFileResult.
1352            # findInFileResultRepr+=findInFileResult.__str__()
1353            # # dbgMsg(findInFileResult)
1354        # dbgMsg(findInFileResultRepr    )
1355        # #possible implementation of grep   
1356        # import sys
1357
1358        # pattern = sys.argv[1]
1359        # filename = sys.argv[2]
1360
1361        # data = [line.split() for  line in open(filename,'r')]
1362        # for k in range(len(data)-len(pattern)):
1363            # s = ''.join([data[k+j][2] for j in range(len(pattern))])
1364            # if s == pattern:
1365                # for j in range(len(pattern)):
1366                    # dbgMsg(data[k+j][0]        )
1367                   
1368    def findAllInOpenDocs(self,_text,_reFlag=False, _inCurrentDoc=False):
1369        # progress dialog not necessary here
1370        foundFiles = []
1371        editorList=[]
1372        if _inCurrentDoc:
1373            editorList.append(self.editTab.currentWidget())
1374        else:
1375            editorList=self.getEditorList()
1376       
1377        for editor in editorList:
1378            currentLine,currentIndex = editor.getCursorPosition() # record current cursor position
1379            filename=self.getEditorFileName(editor)
1380            if filename=='':
1381                continue # we do not allow searching in the unsaved files
1382           
1383            foundFlag=editor.findFirst(_text,_reFlag,\
1384            self.findDialogForm.caseCheckBox.isChecked(),\
1385            self.findDialogForm.wholeCheckBox.isChecked(),\
1386            False,\
1387            True,0,0,False)           
1388           
1389            findResults=None
1390            if foundFlag:
1391                foundFiles.append(FindInFilesResults(filename,_text))
1392                findResults=foundFiles[-1]
1393               
1394            while foundFlag:
1395                line,index=editor.getCursorPosition()
1396                # dbgMsg("FOUND OCCURENCE IN LINE ",line)
1397                findResults.addLineWithText(line,editor.text(line))
1398                foundFlag=editor.findNext()
1399               
1400            editor.setCursorPosition(currentLine,currentIndex)   # restore cursor position
1401           
1402        return foundFiles   
1403   
1404    def findFiles(self, _files, _text,_reFlag=False):
1405        progressDialog = QtGui.QProgressDialog(self)
1406
1407        progressDialog.setCancelButtonText("&Cancel")
1408        numberOfFiles=len(_files)
1409        progressDialog.setRange(0, numberOfFiles)
1410        progressDialog.setWindowTitle("Find Text in Files")
1411
1412        foundFiles = []
1413        i=1
1414        for filename in _files:
1415            # dbgMsg("SEARCHING ", filename)
1416            progressDialog.setValue(i)
1417            progressDialog.setLabelText("Searching file number %d of %d..." % (i, numberOfFiles))
1418            QtGui.qApp.processEvents()
1419
1420            if progressDialog.wasCanceled():
1421                break
1422
1423            inFile = QtCore.QFile(filename)
1424
1425            if inFile.open(QtCore.QIODevice.ReadOnly):
1426                stream = QtCore.QTextStream(inFile)
1427               
1428                textEditLocal=QsciScintillaCustom()
1429               
1430                textEditLocal.setText(stream.readAll())
1431               
1432                foundFlag=textEditLocal.findFirst(_text,_reFlag,\
1433                self.findDialogForm.caseCheckBoxIF.isChecked(),\
1434                self.findDialogForm.wholeCheckBoxIF.isChecked(),\
1435                False,\
1436                True,0,0,False)     
1437                findResults=None
1438                if foundFlag:
1439                    foundFiles.append(FindInFilesResults(filename,_text))
1440                    findResults=foundFiles[-1]
1441                   
1442                while foundFlag:
1443                    line,index=textEditLocal.getCursorPosition()
1444                    # dbgMsg("FOUND OCCURENCE IN LINE ",line)
1445                    findResults.addLineWithText(line,textEditLocal.text(line))
1446                    foundFlag=textEditLocal.findNext()
1447                         
1448                # while not stream.atEnd():
1449                    # if progressDialog.wasCanceled():
1450                        # break
1451                    # line = stream.readLine()
1452                    # if text in line:
1453                        # foundFiles.append(filename)
1454                        # break
1455            i+=1
1456        progressDialog.close()
1457
1458        return foundFiles
1459       
1460       
1461        # for filename in files:
1462            # dbgMsg("SEARCHING ", filename)
1463            # progressDialog.setValue(i)
1464            # progressDialog.setLabelText("Searching file number %d of %d..." % (i, numberOfFiles))
1465            # QtGui.qApp.processEvents()
1466
1467            # if progressDialog.wasCanceled():
1468                # break
1469
1470            # inFile = QtCore.QFile(filename)
1471
1472            # if inFile.open(QtCore.QIODevice.ReadOnly):
1473                # stream = QtCore.QTextStream(inFile)
1474                # while not stream.atEnd():
1475                    # if progressDialog.wasCanceled():
1476                        # break
1477                    # line = stream.readLine()
1478                    # if text in line:
1479                        # foundFiles.append(filename)
1480                        # break
1481
1482        # progressDialog.close()
1483
1484        # return foundFiles
1485    def replaceInFiles(self,_text,_replaceText,_filters,_directory,_mode=ALL_IN_FILES):
1486        # dbgMsg("search parameters",_text," ", _filters," ",_directory)
1487        message="About to replace all occurences of <b>\"%s\"</b>  <br> in ALL <b>\"%s\"</b> files inside directory:<br> %s  <br> Proceed?"%(_text,_filters,_directory)
1488        ret = QtGui.QMessageBox.warning(self, "Replace in Files",
1489                message,
1490                QtGui.QMessageBox.Ok |QtGui.QMessageBox.Cancel)
1491        if ret == QtGui.QMessageBox.Cancel:           
1492            return 
1493           
1494           
1495        reFlag=False
1496       
1497        if str(self.findDialogForm.syntaxComboBoxIF.currentText())=="Regular expression":
1498            reFlag=True       
1499           
1500        newSearchFlag=self.findAndReplaceHistory.newReplaceParametersIF(_text,_replaceText,_filters,_directory)       
1501        self.findDialogForm.initializeAllSearchLists(self.findAndReplaceHistory)
1502       
1503        # self.findDialogForm.findComboBoxIF.clear()
1504        # self.findDialogForm.replaceComboBoxIF.clear()
1505        # self.findDialogForm.filtersComboBoxIF.clear()
1506        # self.findDialogForm.directoryComboBoxIF.clear()
1507        # # self.findDialogForm.findComboBoxIF.addItems(self.findAndReplaceHistory.findHistoryIF)
1508        # # self.findDialogForm.replaceComboBoxIF.addItems(self.findAndReplaceHistory.replaceHistoryIF)
1509        # self.findDialogForm.findComboBoxIF.addItems(self.findAndReplaceHistory.findHistory)
1510        # self.findDialogForm.replaceComboBoxIF.addItems(self.findAndReplaceHistory.replaceHistory)
1511       
1512        # self.findDialogForm.filtersComboBoxIF.addItems(self.findAndReplaceHistory.filtersHistoryIF)
1513        # self.findDialogForm.directoryComboBoxIF.addItems(self.findAndReplaceHistory.directoryHistoryIF)
1514       
1515        #constructing the list of files to be searched based on directory and filters input
1516       
1517        import fnmatch
1518        import os
1519        filters=str(_filters).split()
1520        dbgMsg(filters)
1521       
1522        matches = []
1523        if _mode==ALL_IN_FILES:
1524            for filter in filters:
1525                if self.findDialogForm.inAllSubFoldersCheckBoxIF.isChecked():
1526                    for root, dirnames, filenames in os.walk(str(_directory)):
1527                        for filename in fnmatch.filter(filenames, filter):
1528                            matches.append(os.path.join(root, filename))
1529                else:
1530                    root=str(_directory)
1531                    for filename in os.listdir(root):
1532                        if fnmatch.fnmatch(filename, filter):
1533                            matches.append(os.path.join(root, filename))
1534                       
1535       
1536           
1537        # dbgMsg("matches=",matches)
1538       
1539        replaceInFilesData=[]
1540       
1541        if _mode==ALL_IN_FILES:
1542            replaceInFilesData=self.processReplaceInFiles(matches,_text,_replaceText,reFlag)
1543        elif _mode==ALL_IN_ALL_OPEN_DOCS:
1544            replaceInFilesData=self.processReplaceInAllOpenDocs(_text,_replaceText,reFlag)
1545        else:
1546            return
1547       
1548        try:
1549            message="Replaced %s occurences of \"<b>%s</b>\" in %s files"%(str(replaceInFilesData[0]),_text,str(replaceInFilesData[1]))
1550            ret = QtGui.QMessageBox.information(self, "Replace in Files",
1551                    message,
1552                    QtGui.QMessageBox.Ok )
1553 
1554        except IndexError:
1555            pass
1556        # dbgMsg("REPLACED ", replaceInFilesData[0] ," occurences of ",_text," in ",replaceInFilesData[1]," FILES")
1557        # for findInFileResult in foundFiles:
1558            # dbgMsg(findInFileResult.lineOccurences)
1559        # if len(foundFiles):
1560            # dbgMsg(foundFiles[0].produceSummaryRepr(foundFiles)    )
1561        # findInFilesFormatter=FindInFilesResults()  # use  empty FindInFilesResults object as a formatter         
1562        # self.findDisplayWidget.addNewFindInFilesResults(findInFilesFormatter.produceSummaryRepr(foundFiles,_text))
1563        # if not self.showFindInFilesDockAct.isChecked():
1564            # self.showFindInFilesDockAct.trigger() # calling toggle does not emit triggered signal and thus action slot is not     
1565
1566    def processReplaceInAllOpenDocs(self,_text,_replaceText,_reFlag):
1567        # progress dialog not necessary here
1568        replaceInFilesData = []
1569       
1570        fileCounter=0
1571        substitutionCounter=0       
1572
1573 
1574        editorList=self.getEditorList()
1575       
1576        for editor in editorList:
1577            currentLine,currentIndex = editor.getCursorPosition() # record current cursor position
1578            filename=self.getEditorFileName(editor)
1579            if filename=='':
1580                continue # we do not allow searching or replacing in the unsaved files
1581           
1582            foundFlag=editor.findFirst(_text,_reFlag,\
1583            self.findDialogForm.caseCheckBox.isChecked(),\
1584            self.findDialogForm.wholeCheckBox.isChecked(),\
1585            False,\
1586            True,0,0,False)           
1587           
1588            newFileCountedFlag=False
1589         
1590            editor.beginUndoAction()
1591                # editor.modificationChanged.disconnect(self.textChangedHandlers[editor].handleModificationChanged)
1592               
1593            while foundFlag:
1594                line,index=editor.getCursorPosition()
1595                # dbgMsg("FOUND OCCURENCE IN LINE ",line, " replacing it with ", _replaceText)
1596                # findResults.addLineWithText(line,editor.text(line))
1597                editor.replace(_replaceText)
1598               
1599                if not newFileCountedFlag:
1600                    fileCounter+=1
1601                    newFileCountedFlag=True
1602                substitutionCounter+=1
1603                foundFlag=editor.findFirst(_text,_reFlag,\
1604                self.findDialogForm.caseCheckBox.isChecked(),\
1605                self.findDialogForm.wholeCheckBox.isChecked(),\
1606                False)
1607
1608            editor.endUndoAction()   
1609            editor.setCursorPosition(currentLine,currentIndex)   # restore cursor position
1610           
1611        replaceInFilesData=[substitutionCounter,fileCounter]   
1612        return replaceInFilesData
1613        # no progress dialog is necessary
1614       
1615    def processReplaceInFiles(self, _files, _text,_replaceText,_reFlag=False):
1616        # have to deal with files which are currently open - enable undo action and use open editor for them
1617        #dbgMsg(warning before execution replace in files)
1618        progressDialog = QtGui.QProgressDialog(self)
1619
1620        progressDialog.setCancelButtonText("&Cancel")
1621        numberOfFiles=len(_files)
1622        progressDialog.setRange(0, numberOfFiles)
1623        progressDialog.setWindowTitle("Replacing Text in Files")
1624
1625        replaceInFilesData = []
1626        i=1
1627        # this is used to construct dict of open files
1628        openFileDict=self.getFileNameToEditorWidgetMap()
1629        # openFileDict={}
1630        # for key in self.fileDict.keys():
1631            # if self.fileDict[key][0]!='':
1632                # openFileDict[self.fileDict[key][0]]=key
1633                # getFileNameToEditorWidgetMap
1634       
1635        fileCounter=0
1636        substitutionCounter=0       
1637       
1638        for filename in _files:
1639            # dbgMsg("SEARCHING ", filename)
1640            progressDialog.setValue(i)
1641            progressDialog.setLabelText("Searching file number %d of %d..." % (i, numberOfFiles))
1642            QtGui.qApp.processEvents()
1643
1644            if progressDialog.wasCanceled():
1645                break
1646               
1647            textEditLocal=None   
1648           
1649            usingOpenEditor=False
1650            openFileForReplaceFlag=False
1651           
1652            fileNameNormalized=os.path.abspath(filename)
1653           
1654            if fileNameNormalized in  openFileDict.keys():
1655                # textEditLocal=self.editTab.currentWidget()
1656                textEditLocal=openFileDict[fileNameNormalized]
1657                textEditLocal.setCursorPosition(0,0) # have to move cursor to the begining of the document
1658                # dbgMsg("textEditLocal=",textEditLocal)
1659                # self.replaceAll(self,_text,_replaceText,_inSelectionFlag)
1660                # continue
1661                usingOpenEditor=True
1662            else:
1663               
1664           
1665                inFile = QtCore.QFile(filename)
1666                if not inFile.open(QtCore.QIODevice.ReadWrite): # this will take care of write protected files - we will not process them   
1667                    continue
1668                stream = QtCore.QTextStream(inFile)
1669                textEditLocal=QsciScintillaCustom()               
1670                textEditLocal.setText(stream.readAll())
1671
1672            # dbgMsg("usingOpenEditor=",usingOpenEditor)
1673            # dbgMsg("openFileDict=",openFileDict)
1674            # dbgMsg("filename=",filename)
1675           
1676           
1677            # if inFile.open(QtCore.QIODevice.ReadWrite): # this will take care of write protected files - we will not process them
1678            # stream = QtCore.QTextStream(inFile)
1679           
1680            # if not textEditLocal:
1681                # textEditLocal=QsciScintillaCustom()               
1682                # textEditLocal.setText(stream.readAll())
1683           
1684            foundFlag=textEditLocal.findFirst(_text,_reFlag,\
1685            self.findDialogForm.caseCheckBoxIF.isChecked(),\
1686            self.findDialogForm.wholeCheckBoxIF.isChecked(),\
1687            False,\
1688            True,0,0,False)     
1689            findResults=None
1690            # if foundFlag:
1691                # foundFiles.append(FindInFilesResults(filename,_text))
1692                # findResults=foundFiles[-1]
1693               
1694            newFileCountedFlag=False
1695            if usingOpenEditor:
1696                textEditLocal.beginUndoAction()
1697                # textEditLocal.modificationChanged.disconnect(self.textChangedHandlers[textEditLocal].handleModificationChanged)
1698               
1699            while foundFlag:
1700                line,index=textEditLocal.getCursorPosition()
1701                # dbgMsg("FOUND OCCURENCE IN LINE ",line, " replacing it with ", _replaceText)
1702                # findResults.addLineWithText(line,textEditLocal.text(line))
1703                textEditLocal.replace(_replaceText)
1704               
1705                if not newFileCountedFlag:
1706                    fileCounter+=1
1707                    newFileCountedFlag=True
1708                substitutionCounter+=1
1709                foundFlag=textEditLocal.findFirst(_text,_reFlag,\
1710                self.findDialogForm.caseCheckBoxIF.isChecked(),\
1711                self.findDialogForm.wholeCheckBoxIF.isChecked(),\
1712                False)
1713                # ,\
1714                # True,0,0,False)                 
1715               
1716                # foundFlag=textEditLocal.findNext()
1717               
1718            if usingOpenEditor:
1719                textEditLocal.endUndoAction()
1720
1721                if newFileCountedFlag:
1722                    self.saveFile(filename,textEditLocal) # using saveFile function for open editor
1723                    # heve to deactivate modification time sensing
1724                    textEditLocal.modificationChanged.disconnect(self.textChangedHandlers[textEditLocal].handleModificationChanged)
1725                   
1726                    self.setEditorFileModificationTime(textEditLocal,os.path.getmtime(filename))
1727                   
1728                    # heve to reactivate modification time sensing
1729                    textEditLocal.modificationChanged.connect(self.textChangedHandlers[textEditLocal].handleModificationChanged)
1730                    # self.reloadFile(textEditLocal,self.fileDict[textEditLocal][0])
1731                # textEditLocal.modificationChanged.connect(self.textChangedHandlers[textEditLocal].handleModificationChanged)     
1732            else:   
1733               
1734                inFile.close() # before writing we close the file - alternatively we may move file pointer to the begining
1735               
1736                if newFileCountedFlag and inFile.open(QtCore.QIODevice.WriteOnly):   
1737                    outf = QtCore.QTextStream(inFile)
1738                    outf << textEditLocal.text()
1739
1740            i+=1
1741           
1742        progressDialog.close()
1743       
1744        replaceInFilesData=[substitutionCounter,fileCounter]
1745        return replaceInFilesData
1746                     
1747    def findNext(self,_text):
1748        # dbgMsg("findNext = ",_text)
1749        editor=self.editTab.currentWidget()
1750       
1751        reFlag=False
1752       
1753        if str(self.findDialogForm.syntaxComboBox.currentText())=="Regular expression":
1754            reFlag=True
1755           
1756        dbgMsg("RE FLAG:=",reFlag)
1757       
1758
1759       
1760        newSearchFlag=self.findAndReplaceHistory.newSearchParameters(_text,reFlag,self.findDialogForm.caseCheckBox.isChecked(),self.findDialogForm.wholeCheckBox.isChecked(),True,self.findDialogForm.inSelectionBox.isChecked())
1761        dbgMsg("self.findDialogForm.wholeCheckBox.isChecked()=",self.findDialogForm.wholeCheckBox.isChecked())
1762        self.findDialogForm.initializeSearchLists(self.findAndReplaceHistory)
1763        # self.findDialogForm.findComboBox.clear()
1764        # self.findDialogForm.replaceComboBox.clear()
1765        # self.findDialogForm.findComboBox.addItems(self.findAndReplaceHistory.findHistory)
1766        # self.findDialogForm.replaceComboBox.addItems(self.findAndReplaceHistory.replaceHistory) 
1767       
1768        dbgMsg("self.findAndReplaceHistory.re:=",self.findAndReplaceHistory.re)   
1769       
1770        if newSearchFlag:
1771            foundFlag=editor.findFirst(self.findAndReplaceHistory.textToFind,self.findAndReplaceHistory.re,self.findAndReplaceHistory.cs,self.findAndReplaceHistory.wo,self.findAndReplaceHistory.wrap)
1772            dbgMsg("foundFlag=",foundFlag)
1773           
1774        else:
1775           
1776            editor.findNext()   
1777        # if _text!=self.textToFind:
1778            # self.textToFind=_text
1779            # editor.findFirst(self.textToFind,False,True,False,True)
1780        # else:
1781            # editor.findNext()
1782           
1783    def findNextSimple(self):
1784        editor=self.editTab.currentWidget()
1785        editor.findNext()
1786       
1787    def replaceNext(self,_text,_replaceText):
1788        # dbgMsg("Find text=",_text," replaceText=",_replaceText   )
1789        editor=self.editTab.currentWidget()
1790       
1791       
1792       
1793        reFlag=False
1794        inSelectionFlag=self.findDialogForm.inSelectionBox.isChecked()
1795       
1796        if str(self.findDialogForm.syntaxComboBox.currentText())=="Regular expression":
1797            reFlag=True
1798       
1799
1800       
1801        newReplaceFlag=self.findAndReplaceHistory.newReplaceParameters(_text,_replaceText,reFlag,self.findDialogForm.caseCheckBox.isChecked(),self.findDialogForm.wholeCheckBox.isChecked(),True,inSelectionFlag)
1802
1803        self.findDialogForm.initializeSearchLists(self.findAndReplaceHistory)
1804        # self.findDialogForm.findComboBox.clear()
1805        # self.findDialogForm.replaceComboBox.clear()
1806        # self.findDialogForm.findComboBox.addItems(self.findAndReplaceHistory.findHistory)
1807        # self.findDialogForm.replaceComboBox.addItems(self.findAndReplaceHistory.replaceHistory)   
1808        if newReplaceFlag:
1809            editor.findFirst(self.findAndReplaceHistory.textToFind,self.findAndReplaceHistory.re,self.findAndReplaceHistory.cs,self.findAndReplaceHistory.wo,False)
1810            # self.findAndReplaceHistory.wrap
1811            # editor.SendScintilla(QsciScintilla.SCI_REPLACESEL,0, self.findAndReplaceHistory.replaceText)
1812            editor.replace(self.findAndReplaceHistory.replaceText)
1813            # dbgMsg("FOUND TEXT ",self.findAndReplaceHistory.textToFind, " position ", editor.getCursorPosition())
1814            # dbgMsg("REPLACING FIRST\n\n\n")
1815        else:
1816            #for some reason there are problem using findNext together with replace - since editor is expanding consecutive calls
1817            # to replace (especially when replacin short string with long string) result in replace abbandoning changes because it may think there is not eanough space. findFirst works fine though
1818            # editor.findNext()   
1819            # self.findNext(self.findAndReplaceHistory.textToFind)
1820            editor.findFirst(self.findAndReplaceHistory.textToFind,self.findAndReplaceHistory.re,self.findAndReplaceHistory.cs,self.findAndReplaceHistory.wo,False)
1821            # editor.SendScintilla(QsciScintilla.SCI_REPLACESEL,0, self.findAndReplaceHistory.replaceText)
1822           
1823           
1824            editor.replace(self.findAndReplaceHistory.replaceText)
1825            # dbgMsg("FOUND TEXT ",self.findAndReplaceHistory.textToFind, " position ", editor.getCursorPosition())
1826            # dbgMsg("REPLACING NEXT\n\n\n")
1827           
1828    def replaceAll(self,_text,_replaceText,_inSelectionFlag):
1829        # dbgMsg("Find text=",_text," replaceText=",_replaceText   )
1830        editor=self.editTab.currentWidget()
1831       
1832        reFlag=False
1833        inSelectionFlag=_inSelectionFlag
1834       
1835        if str(self.findDialogForm.syntaxComboBox.currentText())=="Regular expression":
1836            reFlag=True
1837       
1838        newReplaceFlag=self.findAndReplaceHistory.newReplaceParameters(_text,_replaceText,reFlag,self.findDialogForm.caseCheckBox.isChecked(),self.findDialogForm.wholeCheckBox.isChecked(),True,inSelectionFlag)
1839       
1840        self.findDialogForm.initializeSearchLists(self.findAndReplaceHistory)
1841       
1842        substitutionCounter=0
1843       
1844        if inSelectionFlag and editor.hasSelectedText():
1845        # if editor.hasSelectedText():
1846            line_before, index_before = editor.getCursorPosition()
1847            line_from, index_from, line_to, index_to = editor.getSelection()
1848            # line=line_from
1849            # index=index_from
1850            # dbgMsg("line_from, index_from, line_to, index_to=",line_from, index_from, line_to, index_to)
1851            foundFlag=editor.findFirst(self.findAndReplaceHistory.textToFind,\
1852            self.findAndReplaceHistory.re,\
1853            self.findAndReplaceHistory.cs,\
1854            self.findAndReplaceHistory.wo,\
1855            False,\
1856            True,line_from,index_from,False)     
1857           
1858            line, index = editor.getCursorPosition()
1859           
1860            editor.beginUndoAction() # undo
1861            while foundFlag and (line<line_to or (line==line_to and index<=index_to)) :                 
1862                # dbgMsg("line, index=",line, index)
1863                editor.replace(self.findAndReplaceHistory.replaceText)
1864                substitutionCounter+=1
1865                # dbgMsg("REPLACING TEXT WITH ",self.findAndReplaceHistory.replaceText)
1866                foundFlag=editor.findFirst(self.findAndReplaceHistory.textToFind,\
1867                self.findAndReplaceHistory.re,\
1868                self.findAndReplaceHistory.cs,\
1869                self.findAndReplaceHistory.wo,\
1870                False)                 
1871                # editor.findNext()   
1872                line, index = editor.getCursorPosition()
1873            editor.endUndoAction() # undo
1874           
1875            editor.setCursorPosition(line_before, index_before)   
1876        elif not inSelectionFlag:
1877       
1878            line_from=0
1879            index_from=0
1880            line_before, index_before = editor.getCursorPosition()
1881            foundFlag=editor.findFirst(self.findAndReplaceHistory.textToFind,\
1882            self.findAndReplaceHistory.re,\
1883            self.findAndReplaceHistory.cs,\
1884            self.findAndReplaceHistory.wo,\
1885            False,\
1886            True,line_from,index_from,False)     
1887            editor.beginUndoAction() # undo                   
1888           
1889            # previousLine,previousPos=editor.getCursorPosition()
1890            while foundFlag:
1891                # dbgMsg("FOUND TEXT ",self.findAndReplaceHistory.textToFind, " position ", editor.getCursorPosition())
1892                editor.replace(self.findAndReplaceHistory.replaceText)
1893                substitutionCounter+=1
1894                foundFlag=editor.findFirst(self.findAndReplaceHistory.textToFind,\
1895                self.findAndReplaceHistory.re,\
1896                self.findAndReplaceHistory.cs,\
1897                self.findAndReplaceHistory.wo,\
1898                False)
1899                # ,\
1900                # True,line_from,index_from,False)
1901               
1902                # currentLine,currentPos=editor.getCursorPosition()
1903               
1904                # if currentLine==previousLine and currentPos==previousPos:
1905                    # foundFlag=False
1906               
1907                # foundFlag=editor.findNext()
1908            editor.endUndoAction() # undo   
1909           
1910            editor.setCursorPosition(line_before, index_before)   
1911
1912       
1913        message="Replaced %s occurences of \"<b>%s</b>\""%(str(substitutionCounter),_text)
1914        ret = QtGui.QMessageBox.information(self, "Replace in Files",
1915                message,
1916                QtGui.QMessageBox.Ok )
1917           
1918        # dbgMsg("replaceAll")
1919       
1920    def marginClickedHandler(self,_margin,_line,_keyboardState):
1921        editor=self.editTab.currentWidget()     
1922        if _margin==1:
1923            if editor.markersAtLine(_line)!=self.bookmarkMask: # check if there is marker in this liine
1924                marker=editor.markerAdd(_line,self.lineBookmark)                 
1925            else: #otherwise remove bookmark
1926                editor.markerDelete(_line)     
1927       
1928   
1929    def toggleBookmark(self):
1930        # dbgMsg("Toggle bookmarks, marker=",self.lineBookmark        )
1931        editor=self.editTab.currentWidget()
1932        line, index = editor.getCursorPosition()       
1933        # dbgMsg("line=",line," index=",index)
1934        # dbgMsg("editor.markersAtLine(line)=",editor.markersAtLine(line))
1935        # dbgMsg("self.bookmarkMask=",self.bookmarkMask)
1936        if editor.markersAtLine(line)!=self.bookmarkMask: # check if there is marker in this liine
1937            # dbgMsg("ADDING BOOKMARK")
1938            # if not add bookmark
1939            marker=editor.markerAdd(line,self.lineBookmark) 
1940           
1941            # dbgMsg("AFTER ADDING editor.markersAtLine(line)=",editor.markersAtLine(line))
1942            # if editor.markersAtLine(line)>1:
1943                # editor.markerDelete(line)
1944                # dbgMsg("DELETING EXTRA MARKER ",editor.markersAtLine(line))
1945        else: #otherwise remove bookmark
1946            # dbgMsg("REMOVING BOOKMARK")
1947            editor.markerDelete(line)   
1948       
1949       
1950
1951    def goToNextBookmark(self):
1952        # dbgMsg(" Next Bookmark" )
1953        editor=self.editTab.currentWidget()
1954        line, index = editor.getCursorPosition()
1955        # dbgMsg("current line=",line)
1956        lineNext=editor.markerFindNext(line,self.bookmarkMask)
1957        # dbgMsg("lineNext=",lineNext," line=",line)
1958       
1959        if lineNext==line:
1960            lineNext=editor.markerFindNext(line+1,self.bookmarkMask)
1961           
1962        if  lineNext==-1:
1963            lineNext=editor.markerFindNext(0,self.bookmarkMask)
1964            if lineNext==-1:
1965                return
1966
1967        if lineNext!=line and lineNext!=-1:
1968            editor.setCursorPosition(lineNext,0)
1969            return
1970
1971               
1972    def goToPreviousBookmark(self):
1973        # dbgMsg(" Previous Bookmark" )
1974        editor=self.editTab.currentWidget()
1975        line, index = editor.getCursorPosition()
1976       
1977        linePrevious=editor.markerFindPrevious(line,self.bookmarkMask)
1978        # dbgMsg("linePrevious=",linePrevious," line=",line)
1979       
1980        if linePrevious==line:
1981            linePrevious=editor.markerFindPrevious(line-1,self.bookmarkMask)
1982           
1983        if  linePrevious==-1:
1984            linePrevious=editor.markerFindPrevious(editor.lines(),self.bookmarkMask)
1985            if linePrevious==-1:
1986                return
1987       
1988        if linePrevious!=line and linePrevious!=-1:
1989            editor.setCursorPosition(linePrevious,0)
1990            return       
1991       
1992    def deleteAllBookmarks(self):
1993        editor=self.editTab.currentWidget()
1994        editor.markerDeleteAll(self.lineBookmark)
1995
1996    def goToLineShow(self,_line):
1997        editor=self.editTab.currentWidget()
1998        self.goToLineDlg=GoToLineDlg(editor,self)
1999        self.goToLineDlg.show()
2000
2001    def goToLine(self,_line):
2002        dbgMsg("GO TO LINE SLOT = ",_line)
2003        editor=self.editTab.currentWidget()
2004        editor.setCursorPosition(_line-1,0)
2005       
2006
2007       
2008    def goToMatchingBrace(self):       
2009        editor=self.editTab.currentWidget()
2010        editor.moveToMatchingBrace()
2011       
2012    def selectToMatchingBrace(self):
2013        # dbgMsg("select to matching brace")
2014        editor=self.editTab.currentWidget()
2015        editor.selectToMatchingBrace()
2016       
2017    def configurationUpdate(self):
2018        # dbgMsg("configuration update")
2019        editor=self.editTab.currentWidget()
2020        configurationDlg= ConfigurationDlg(editor,self)
2021        if configurationDlg.exec_():
2022            for key in self.configuration.updatedConfigs.keys():
2023                dbgMsg("NEW SETTING = ",key,":",self.configuration.updatedConfigs[key])
2024                configureFcn=getattr(self,"configure"+key)
2025                configureFcn(self.configuration.updatedConfigs[key])
2026            # dbgMsg("CLICKED OK BUTTING ON CONFIGURATION PAGE")
2027                # self.editTab.currentWidget().setBraceMatching(lexer[3])
2028                # self.editTab.currentWidget().setFolding(lexer[4])
2029                # self.editTab.currentWidget().setWhitespaceVisibility(lexer[5])
2030                # self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
2031                # self.editTab.currentWidget().setIndentationGuides(True) 
2032               
2033    def configureUseTabSpaces(self,_flag):
2034        numberOfDocuments=self.editTab.count()
2035        for i in  range(numberOfDocuments):
2036            self.editTab.widget(i).setIndentationsUseTabs( not _flag)
2037            if _flag:
2038                self.editTab.widget(i).setIndentationWidth(self.configuration.setting("TabSpaces"))
2039            else:
2040                self.editTab.widget(i).setIndentationWidth(0) # If width is 0 then the value returned by tabWidth() is used
2041           
2042               
2043               
2044    def configureFoldText(self,_flag):
2045        numberOfDocuments=self.editTab.count()
2046        for i in  range(numberOfDocuments):
2047            if _flag:
2048                self.editTab.widget(i).setFolding(QsciScintilla.BoxedTreeFoldStyle) # 5 corresponds to BoxedTreeFoldStyle
2049            else:
2050                self.editTab.widget(i).setFolding(QsciScintilla.NoFoldStyle) # no folding
2051   
2052    def configureDisplayWhitespace(self,_flag):
2053        numberOfDocuments=self.editTab.count()
2054        for i in  range(numberOfDocuments):
2055            if _flag:
2056                self.editTab.widget(i).setWhitespaceVisibility(QsciScintilla.SCWS_VISIBLEALWAYS) #
2057            else:
2058                self.editTab.widget(i).setWhitespaceVisibility(QsciScintilla.SCWS_INVISIBLE) # no whitespaces
2059               
2060    def configureDisplayEOL(self,_flag):
2061        numberOfDocuments=self.editTab.count()
2062        for i in  range(numberOfDocuments):
2063            self.editTab.widget(i).setEolVisibility(_flag)
2064
2065    def configureWrapLines(self,_flag):
2066        numberOfDocuments=self.editTab.count()
2067        for i in  range(numberOfDocuments):
2068            if _flag:           
2069                self.editTab.widget(i).setWrapMode(QsciScintilla.WrapWord)
2070            else:
2071                self.editTab.widget(i).setWrapMode(QsciScintilla.WrapNone)
2072
2073    def configureShowWrapSymbol(self,_flag):
2074        numberOfDocuments=self.editTab.count()       
2075        for i in  range(numberOfDocuments):
2076            if _flag:           
2077                self.editTab.widget(i).setWrapVisualFlags(QsciScintilla.WrapFlagByText)
2078            else:
2079                self.editTab.widget(i).setWrapVisualFlags(QsciScintilla.WrapFlagNone)
2080       
2081           
2082               
2083    def configureTabGuidelines(self,_flag):
2084        numberOfDocuments=self.editTab.count()
2085        for i in  range(numberOfDocuments):
2086            self.editTab.widget(i).setIndentationGuides(_flag)
2087           
2088    def configureDisplayLineNumbers(self,_flag):
2089        numberOfDocuments=self.editTab.count()
2090        for i in  range(numberOfDocuments):
2091            self.editTab.widget(i).setMarginLineNumbers(1,_flag)
2092
2093           
2094    def newFile(self):
2095       
2096        textEditLocal = QsciScintillaCustom()
2097        textEditLocal.clear()
2098        self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),"New Document "+str(self.editTab.count()+1))
2099        self.editTab.setCurrentWidget(textEditLocal)       
2100        # self.editTab.addTab()           
2101        self.setCurrentFile('')
2102        self.setEditorProperties(textEditLocal)
2103        self.commentStyleDict[self.editTab.currentWidget()]=['','']
2104        # self.fileDict[self.editTab.currentWidget()]=['',0,self.editTab.tabText(self.editTab.indexOf(self.editTab.currentWidget()))]
2105        self.setPropertiesInEditorList(self.editTab.currentWidget(),'',0,'utf-8')
2106        # self.fileDict[self.editTab.currentWidget()]=['',0,'utf-8']
2107
2108        # adding text Changed Handler
2109        self.textChangedHandlers[textEditLocal]=ChangedTextHandler(textEditLocal,self)
2110        editorIndex=self.editTab.indexOf(textEditLocal)
2111
2112        # self.editTab.widget(editorIndex).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)   
2113        self.editTab.widget(editorIndex).modificationChanged.connect(self.textChangedHandlers[textEditLocal].handleModificationChanged)
2114        self.editTab.widget(editorIndex).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)
2115        self.editTab.widget(editorIndex).cursorPositionChanged.connect(self.handleCursorPositionChanged)
2116
2117        # self.textChangedHandlers[textEditLocal]=ChangedTextHandler(textEditLocal,self)
2118        # self.editTab.widget(0).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)         
2119
2120    def open(self):
2121        # if self.maybeSave():
2122        #get path to file in the current widget
2123        dbgMsg("INSIDE OPEN")
2124        currentFilePath=None
2125        try:
2126            # currentFilePath=self.fileDict[self.editTab.currentWidget()][0] 
2127            currentFilePath=self.getEditorFileName(self.editTab.currentWidget())             
2128        except KeyError:
2129           
2130            pass
2131           
2132        if currentFilePath:
2133            currentFilePath=os.path.dirname(str(currentFilePath))
2134            self.lastFileOpenPath=currentFilePath
2135        else:
2136            currentFilePath=self.lastFileOpenPath
2137           
2138        dbgMsg("THIS IS CURRENT PATH=",currentFilePath)
2139        fileNames = QtGui.QFileDialog.getOpenFileNames(self,"Open new file...",currentFilePath,self.fileDialogFilters)
2140        if fileNames.count():
2141            self.loadFiles(fileNames)               
2142               
2143    def closeTabIndex(self, index):
2144        self.closeTab(index)
2145       
2146    def closeTab(self, index=None):
2147        dbgMsg("closing tab ",index)
2148        textEditLocal=None
2149        if index is not None and not isinstance(index, bool) : # ctrl+w calls closeTab with False bool type argument and we need to make sure that it is not converted to int index
2150            textEditLocal=self.editTab.widget(index)
2151        else:
2152            textEditLocal= self.editTab.currentWidget()   
2153        # textEditLocal=self.editTab.widget(index) if index is not None else self.editTab.widget(self.editTab.currentIndex())
2154        # dbgMsg("self.editTab.indexOf(textEditLocal)=",self.editTab.indexOf(textEditLocal))
2155        # dbgMsg("current index =", self.editTab.currentIndex())
2156       
2157        self.maybeSave()
2158       
2159        if self.editTab.count()==1:
2160            self.editTab.currentWidget().clear()
2161            self.editTab.currentWidget().setModified(False) # clearing document modifies its content but since no new text has been typed we set modified to false             
2162            self.editTab.setTabText(0,'Empty Document')
2163            self.setCurrentFile('')
2164            self.commentStyleDict[self.editTab.currentWidget()]=['','']
2165            if self.editTab.currentWidget() in self.getEditorList():
2166                # del self.fileDict[self.editTab.currentWidget()]
2167                self.removeEditor(self.editTab.currentWidget())
2168
2169            self.editTab.setTabIcon(0,QtGui.QIcon(':/icons/document-clean.png') )
2170        else:
2171            self.editTab.removeTab( self.editTab.indexOf(textEditLocal))
2172            del self.commentStyleDict[textEditLocal]
2173            self.removeEditor(textEditLocal)
2174            # del self.fileDict[textEditLocal]
2175           
2176            if self.editTab.currentWidget() in self.textChangedHandlers:   
2177                del self.textChangedHandlers[textEditLocal]
2178           
2179    def foldAll(self):
2180        editor= self.editTab.currentWidget()
2181        editor.foldAll(True)
2182        # editor.foldAll()
2183       
2184    def zoomIn(self):
2185        # editor=self.editTab.currentWidget()
2186        self.zoomRange+=1
2187        self.configuration.setSetting("ZoomRange",self.zoomRange)
2188        for editor in self.getEditorList():           
2189            editor.zoomIn()
2190            # lexer=editor.lexer()
2191            # if lexer:
2192               
2193                # dbgMsg("editor.lexer()=",editor.lexer())
2194                # dbgMsg("lexer().font().pointSize()=",editor.lexer().defaultFont(0).pointSize())
2195       
2196    def zoomOut(self):
2197        self.zoomRange-=1
2198        self.configuration.setSetting("ZoomRange",self.zoomRange)
2199        for editor in self.getEditorList():           
2200            editor.zoomOut()   
2201   
2202    # def __lines_changed(self):
2203        # """Update margin"""
2204        # self.update_line_numbers_margin()
2205       
2206    # def update_line_numbers_margin(self):
2207        # """Update margin width"""
2208        # width = log(self.lines(), 10) + 2
2209        # self.setMarginWidth(1, QString('0'*int(width)))
2210       
2211    def save(self):
2212       
2213        editor=self.editTab.currentWidget()
2214        fileName=''
2215        if editor in self.getEditorList():
2216            fileName=self.getEditorFileName(editor)
2217           
2218        if fileName:
2219            return self.saveFile(fileName)
2220
2221        return self.saveAs()
2222
2223    def saveAs(self,suggestedName=None):
2224        # self.deactivateChangeSensing=True
2225        currentFilePath=None
2226        currentExtension=""
2227        try:
2228            # currentFilePath=self.fileDict[self.editTab.currentWidget()][0]
2229            currentFilePath=self.getEditorFileName(self.editTab.currentWidget())             
2230        except KeyError:
2231            pass
2232           
2233        if currentFilePath:
2234            fileSplit=os.path.splitext(str(currentFilePath))
2235            currentExtension=fileSplit[1]                   
2236            # currentFilePath=os.path.dirname(str(currentFilePath))
2237           
2238            self.lastFileOpenPath=currentFilePath
2239        else:
2240            currentFilePath=self.lastFileOpenPath
2241           
2242        dbgMsg("suggestedName=",suggestedName)
2243        fileName=""
2244        if suggestedName is None or  isinstance(suggestedName, bool) : # saveAs is called by default with False bool type argument and we need to make sure that it is not converted to int index
2245            # if self.saveAsFileDialog:
2246                # pass
2247                # # fileName = QtGui.QFileDialog.getSaveFileName(self,"Save File",currentFilePath)
2248            # else:
2249                # self.saveAsFileDialog=QtGui.QFileDialog(self)
2250               
2251            # self.saveAsFileDialog.setDirectory(currentFilePath)   
2252           
2253            # if self.saveAsFileDialog.exec_():
2254            currentFilterString=self.getCurrentFilterString(currentExtension)
2255            dbgMsg("currentFilterString=",currentFilterString)
2256            # currentFilterString="Text file (*.txt)"
2257           
2258            fileName=QtGui.QFileDialog.getSaveFileName(self,"Save File",currentFilePath,currentFilterString+"\n"+self.fileDialogFilters)
2259            dbgMsg("SAVE FILE NAME is:",fileName)
2260            if fileName=="":
2261                return False
2262           
2263               
2264        else:         
2265            dbgMsg("")
2266            fileName = QtGui.QFileDialog.getSaveFileName(self,"Save File",suggestedName)
2267            if fileName=="":
2268                return False           
2269           
2270        fileName=os.path.abspath(fileName) # "normalizing" file name to make sure \ and / are used in a consistent manner
2271           
2272        if fileName:
2273            returnCode = self.saveFile(fileName)       
2274            if returnCode:
2275                lexer=self.guessLexer(fileName)
2276                if lexer[0]:
2277                    self.editTab.currentWidget().setLexer(lexer[0])             
2278                    self.editTab.currentWidget().setBraceMatching(lexer[3])
2279                    if self.configuration.setting("FoldText"):
2280                        self.editTab.currentWidget().setFolding(QsciScintilla.BoxedTreeFoldStyle)
2281                    else:
2282                        self.editTab.currentWidget().setFolding(QsciScintilla.NoFoldStyle)               
2283                    self.editTab.currentWidget().setWhitespaceVisibility(self.configuration.setting("DisplayWhitespace"))
2284                    self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
2285                    self.editTab.currentWidget().setIndentationGuides(self.configuration.setting("TabGuidelines"))     
2286                    # self.editTab.currentWidget().setTabIndents(False)
2287                else:# lexer could not be guessed - use default lexer
2288                    self.editTab.currentWidget().setLexer(None)
2289                   
2290                tabIndex=self.editTab.indexOf(self.editTab.currentWidget())
2291                self.editTab.setTabText(tabIndex,self.strippedName(fileName))
2292                self.commentStyleDict[self.editTab.currentWidget()]=[lexer[1],lexer[2]] # associating comment style with the lexer
2293                # self.fileDict[self.editTab.currentWidget()]=[fileName,os.path.getmtime(fileName)] # saving new name and new modification time
2294                currentEncoding=self.getEditorFileEncoding(self.editTab.currentWidget())
2295                self.setPropertiesInEditorList(self.editTab.currentWidget(),fileName,os.path.getmtime(fileName),currentEncoding)
2296                # dbgMsg("CURRENT ENCODING=",currentEncoding)
2297                # self.deactivateChangeSensing=False
2298            return returnCode
2299
2300        # self.deactivateChangeSensing=False   
2301        return False
2302
2303    def saveAll(self):
2304       
2305        unnamedFiles={}   
2306       
2307        for editor in self.getEditorList():           
2308            if not self.getEditorFileName(editor)=='':
2309                index=self.editTab.indexOf(editor)
2310                self.editTab.setCurrentIndex(index)
2311                if self.editTab.currentWidget().isModified():
2312                    self.save()
2313                else:
2314                    self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))
2315            else:
2316                index=self.editTab.indexOf(editor)
2317                unnamedFiles[editor]=self.editTab.tabText(index)   
2318                # openFilesToRestore[self.editTab.indexOf(editor)]=self.fileDict[editor][0] # saving file name and position of the tab
2319
2320        # dealing with unnamed files:
2321        for editor in unnamedFiles.keys():
2322            if editor==self.defaultEditor: #we will not attempt to save content of the default editor. This editor should be removed anyway the moment we open any new file
2323                continue
2324            index=self.editTab.indexOf(editor)
2325            self.editTab.setCurrentIndex(index)
2326            self.saveAs(unnamedFiles[editor])
2327           
2328       
2329        # dbgMsg("openFilesToRestore=",openFilesToRestore     )
2330
2331       
2332    def about(self):
2333        QtGui.QMessageBox.about(self, "About Twedit",
2334                "The <b>Twedit</b>  editor is a free Open-Source programmers editor\n"
2335                "Originally it was meant to be editor for Twitter and we limitted number of characters to 144\n"
2336                "However, after feedback from our users we were surprised to learn that people need more 144 characters to\n"
2337                "write software. We have since removed the limitation on number of characters... \n"
2338                "As a courtesy to our users no code written in this editor is catalogued by Google or any other data-mining company.\n"
2339                "\n"
2340                "Copyright Maciej Swat <b>Swat International Productions, LLC</b>"
2341                )
2342
2343    def documentWasModified(self):
2344        self.setWindowModified(self.textEdit.document().isModified())
2345
2346    def createActions(self):
2347        self.newAct = QtGui.QAction(QtGui.QIcon(':/icons/document-new.png'), "&New",
2348                self, shortcut=QtGui.QKeySequence.New,
2349                statusTip="Create a new file", triggered=self.newFile)
2350
2351        self.openAct = QtGui.QAction(QtGui.QIcon(':/icons/document-open.png'),
2352                "&Open...", self, shortcut=QtGui.QKeySequence.Open,
2353                statusTip="Open an existing file", triggered=self.open)
2354
2355        self.saveAct = QtGui.QAction(QtGui.QIcon(':/icons/document-save.png'),
2356                "&Save", self, shortcut=QtGui.QKeySequence.Save,
2357                statusTip="Save the document to disk", triggered=self.save)
2358
2359        self.saveAsAct = QtGui.QAction(QtGui.QIcon(':/icons/document-save-as.png'),"Save &As...", self,
2360                shortcut=QtGui.QKeySequence.SaveAs,
2361                statusTip="Save the document under a new name",
2362                triggered=self.saveAs)
2363               
2364
2365        self.saveAllAct = QtGui.QAction(QtGui.QIcon(':/icons/document-save-all.png'),"Save All", self,
2366                shortcut="Ctrl+Shift+S",
2367                statusTip="Save all documents",
2368                triggered=self.saveAll)               
2369
2370                   
2371        self.printAct = QtGui.QAction(QtGui.QIcon(':/icons/document-print.png'),"print...", self,shortcut="Ctrl+P",statusTip="Print current document",triggered=self.printCurrentDocument)               
2372               
2373        self.exitAct = QtGui.QAction(QtGui.QIcon(':/icons/application-exit.png'),"E&xit", self, shortcut="Ctrl+Q",
2374                statusTip="Exit the application", triggered=self.close)
2375
2376
2377        self.closeTabAct = QtGui.QAction(QtGui.QIcon(':/icons/tab-close.png'),"CloseTab", self, shortcut="Ctrl+W",
2378                statusTip="Close Current Tab", triggered=self.closeTab)
2379
2380        self.zoomInAct = QtGui.QAction(QtGui.QIcon(':/icons/zoom-in.png'),"ZoomIn", self, shortcut="Ctrl+Shift+=",
2381                statusTip="Zoom In", triggered=self.zoomIn) 
2382               
2383        self.zoomOutAct = QtGui.QAction(QtGui.QIcon(':/icons/zoom-out.png'),"ZoomOut", self, shortcut="Ctrl+-",
2384                statusTip="Zoom Out", triggered=self.zoomOut)                 
2385
2386        self.foldAllAct = QtGui.QAction("Toggle Fold All", self, statusTip="Fold document at all folding points", triggered=self.foldAll)                 
2387         
2388        self.showFindInFilesDockAct=QtGui.QAction("Show Find in Files Results", self, statusTip="Show Find in Files Results", triggered=self.toggleFindInFilesDock)
2389        self.showFindInFilesDockAct.setCheckable(True)
2390       
2391        self.blockCommentAct = QtGui.QAction("BlockComment", self, shortcut="Ctrl+D",
2392                statusTip="Block Comment", triggered=self.blockComment)
2393               
2394        self.blockUncommentAct = QtGui.QAction("BlockUncomment", self, shortcut="Ctrl+Shift+D",
2395                statusTip="Block Uncomment", triggered=self.blockUncomment) 
2396
2397               
2398               
2399               
2400        self.findAct = QtGui.QAction(QtGui.QIcon(':/icons/edit-find.png'),"Find...", self, shortcut="Ctrl+F",
2401                statusTip="Find...", triggered=self.find) 
2402               
2403        self.findNextAct = QtGui.QAction("Find Next", self, shortcut="F3",
2404                statusTip="Find Next", triggered=self.findNextSimple) 
2405               
2406               
2407        self.toggleBookmarkAct = QtGui.QAction(QtGui.QIcon(':/icons/flag.png'),"Toogle Bookmark", self, shortcut="Ctrl+F2",
2408                statusTip="Toggle Text Bookmark", triggered=self.toggleBookmark) 
2409               
2410        self.goToNextBookmarkAct = QtGui.QAction("Go To Next Bookmark", self, shortcut="F2",
2411                statusTip="Go to Next Bookmark", triggered=self.goToNextBookmark) 
2412               
2413        self.goToPreviousBookmarkAct = QtGui.QAction("Go To Previous Bookmark", self, shortcut="Shift+F2",
2414                statusTip="Go to Previous Bookmark", triggered=self.goToPreviousBookmark) 
2415               
2416        self.deleteAllBookmarksAct = QtGui.QAction("Delete All Bookmarks", self, shortcut="",
2417                statusTip="Delete All Bookmarks", triggered=self.deleteAllBookmarks)
2418               
2419        self.goToLineAct = QtGui.QAction("Go To Line...", self, shortcut="Ctrl+G",
2420                statusTip="Go To Line", triggered=self.goToLineShow)
2421
2422        self.goToMatchingBraceAct = QtGui.QAction("Go To Matching Brace", self, shortcut="Ctrl+]",
2423                statusTip="Go To Matching Brace", triggered=self.goToMatchingBrace) 
2424
2425        self.selectToMatchingBraceAct = QtGui.QAction("Select To Matching Brace", self, shortcut="Ctrl+Shift+]",
2426                statusTip="Select To Matching Brace", triggered=self.selectToMatchingBrace) 
2427               
2428        self.cutAct = QtGui.QAction(QtGui.QIcon(':/icons/edit-cut.png'), "Cu&t",
2429                self, shortcut=QtGui.QKeySequence.Cut,
2430                statusTip="Cut the current selection's contents to the clipboard",
2431                triggered=self.cut)
2432
2433        self.copyAct = QtGui.QAction(QtGui.QIcon(':/icons/edit-copy.png'),
2434                "&Copy", self, shortcut=QtGui.QKeySequence.Copy,
2435                statusTip="Copy the current selection's contents to the clipboard",
2436                triggered=self.copy)
2437
2438        self.pasteAct = QtGui.QAction(QtGui.QIcon(':/icons/edit-paste.png'),
2439                "&Paste", self, shortcut=QtGui.QKeySequence.Paste,
2440                statusTip="Paste the clipboard's contents into the current selection",
2441                triggered=self.paste)
2442
2443        self.increaseIndentAct = QtGui.QAction(QtGui.QIcon(':/icons/format-indent-more.png'),"IncreaseIndent", self, shortcut="Tab",
2444                statusTip="Increase Indent", triggered=self.increaseIndent) 
2445               
2446        self.decreaseIndentAct = QtGui.QAction(QtGui.QIcon(':/icons/format-indent-less.png'),"DecreaseIndent", self, shortcut="Shift+Tab",
2447                statusTip="Decrease Indent", triggered=self.decreaseIndent) 
2448               
2449        self.upperCaseAct=QtGui.QAction("CONVERT TO UPPER CASE", self, shortcut="Ctrl+Shift+U",
2450                statusTip="Convert To Upper Case", triggered=self.convertToUpperCase)
2451               
2452        self.lowerCaseAct=QtGui.QAction("convert to lower case", self, shortcut="Ctrl+U",
2453                statusTip="Convert To Upper Case", triggered=self.convertToLowerCase)
2454         
2455        self.convertEOLAct=QtGui.QAction("Convert EOL", self,statusTip="Convert End of Line Character")
2456        self.convertEOLWinAct=QtGui.QAction("Windows EOL", self,statusTip="Convert End of Line Character to Windows Style",triggered=self.convertEolWindows)
2457        self.convertEOLUnixAct=QtGui.QAction("Unix EOL", self,statusTip="Convert End of Line Character to Unix Style",triggered=self.convertEolUnix)       
2458        self.convertEOLMacAct=QtGui.QAction("Mac EOL", self,statusTip="Convert End of Line Character to Mac Style",triggered=self.convertEolMac)       
2459       
2460        self.undoAct= QtGui.QAction(QtGui.QIcon(':/icons/edit-undo.png'),"Undo", self, shortcut="Ctrl+Z",
2461                statusTip="Undo", triggered=self.__undo)                   
2462               
2463        self.redoAct= QtGui.QAction(QtGui.QIcon(':/icons/edit-redo.png'),"Redo", self, shortcut="Ctrl+Y",
2464                statusTip="Redo", triggered=self.__redo)                   
2465               
2466        self.configurationAct = QtGui.QAction(QtGui.QIcon(':/icons/configure.png'),"Configuration", self, shortcut="",
2467                statusTip="Configuration...", triggered=self.configurationUpdate) 
2468
2469               
2470        self.aboutAct = QtGui.QAction("&About", self,
2471                statusTip="Show the application's About box",
2472                triggered=self.about)
2473
2474        self.aboutQtAct = QtGui.QAction("About &Qt", self,
2475                statusTip="Show the Qt library's About box",
2476                triggered=QtGui.qApp.aboutQt)
2477
2478        self.editTab.currentChanged.connect(self.tabIndexChanged) # connects tab changed signal to appropriate slot
2479        self.editTab.tabCloseRequested.connect(self.closeTabIndex)     
2480
2481       
2482
2483       
2484        # self.cutAct.setEnabled(False)
2485        # self.copyAct.setEnabled(False)
2486        # self.textEdit.copyAvailable.connect(self.cutAct.setEnabled)
2487        # self.textEdit.copyAvailable.connect(self.copyAct.setEnabled)
2488
2489    def createMenus(self):
2490        self.fileMenu = self.menuBar().addMenu("&File")
2491        self.fileMenu.addAction(self.newAct)
2492        self.fileMenu.addAction(self.openAct)
2493        self.fileMenu.addAction(self.saveAct)
2494        self.fileMenu.addAction(self.saveAsAct)
2495        self.fileMenu.addAction(self.saveAllAct)
2496        self.fileMenu.addSeparator()
2497        #---------------------------       
2498        self.fileMenu.addAction(self.printAct)
2499       
2500        self.fileMenu.addSeparator();
2501        #---------------------------       
2502        self.fileMenu.addAction(self.exitAct)
2503
2504        self.editMenu = self.menuBar().addMenu("&Edit")
2505        self.editMenu.addAction(self.cutAct)
2506        self.editMenu.addAction(self.copyAct)
2507        self.editMenu.addAction(self.pasteAct)
2508       
2509        self.editMenu.addSeparator()
2510        self.editMenu.addAction(self.blockCommentAct)       
2511        self.editMenu.addAction(self.blockUncommentAct)
2512       
2513        self.editMenu.addAction(self.increaseIndentAct)
2514        self.editMenu.addAction(self.decreaseIndentAct)
2515        self.editMenu.addSeparator()
2516        self.editMenu.addAction(self.upperCaseAct)
2517        self.editMenu.addAction(self.lowerCaseAct)
2518       
2519        self.convertEOLMenu=self.editMenu.addMenu("Convert EOL")
2520        self.convertEOLMenu.addAction(self.convertEOLWinAct)
2521        self.convertEOLMenu.addAction(self.convertEOLUnixAct)
2522        self.convertEOLMenu.addAction(self.convertEOLMacAct)
2523       
2524        self.editMenu.addSeparator()
2525       
2526        self.editMenu.addAction(self.undoAct)
2527        self.editMenu.addAction(self.redoAct)
2528       
2529        self.searchMenu = self.menuBar().addMenu("&Search")
2530        self.searchMenu.addAction(self.findAct)
2531       
2532        self.searchMenu.addAction(self.findNextAct)
2533       
2534        self.searchMenu.addSeparator()
2535        self.searchMenu.addAction(self.toggleBookmarkAct)
2536        self.searchMenu.addAction(self.goToNextBookmarkAct)
2537        self.searchMenu.addAction(self.goToPreviousBookmarkAct)
2538        self.searchMenu.addAction(self.deleteAllBookmarksAct)
2539        self.searchMenu.addSeparator()
2540        self.searchMenu.addAction(self.goToLineAct)
2541        self.searchMenu.addAction(self.goToMatchingBraceAct)
2542        self.searchMenu.addAction(self.selectToMatchingBraceAct)
2543       
2544       
2545       
2546       
2547
2548       
2549        self.viewMenu = self.menuBar().addMenu("&View")
2550        self.viewMenu.addAction(self.closeTabAct)
2551        self.viewMenu.addAction(self.zoomInAct)
2552        self.viewMenu.addAction(self.zoomOutAct)
2553        self.viewMenu.addSeparator()
2554        #---------------------------
2555        self.viewMenu.addAction(self.foldAllAct)   
2556        self.viewMenu.addSeparator()
2557        #---------------------------
2558        self.viewMenu.addAction(self.showFindInFilesDockAct)
2559       
2560       
2561        self.languageMenu=self.menuBar().addMenu("&Language") # initialized in LanguageManager
2562       
2563       
2564        self.configurationMenu=self.menuBar().addMenu("&Configuration")
2565        self.configurationMenu.addAction(self.configurationAct)
2566       
2567        self.menuBar().addSeparator()
2568
2569        self.helpMenu = self.menuBar().addMenu("&Help")
2570        self.helpMenu.addAction(self.aboutAct)
2571        self.helpMenu.addAction(self.aboutQtAct)
2572
2573    def createToolBars(self):
2574        self.fileToolBar = self.addToolBar("File")
2575        self.fileToolBar.addAction(self.newAct)
2576        self.fileToolBar.addAction(self.openAct)
2577        self.fileToolBar.addAction(self.saveAct)
2578        self.fileToolBar.addAction(self.saveAsAct)
2579        self.fileToolBar.addAction(self.saveAllAct)
2580
2581        self.editToolBar = self.addToolBar("Edit")
2582        self.editToolBar.addAction(self.cutAct)
2583        self.editToolBar.addAction(self.copyAct)
2584        self.editToolBar.addAction(self.pasteAct)
2585        self.editToolBar.addAction(self.increaseIndentAct)
2586        self.editToolBar.addAction(self.decreaseIndentAct)
2587
2588        self.searchToolBar = self.addToolBar("Search")
2589        self.searchToolBar.addAction(self.findAct)
2590        self.searchToolBar.addAction(self.toggleBookmarkAct)
2591       
2592    def createStatusBar(self):
2593        self.statusBar().showMessage("Ready")
2594
2595    def toggleFindInFilesDock(self, _flag=False):
2596        dbgMsg("FLAG=",_flag)
2597        dbgMsg("self.showFindInFilesDockAct.isChecked():",self.showFindInFilesDockAct.isChecked())
2598        if self.findDock.isHidden():
2599            self.findDock.show()
2600        else:
2601            self.findDock.hide()
2602        # if self.showFindInFilesDockAct.isChecked():
2603           
2604            # self.findDock.hide()
2605            # # self.showFindInFilesDockAct.setChecked(False)
2606        # else:
2607            # self.findDock.show()
2608            # # self.showFindInFilesDockAct.setChecked(True)
2609           
2610       
2611    def maybeSave(self):
2612        dbgMsg("slot maybeSave")
2613        # return True
2614        editor=self.editTab.currentWidget()
2615        dbgMsg("editor=",editor," isModified()=",editor.isModified())
2616        if editor.isModified():
2617            fileName=''
2618            if self.getEditorFileName(editor)!='':
2619                fileName = self.getEditorFileName(editor)
2620            else:
2621                index = self.editTab.indexOf(editor)
2622                fileName = self.editTab.tabText(index)       
2623       
2624            message="The document "+fileName+" has been modified.\nDo you want to save changes?"
2625           
2626            ret = QtGui.QMessageBox.warning(self, "Save Modification",
2627                    message,
2628                    QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard |
2629                    QtGui.QMessageBox.Cancel)
2630            if ret == QtGui.QMessageBox.Save:
2631                return self.save()
2632            elif ret == QtGui.QMessageBox.Cancel:
2633                return False
2634        return True
2635   
2636    def __undo(self):
2637        editor=self.editTab.currentWidget()
2638        editor.undo()
2639        self.checkActions()
2640       
2641    def __redo(self):
2642        editor=self.editTab.currentWidget()
2643       
2644        editor.redo()
2645        self.checkActions()
2646       
2647       
2648    def printCurrentDocument(self):
2649        editor=self.editTab.currentWidget()
2650        printer=PrinterTwedit()
2651        printDialog=QPrintDialog(printer,self)
2652        if printDialog.exec_()==QDialog.Accepted:
2653            dbgMsg("Paper size=", printer.paperSize())
2654            printer.setDocName(self.getCurrentDocumentName())
2655            printer.printRange(editor) 
2656        dbgMsg("THIS IS PRINT CURRENT DOCUMENT")
2657       
2658    def convertToUpperCase(self):
2659        editor=self.editTab.currentWidget()       
2660        editor.SendScintilla(QsciScintilla.SCI_UPPERCASE)
2661       
2662    def convertToLowerCase(self):
2663        editor=self.editTab.currentWidget()       
2664        editor.SendScintilla(QsciScintilla.SCI_LOWERCASE)
2665
2666    def convertEolWindows(self):
2667        editor=self.editTab.currentWidget()       
2668        editor.setEolMode(QsciScintilla.EolWindows)
2669        editor.convertEols(QsciScintilla.EolWindows)
2670       
2671    def convertEolUnix(self):
2672        editor=self.editTab.currentWidget()       
2673        editor.setEolMode(QsciScintilla.EolUnix)
2674        editor.convertEols(QsciScintilla.EolUnix)
2675       
2676   
2677    def convertEolMac(self):
2678        editor=self.editTab.currentWidget()       
2679        editor.setEolMode(QsciScintilla.EolMac)
2680        editor.convertEols(QsciScintilla.EolMac)
2681       
2682    def checkActions(self):
2683        editor=self.editTab.currentWidget()
2684        # dbgMsg("dealing with editor", editor)
2685        if editor:
2686            self.undoAct.setEnabled(editor.isUndoAvailable())
2687            self.redoAct.setEnabled(editor.isRedoAvailable())
2688            # dbgMsg("text in editir ",self.editor, "has changed")
2689            # index=self.editTab.indexOf(editor)
2690            # dbgMsg("isModified=",self.editor.isModified())
2691            # if ()
2692            # self.editorWindow.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-edited.png'))
2693           
2694            # dbgMsg("checkActions - document modified=",editor.isModified())
2695       
2696    def __modificationChanged(self, m):
2697        """
2698        Private slot to handle the modificationChanged signal.
2699       
2700        @param m modification status
2701        """
2702        dbgMsg(" INSIDE MODIFICATIONCHANGED SLOT")
2703        self.setWindowModified(m)
2704        self.checkActions()
2705       
2706    def maybeReload(self,tab):
2707        dbgMsg("slot maybeReload")
2708        # return True
2709        message="The document "+self.getEditorFileName(tab)+" has been modified by external program.\nDo you want to reload?"
2710        ret = QtGui.QMessageBox.warning(self, "Reload",
2711                message,
2712                QtGui.QMessageBox.Yes | QtGui.QMessageBox.No )
2713               
2714        if ret == QtGui.QMessageBox.Yes:
2715           
2716            return self.reloadFile(tab,self.getEditorFileName(tab))
2717            # return self.reloadFile(tab,self.fileDict[tab][0])
2718        elif ret == QtGui.QMessageBox.No:
2719            return False
2720        return False
2721
2722
2723    def reloadFile (self, editor,fileName):
2724        file=None   
2725       
2726        try:   
2727            file = open(fileName, 'rb')
2728        except:
2729            QtGui.QMessageBox.warning(self, "Twedit",
2730                    "Cannot read file %s:\n%s." % (fileName, "Check if the file is accessible"))
2731            return     
2732        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
2733        # have to disconnect signal which looks for text changes
2734        # editor.textChanged.disconnect(self.textChangedHandlers[editor].handleChangedText)
2735        editor.modificationChanged.disconnect(self.textChangedHandlers[editor].handleModificationChanged)
2736        editor.textChanged.disconnect(self.textChangedHandlers[editor].handleChangedText)
2737        editor.cursorPositionChanged.disconnect(self.handleCursorPositionChanged)
2738     
2739       
2740       
2741        # txt=file.read()
2742        # file.close()
2743        # editor.setText(txt)
2744       
2745        # txt, encoding = Encoding.decode(file.read())
2746        # dbgMsg("encoding=",encoding        )
2747        # file.close()
2748        # editor.setText(txt)
2749       
2750        import codecs
2751
2752        # txt, encoding = Encoding.decode(file.read())
2753        txt, encoding = Encoding.decode(file)
2754        dbgMsg("RELOAD FILE encoding=",encoding,"\n\n\n")
2755        file.close()               
2756        # add re-read option to avoid duplicate reads in all cases?
2757
2758        fh=codecs.open(fileName,'rb',Encoding.normalizeEncodingName(encoding))
2759        txt=fh.read()               
2760        fh.close()
2761       
2762        editor.setText(txt)       
2763       
2764        # restore text-change watcher signal
2765        # editor.textChanged.connect(self.textChangedHandlers[editor].handleChangedText)
2766        editor.modificationChanged.connect(self.textChangedHandlers[editor].handleModificationChanged)
2767        editor.textChanged.connect(self.textChangedHandlers[editor].handleChangedText)
2768        editor.cursorPositionChanged.connect(self.handleCursorPositionChanged)
2769       
2770        # self.fileDict[editor]=[os.path.abspath(fileName),os.path.getmtime(fileName),encoding] # "normalizing" file name to make sure \ and / are used in a consistent manner
2771        self.setPropertiesInEditorList(editor,os.path.abspath(fileName),os.path.getmtime(fileName),encoding)# "normalizing" file name to make sure \ and / are used in a consistent manner
2772               
2773        editor.setModified(False)
2774       
2775        self.updateTextSizeLabel()
2776        self.updateEncodingLabel()
2777       
2778       
2779       
2780        QtGui.QApplication.restoreOverrideCursor()
2781        return True
2782       
2783    def loadFiles(self, fileNames):
2784        for i in range(fileNames.count()):
2785            self.loadFile(os.path.abspath(fileNames[i]))# "normalizing" file name to make sure \ and / are used in a consistent manner
2786           
2787    # def get_coding(self,text):
2788        # """
2789        # Function to get the coding of a text.
2790       
2791        # @param text text to inspect (string)
2792        # @return coding string
2793        # """
2794        # lines = text.splitlines()
2795        # for coding in coding_regexps:
2796            # coding_re = coding[1]
2797            # head = lines[:coding[0]]
2798            # for l in head:
2799                # m = coding_re.search(l)
2800                # if m:
2801                    # return m.group(1).lower()
2802        # return None           
2803   
2804    # def decode(self,text):
2805        # """
2806        # Function to decode a text.
2807       
2808        # @param text text to decode (string)
2809        # @return decoded text and encoding
2810        # """
2811        # # try:
2812            # # if text.startswith(BOM_UTF8):
2813                # # # UTF-8 with BOM
2814                # # return unicode(text[len(BOM_UTF8):], 'utf-8'), 'utf-8-bom'
2815            # # elif text.startswith(BOM_UTF16):
2816                # # # UTF-16 with BOM
2817                # # return unicode(text[len(BOM_UTF16):], 'utf-16'), 'utf-16'
2818            # # elif text.startswith(BOM_UTF32):
2819                # # # UTF-32 with BOM
2820                # # return unicode(text[len(BOM_UTF32):], 'utf-32'), 'utf-32'
2821            # # coding = self.get_coding(text)
2822            # # if coding:
2823                # # return unicode(text, coding), coding
2824        # # except (UnicodeError, LookupError):
2825            # # return None,None           
2826           
2827        # return unicode(text, 'utf-8'), 'utf-8-guessed'   
2828       
2829    def loadFile(self, fileName,_restoreFlag=False):
2830        # file = QtCore.QFile(fileName)
2831       
2832        # openFileDict={}
2833        # for key in self.fileDict.keys():
2834            # if self.fileDict[key][0]!='':
2835                # openFileDict[self.fileDict[key][0]]=key
2836        openFileDict=self.getFileNameToEditorWidgetMap()       
2837               
2838        if fileName in  openFileDict.keys():
2839            #make tab with open file active
2840            try:
2841                self.editTab.setCurrentWidget(openFileDict[fileName])
2842            except KeyError,e:
2843                pass
2844                # self.editTab.setCurrentWidget("STRANGE FILE")
2845            return
2846           
2847        file=None   
2848       
2849        try:
2850           
2851            file = open(fileName, 'r')
2852        except:
2853            QtGui.QMessageBox.warning(self, "Twedit",
2854                    "Cannot read file %s:\n%s." % (fileName, "Check if the file is accessible"))
2855            return 
2856           
2857           
2858        # if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
2859            # if _restoreFlag:
2860                # return
2861            # QtGui.QMessageBox.warning(self, "Application",
2862                    # "Cannot read file %s:\n%s." % (fileName, file.errorString()))
2863            # return
2864
2865        # inf = QtCore.QTextStream(file)
2866        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
2867       
2868       
2869       
2870        lexer=self.guessLexer(fileName)
2871        textEditLocal=None
2872        encoding=None
2873       
2874        # dbgMsg("self.editTab.count()=",self.editTab.count())
2875        if self.editTab.count()==1:
2876            # have to disconnect signal while opening document in first tab while new text is read in
2877            # self.editTab.widget(0).textChanged.disconnect(self.textChangedHandlers[textEditLocal].handleChangedText) 
2878            textEditLocal = self.editTab.currentWidget()
2879            if not textEditLocal.isModified() and not textEditLocal.length():
2880                # it is better to create new QScintilla object than reuse old one
2881                # because reused editor tab had bookmar problems
2882                self.editTab.removeTab(0)
2883                textEditLocal=QsciScintillaCustom()
2884                self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))           
2885                textEditLocal=self.editTab.currentWidget()
2886           
2887                # dbgMsg("textLocalIs Modified=",textEditLocal.isModified())
2888                # if not file:
2889                    # dbgMsg("file=",file)
2890                   
2891                   
2892                # txt=file.read()                                 
2893                # file.close()                 
2894                # textEditLocal.setText(txt)   
2895                import codecs               
2896                # textTmp=file.read()
2897                # if textTmp.startswith(codecs.BOM_UTF16_BE):
2898                    # dbgMsg("\n\n\nGOT BOM BE\n\n\n")
2899                # else:
2900                    # dbgMsg("\n\n\n DID NOT GET BOM BE\n\n\n")
2901                # passing file.read() to decode causes improper detection of encoding
2902                # we have to first store file content localy and then pass the string to decode fcn
2903                # txt, encoding = Encoding.decode(file.read())
2904                # txt, encoding = Encoding.decode(textTmp)
2905                # file.seek(0)
2906                txt, encoding = Encoding.decode(file)
2907                dbgMsg("section 1 encoding=",encoding,"\n\n\n")
2908                file.close()
2909                # add re-read option to avoid duplicate reads in all cases?
2910               
2911                fh=codecs.open(fileName,'rb',Encoding.normalizeEncodingName(encoding))
2912                txt=fh.read()
2913                fh.close()
2914                # if encoding not in []
2915                textEditLocal.SendScintilla(QsciScintilla.SCI_SETCODEPAGE, QsciScintilla.SC_CP_UTF8)
2916                textEditLocal.setText(txt)
2917
2918               
2919                # textEditLocal.setText(inf.readAll())
2920                self.editTab.setTabText(0,self.strippedName(fileName))   
2921                self.setEditorProperties(textEditLocal)               
2922                if lexer[0]:
2923                    textEditLocal.setLexer(lexer[0])
2924                    self.editTab.currentWidget().setBraceMatching(lexer[3])
2925                   
2926                    if self.configuration.setting("FoldText"):
2927                        textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
2928                    else:
2929                        textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
2930                   
2931                    self.editTab.currentWidget().setWhitespaceVisibility(self.configuration.setting("DisplayWhitespace"))
2932                    self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
2933                    self.editTab.currentWidget().setIndentationGuides(self.configuration.setting("TabGuidelines"))     
2934                   
2935                    # self.editTab.currentWidget().setTabIndents(False)
2936             
2937            else:
2938                textEditLocal=QsciScintillaCustom()
2939                self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))
2940                self.setCurrentFile(fileName)
2941                # textEditLocal.setText(inf.readAll())
2942                # txt, self.encoding = self.decode(file.read())
2943                # file.close()
2944                # txt,encoding=self.decode(file.read())
2945               
2946               
2947                # txt=file.read()
2948                # file.close()
2949                # textEditLocal.setText(txt)
2950                import codecs
2951                # textTmp=file.read()
2952                # if textTmp.startswith(codecs.BOM_UTF16_BE):
2953                    # dbgMsg("\n\n\nGOT BOM BE\n\n\n")
2954                # else:
2955                    # dbgMsg("\n\n\n DID NOT GET BOM BE\n\n\n")
2956               
2957                # txt, encoding = Encoding.decode(file.read())
2958                txt, encoding = Encoding.decode(file)
2959                dbgMsg("section 2 encoding=",encoding,"\n\n\n"               )
2960                file.close()                 
2961                # add re-read option to avoid duplicate reads in all cases?
2962                fh=codecs.open(fileName,'rb',Encoding.normalizeEncodingName(encoding))
2963                txt=fh.read()               
2964                fh.close()
2965                textEditLocal.SendScintilla(QsciScintilla.SCI_SETCODEPAGE, QsciScintilla.SC_CP_UTF8)
2966                textEditLocal.setText(txt)
2967               
2968               
2969                self.setEditorProperties(textEditLocal)
2970                if lexer[0]:
2971                    textEditLocal.setLexer(lexer[0])
2972                    self.editTab.currentWidget().setBraceMatching(lexer[3])                   
2973                    if self.configuration.setting("FoldText"):
2974                        textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
2975                    else:
2976                        textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
2977
2978                    self.editTab.currentWidget().setWhitespaceVisibility(self.configuration.setting("DisplayWhitespace"))
2979                    self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
2980                    self.editTab.currentWidget().setIndentationGuides(self.configuration.setting("TabGuidelines"))     
2981                    # self.editTab.currentWidget().setTabIndents(False)
2982            self.editTab.setTabIcon(0,QtGui.QIcon(':/icons/document-clean.png'))
2983            # enable textChangedSignal       
2984            # self.editTab.widget(0).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)   
2985        else:
2986            textEditLocal=QsciScintillaCustom()
2987            self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))
2988            self.setCurrentFile(fileName)
2989           
2990            # textEditLocal.setText(inf.readAll())
2991            # txt, self.encoding = self.decode(file.read())
2992           
2993            # txt=file.read()
2994            # file.close()
2995            # textEditLocal.setText(txt)
2996            import codecs
2997
2998            # txt, encoding = Encoding.decode(file.read())
2999            txt, encoding = Encoding.decode(file)
3000            dbgMsg("section 3 encoding=",encoding,"\n\n\n")
3001            file.close()               
3002            # add re-read option to avoid duplicate reads in all cases?
3003
3004            fh=codecs.open(fileName,'rb',Encoding.normalizeEncodingName(encoding))
3005            txt=fh.read()               
3006            fh.close()
3007            textEditLocal.SendScintilla(QsciScintilla.SCI_SETCODEPAGE, QsciScintilla.SC_CP_UTF8)
3008            textEditLocal.setText(txt)
3009           
3010           
3011           
3012            self.setEditorProperties(textEditLocal)           
3013            if lexer[0]:
3014                textEditLocal.setLexer(lexer[0])       
3015                self.editTab.currentWidget().setBraceMatching(lexer[3])
3016                if self.configuration.setting("FoldText"):
3017                    textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
3018                else:
3019                    textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
3020               
3021                self.editTab.currentWidget().setWhitespaceVisibility(lexer[5])
3022                self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
3023                self.editTab.currentWidget().setIndentationGuides(True)         
3024                # self.editTab.currentWidget().setTabIndents(False)
3025       
3026        # editor=self.editTab.currentWidget()
3027        editor=textEditLocal
3028        self.editTab.setCurrentWidget(editor)       
3029        editor.setModified(False) # loading document modifies its content but since no new text has been typed we set modified to false
3030
3031        self.checkActions()
3032       
3033        #editor.zoomTo(self.zoom)
3034       
3035        zoomRange=self.configuration.setting("ZoomRange")
3036       
3037        dbgMsg("THIS IS ZOOM RANGE=",zoomRange,"\n\n\n\n\n")
3038        editor.zoomTo(zoomRange)
3039       
3040        # zoomRange=self.configuration.setting("ZoomRange")
3041        # if zoomRange>0:
3042            # editor.zoomIn(zoomRange)
3043        # else:
3044            # editor.zoomOut(-1*zoomRange)
3045       
3046        self.commentStyleDict[editor]=[lexer[1],lexer[2]] # associating comment style with the lexer
3047       
3048       
3049        # self.textEdit.setPlainText(inf.readAll())
3050        QtGui.QApplication.restoreOverrideCursor()
3051
3052        self.setCurrentFile(fileName)
3053        # self.fileDict[editor]=[os.path.abspath(fileName),os.path.getmtime(fileName),encoding] # file is associated with the tab,  "normalizing" file name to make sure \ and / are used in a consistent manner
3054       
3055        self.setPropertiesInEditorList(editor,os.path.abspath(fileName),os.path.getmtime(fileName),encoding)# file is associated with the tab,  "normalizing" file name to make sure \ and / are used in a consistent manner
3056       
3057        # adding text Changed Handler
3058        self.textChangedHandlers[editor]=ChangedTextHandler(editor,self)
3059        editorIndex=self.editTab.indexOf(editor)
3060        dbgMsg("CONNECTING EDITOR INDEX=",editorIndex)
3061        # self.editTab.widget(editorIndex).textChanged.connect(self.textChangedHandlers[editor].handleChangedText) 
3062        self.editTab.widget(editorIndex).modificationChanged.connect(self.textChangedHandlers[editor].handleModificationChanged)
3063        self.editTab.widget(editorIndex).textChanged.connect(self.textChangedHandlers[editor].handleChangedText)
3064        self.editTab.widget(editorIndex).cursorPositionChanged.connect(self.handleCursorPositionChanged)       
3065       
3066        # self.editTab.widget(editorIndex).modificationChanged.connect(self.textChangedHandlers[editor].modificationChangedSlot)
3067       
3068        self.updateTextSizeLabel()
3069        self.updateEncodingLabel()       
3070        dbgMsg(" SETTING fileName=",fileName," os.path.getmtime(fileName)=",os.path.getmtime(fileName))
3071        self.statusBar().showMessage("File loaded", 2000)
3072       
3073        # editor.convertEols(QsciScintilla.EolMac)
3074           
3075    # def loadFile(self, fileName,_restoreFlag=False):
3076        # file = QtCore.QFile(fileName)
3077       
3078        # openFileDict={}
3079        # for key in self.fileDict.keys():
3080            # if self.fileDict[key][0]!='':
3081                # openFileDict[self.fileDict[key][0]]=key
3082               
3083        # if fileName in  openFileDict.keys():
3084            # #make tab with open file active
3085            # try:
3086                # self.editTab.setCurrentWidget(openFileDict[fileName])
3087            # except KeyError,e:
3088                # pass
3089                # # self.editTab.setCurrentWidget("STRANGE FILE")
3090            # return
3091           
3092       
3093        # if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
3094            # if _restoreFlag:
3095                # return
3096            # QtGui.QMessageBox.warning(self, "Application",
3097                    # "Cannot read file %s:\n%s." % (fileName, file.errorString()))
3098            # return
3099
3100        # inf = QtCore.QTextStream(file)
3101        # QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
3102       
3103       
3104       
3105        # lexer=self.guessLexer(fileName)
3106        # textEditLocal=None
3107        # # dbgMsg("self.editTab.count()=",self.editTab.count())
3108        # if self.editTab.count()==1:
3109            # # have to disconnect signal while opening document in first tab while new text is read in
3110            # # self.editTab.widget(0).textChanged.disconnect(self.textChangedHandlers[textEditLocal].handleChangedText) 
3111            # textEditLocal = self.editTab.currentWidget()
3112            # if not textEditLocal.isModified() and not textEditLocal.length():
3113                # # it is better to create new QScintilla object than reuse old one
3114                # # because reused editor tab had bookmar problems
3115                # self.editTab.removeTab(0)
3116                # textEditLocal=QsciScintillaCustom()
3117                # self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))           
3118                # textEditLocal=self.editTab.currentWidget()
3119           
3120                # # dbgMsg("textLocalIs Modified=",textEditLocal.isModified())
3121                # textEditLocal.setText(inf.readAll())
3122                # self.editTab.setTabText(0,self.strippedName(fileName))   
3123                # self.setEditorProperties(textEditLocal)               
3124                # if lexer[0]:
3125                    # textEditLocal.setLexer(lexer[0])
3126                    # self.editTab.currentWidget().setBraceMatching(lexer[3])
3127                   
3128                    # if self.configuration.setting("FoldText"):
3129                        # textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
3130                    # else:
3131                        # textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
3132                   
3133                    # self.editTab.currentWidget().setWhitespaceVisibility(self.configuration.setting("DisplayWhitespace"))
3134                    # self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
3135                    # self.editTab.currentWidget().setIndentationGuides(self.configuration.setting("TabGuidelines"))   
3136                   
3137                    # # self.editTab.currentWidget().setTabIndents(False)
3138             
3139            # else:
3140                # textEditLocal=QsciScintillaCustom()
3141                # self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))
3142                # self.setCurrentFile(fileName)
3143                # textEditLocal.setText(inf.readAll())
3144                # self.setEditorProperties(textEditLocal)
3145                # if lexer[0]:
3146                    # textEditLocal.setLexer(lexer[0])
3147                    # self.editTab.currentWidget().setBraceMatching(lexer[3])                   
3148                    # if self.configuration.setting("FoldText"):
3149                        # textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
3150                    # else:
3151                        # textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
3152
3153                    # self.editTab.currentWidget().setWhitespaceVisibility(self.configuration.setting("DisplayWhitespace"))
3154                    # self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
3155                    # self.editTab.currentWidget().setIndentationGuides(self.configuration.setting("TabGuidelines"))   
3156                    # # self.editTab.currentWidget().setTabIndents(False)
3157            # self.editTab.setTabIcon(0,QtGui.QIcon(':/icons/document-clean.png'))
3158            # # enable textChangedSignal       
3159            # # self.editTab.widget(0).textChanged.connect(self.textChangedHandlers[textEditLocal].handleChangedText)   
3160        # else:
3161            # textEditLocal=QsciScintillaCustom()
3162            # self.editTab.addTab(textEditLocal,QtGui.QIcon(':/icons/document-clean.png'),self.strippedName(fileName))
3163            # self.setCurrentFile(fileName)
3164            # textEditLocal.setText(inf.readAll())
3165            # self.setEditorProperties(textEditLocal)           
3166            # if lexer[0]:
3167                # textEditLocal.setLexer(lexer[0])       
3168                # self.editTab.currentWidget().setBraceMatching(lexer[3])
3169                # if self.configuration.setting("FoldText"):
3170                    # textEditLocal.setFolding(QsciScintilla.BoxedTreeFoldStyle)
3171                # else:
3172                    # textEditLocal.setFolding(QsciScintilla.NoFoldStyle)
3173               
3174                # self.editTab.currentWidget().setWhitespaceVisibility(lexer[5])
3175                # self.editTab.currentWidget().setIndentationGuidesForegroundColor(self.indendationGuidesColor)
3176                # self.editTab.currentWidget().setIndentationGuides(True)       
3177                # # self.editTab.currentWidget().setTabIndents(False)
3178       
3179        # # editor=self.editTab.currentWidget()
3180        # editor=textEditLocal
3181        # self.editTab.setCurrentWidget(editor)       
3182        # editor.setModified(False) # loading document modifies its content but since no new text has been typed we set modified to false
3183        # self.checkActions()
3184       
3185        # #editor.zoomTo(self.zoom)
3186       
3187        # zoomRange=self.configuration.setting("ZoomRange")
3188        # dbgMsg("THIS IS ZOOM RANGE=",zoomRange,"\n\n\n\n\n")
3189        # editor.zoomTo(zoomRange)
3190       
3191        # # zoomRange=self.configuration.setting("ZoomRange")
3192        # # if zoomRange>0:
3193            # # editor.zoomIn(zoomRange)
3194        # # else:
3195            # # editor.zoomOut(-1*zoomRange)
3196       
3197        # self.commentStyleDict[editor]=[lexer[1],lexer[2]] # associating comment style with the lexer
3198       
3199       
3200        # # self.textEdit.setPlainText(inf.readAll())
3201        # QtGui.QApplication.restoreOverrideCursor()
3202
3203        # self.setCurrentFile(fileName)
3204        # self.fileDict[editor]=[os.path.abspath(fileName),os.path.getmtime(fileName)] # file is associated with the tab,  "normalizing" file name to make sure \ and / are used in a consistent manner
3205        # # adding text Changed Handler
3206        # self.textChangedHandlers[editor]=ChangedTextHandler(editor,self)
3207        # editorIndex=self.editTab.indexOf(editor)
3208        # dbgMsg("CONNECTING EDITOR INDEX=",editorIndex)
3209        # # self.editTab.widget(editorIndex).textChanged.connect(self.textChangedHandlers[editor].handleChangedText) 
3210        # self.editTab.widget(editorIndex).modificationChanged.connect(self.textChangedHandlers[editor].handleModificationChanged)         
3211        # # self.editTab.widget(editorIndex).modificationChanged.connect(self.textChangedHandlers[editor].modificationChangedSlot)
3212       
3213        # dbgMsg("fileName=",fileName," os.path.getmtime(fileName)=",os.path.getmtime(fileName))
3214        # self.statusBar().showMessage("File loaded", 2000)
3215       
3216        # # editor.convertEols(QsciScintilla.EolMac)
3217
3218    def tabIndexChanged(self,_index):
3219        editorTab=self.editTab.widget(_index)
3220        # dbgMsg("self.fileDict=",self.fileDict)
3221        self.checkActions()
3222        self.updateTextSizeLabel()
3223        self.updateEncodingLabel()
3224        if editorTab in self.getEditorList(): # have to do this check becaue adding tab triggers this slot but fileDict dictionary has not been initialized yet
3225            self.setCurrentFile(self.getEditorFileName(editorTab))
3226           
3227       
3228    def guessLexer(self,_fileName):
3229       
3230        fileSplit=os.path.splitext(str(_fileName))
3231        extension=fileSplit[1]
3232        # dbgMsg("EXTENSION=",extension)
3233       
3234        if extension in self.extensionLanguageMap.keys():
3235            return self.languageManager.languageLexerDictionary[self.extensionLanguageMap[extension]]
3236        # return format [lexer,begin comment, end comment, brace matching (0- nor matching, 1 matching), codeFolding]
3237
3238           
3239        if os.path.basename(str(_fileName)).lower()=="cmakelists.txt":
3240            return self.languageManager.languageLexerDictionary["CMake"]       
3241   
3242           
3243        if os.path.basename(str(_fileName)).lower()=="makefile":
3244            return self.languageManager.languageLexerDictionary["Makefile"]       
3245   
3246       
3247           
3248           
3249        return [None,'',None,0,0,QsciScintilla.SCWS_INVISIBLE]
3250       
3251
3252       
3253    # def saveFile(self, _fileName,_editor=None):
3254        # self.deactivateChangeSensing=True
3255       
3256        # file = QtCore.QFile(_fileName)
3257       
3258        # # notice using QFile.Text text flag will cause "\n" to be interpreted during save and as a result "\n" will be written as \r\n on windows
3259        # # as a "\n" on linux. This is not what we want we want literal eno of line storage that is: "\n" is written as "\n" - intepreted as LF
3260        # # "\r\n" is stored as "\r\n" (literally) and interpretted as CR LF
3261        # # and "\r" is interpreted as CR
3262       
3263        # # if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
3264       
3265        # if not file.open(QtCore.QFile.WriteOnly ):
3266            # QtGui.QMessageBox.warning(self, "Twedit",
3267                    # "Cannot write file %s:\n%s." % (_fileName, file.errorString()))
3268            # self.deactivateChangeSensing=False           
3269            # return False
3270
3271        # # outf = QtCore.QTextStream(file)
3272        # QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
3273        # textEditLocal=None
3274        # if _editor:
3275            # textEditLocal=_editor
3276        # else:
3277            # textEditLocal=self.editTab.currentWidget()
3278           
3279
3280
3281       
3282
3283        # txt=textEditLocal.text()
3284        # byteArray=txt.toUtf8()
3285        # file.write(byteArray)       
3286        # file.close()
3287       
3288        # QtGui.QApplication.restoreOverrideCursor()
3289
3290        # dbgMsg("SAVE FILE EDITOR=",_editor,"\n\n\n\n")
3291        # if _editor:
3292            # self.fileDict[_editor]=[_fileName,os.path.getmtime(_fileName)] # saving new name and new modification time
3293        # else:   
3294            # self.setCurrentFile(_fileName)
3295            # self.fileDict[self.editTab.currentWidget()]=[_fileName,os.path.getmtime(_fileName)] # saving new name and new modification time
3296        # self.statusBar().showMessage("File saved", 2000)
3297        # if _editor:
3298            # textEditLocal.setModified(False)
3299           
3300            # index=self.editTab.indexOf(textEditLocal)
3301            # self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))           
3302        # else :
3303            # self.editTab.currentWidget().setModified(False)
3304           
3305            # index=self.editTab.indexOf(self.editTab.currentWidget())
3306            # self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))
3307           
3308        # self.deactivateChangeSensing=False
3309        # return True
3310
3311    def saveFile(self, _fileName,_editor=None):
3312   
3313        self.deactivateChangeSensing=True
3314   
3315        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
3316        textEditLocal=None
3317        if _editor:
3318            textEditLocal=_editor
3319        else:
3320            textEditLocal=self.editTab.currentWidget()
3321   
3322        encoding='utf-8'
3323        txt = unicode(textEditLocal.text())
3324        # work around glitch in scintilla: always make sure,
3325        # that the last line is terminated properly
3326        # eol = self.getLineSeparator()
3327        # if eol:
3328            # if len(txt) >= len(eol):
3329                # if txt[-len(eol):] != eol:
3330                    # txt += eol
3331            # else:
3332                # txt += eol
3333               
3334        try:
3335            fileNameToEditorMap=self.getFileNameToEditorWidgetMap() 
3336           
3337
3338            editorLocal=None
3339            try:
3340                editorLocal=fileNameToEditorMap[_fileName]
3341            except:
3342                dbgMsg("COULD NOT FIND EDITOR FOR FILE NAME=",_fileName)
3343               
3344            try:   
3345                encoding=self.getEditorFileEncoding(textEditLocal)                   
3346                # encoding=self.fileDict[textEditLocal][2]                   
3347            except:           
3348                dbgMsg("COULD NOT FIND ENCODING")
3349               
3350            # encoding='ucs-2'   
3351            txt, encoding = Encoding.encode(txt, encoding)
3352        except Encoding.CodingError, e:
3353            QtGui.QMessageBox.warning(self, "Twedit",
3354                    "Cannot write file %s:\n%s." % (_fileName, repr(e)))
3355            self.deactivateChangeSensing=False           
3356            return False       
3357           
3358        # now write text to the file fn
3359        try:
3360            dbgMsg("SAVE - ENCODING = ",encoding,"\n\n\n\n\n")
3361           
3362            import codecs
3363            fh=codecs.open(_fileName, 'wb',Encoding.normalizeEncodingName(encoding))
3364           
3365            # fh=open(_fileName, 'wb')
3366            Encoding.writeBOM(fh,encoding)
3367            fh.write(txt)
3368            fh.close()
3369            # f = open(_fileName, 'wb')
3370            # f.write(txt)
3371            # f.close()
3372            # file = QtCore.QFile(_fileName)
3373           
3374            # if not file.open(QtCore.QFile.WriteOnly ):
3375                # QtGui.QMessageBox.warning(self, "Twedit",
3376                        # "Cannot write file %s:\n%s." % (_fileName, file.errorString()))
3377                # self.deactivateChangeSensing=False           
3378                # return False           
3379               
3380            # # txt=textEditLocal.text()
3381            # byteArray=QByteArray(txt)
3382            # file.write(byteArray)       
3383            # file.close()           
3384            # if createBackup and perms_valid:
3385                # os.chmod(fn, permissions)
3386            # return True
3387        except IOError, why:
3388            QtGui.QMessageBox.warning(self, "Twedit",
3389                    "Cannot write file %s:\n%s." % (_fileName, why))                   
3390            self.deactivateChangeSensing=False
3391            return False
3392           
3393           
3394        QtGui.QApplication.restoreOverrideCursor()   
3395
3396        dbgMsg("SAVE FILE EDITOR=",_editor,"\n\n\n\n")
3397        if _editor:
3398            # self.fileDict[_editor]=[_fileName,os.path.getmtime(_fileName),encoding] # saving new name and new modification time
3399            self.setPropertiesInEditorList(_editor,_fileName,os.path.getmtime(_fileName),encoding)# saving new name and new modification time
3400        else:   
3401            self.setCurrentFile(_fileName)
3402            # self.fileDict[self.editTab.currentWidget()]=[_fileName,os.path.getmtime(_fileName),encoding] # saving new name and new modification time   
3403            self.setPropertiesInEditorList(self.editTab.currentWidget(),_fileName,os.path.getmtime(_fileName),encoding)# saving new name and new modification time           
3404        self.statusBar().showMessage("File saved", 2000)
3405        if _editor:
3406            textEditLocal.setModified(False)
3407           
3408            index=self.editTab.indexOf(textEditLocal)
3409            self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))           
3410        else :
3411            self.editTab.currentWidget().setModified(False)
3412           
3413            index=self.editTab.indexOf(self.editTab.currentWidget())
3414            self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))       
3415        self.deactivateChangeSensing=False
3416        return True
3417       
3418    def setCurrentFile(self, fileName):
3419        self.curFile = fileName
3420        # self.textEdit.document().setModified(False)
3421        self.setWindowModified(False)
3422
3423        if self.curFile:
3424            # shownName = self.strippedName(self.curFile)
3425            shownName = self.curFile
3426        else:
3427            shownName = 'untitled.txt'
3428
3429        self.setWindowTitle("[*]%s - CC3D-Twedit" % shownName) # [*] is a placeholder for window modification flag - here it is positionwed before window title so that it is visible when windows has been modified
3430
3431    def strippedName(self, fullFileName):
3432        return QtCore.QFileInfo(fullFileName).fileName()
3433       
3434    def __createDockWindow(self, name):
3435        """
3436        Private method to create a dock window with common properties.
3437       
3438        @param name object name of the new dock window (string or QString)
3439        @return the generated dock window (QDockWindow)
3440        """
3441        dock = QDockWidget(self)
3442        dock.setObjectName(name)
3443        #dock.setFeatures(QDockWidget.DockWidgetFeatures(QDockWidget.AllDockWidgetFeatures))
3444        return dock
3445       
3446    def __setupDockWindow(self, dock, where, widget, caption, showFlag=False):
3447        """
3448        Private method to configure the dock window created with __createDockWindow().
3449       
3450        @param dock the dock window (QDockWindow)
3451        @param where dock area to be docked to (Qt.DockWidgetArea)
3452        @param widget widget to be shown in the dock window (QWidget)
3453        @param caption caption of the dock window (string or QString)
3454        """
3455        if caption is None:
3456            caption = QString()
3457        self.addDockWidget(where, dock)
3458        dock.setWidget(widget)
3459        dock.hide()
3460        dock.setWindowTitle(caption)
3461        if showFlag:
3462            dock.show()
3463
3464# class EditorWindow(QMainWindow):
3465        # def __init__(self,_parent=None):
3466                # QMainWindow.__init__(self,_parent)
3467                # textEdit = QsciScintillaCustom()
3468                # self.setCentralWidget(textEdit)
3469               
3470        # def setArgv(self,_argv):
3471                # dbgMsg("command line arguments",_argv)
3472"""
3473    old implementation of the saveFile slot
3474    # def saveFile(self, fileName,_editor=None):
3475        # # self.deactivateChangeSensing=True
3476        # file = QtCore.QFile(fileName)
3477        # if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
3478            # QtGui.QMessageBox.warning(self, "Application",
3479                    # "Cannot write file %s:\n%s." % (fileName, file.errorString()))
3480            # # self.deactivateChangeSensing=False           
3481            # return False
3482
3483        # outf = QtCore.QTextStream(file)
3484        # QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
3485        # textEditLocal=None
3486        # if _editor:
3487            # textEditLocal=_editor
3488        # else:
3489            # textEditLocal=self.editTab.currentWidget()
3490           
3491        # outf << textEditLocal.text().toUtf8()
3492        # QtGui.QApplication.restoreOverrideCursor()
3493
3494        # dbgMsg("SAVE FILE EDITOR=",_editor,"\n\n\n\n")
3495        # if _editor:
3496            # self.fileDict[_editor]=[fileName,os.path.getmtime(fileName)] # saving new name and new modification time
3497        # else:   
3498            # self.setCurrentFile(fileName)
3499            # self.fileDict[self.editTab.currentWidget()]=[fileName,os.path.getmtime(fileName)] # saving new name and new modification time
3500        # self.statusBar().showMessage("File saved", 2000)
3501        # if _editor:
3502            # textEditLocal.setModified(False)
3503           
3504            # index=self.editTab.indexOf(textEditLocal)
3505            # self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))           
3506        # else :
3507            # self.editTab.currentWidget().setModified(False)
3508           
3509            # index=self.editTab.indexOf(self.editTab.currentWidget())
3510            # self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))
3511           
3512        # # self.deactivateChangeSensing=False
3513        # return True
3514       
3515    def saveFile(self, _fileName,_editor=None):
3516        # self.deactivateChangeSensing=True
3517        # # # # file=None
3518       
3519        # # # # try:
3520            # # # # file = open(str(_fileName),'w')
3521           
3522        # # # # except:
3523            # # # # # self.statusBar().message('Could not write to %s' % (self._filename),2000)
3524            # # # # QtGui.QMessageBox.warning(self, "Application",
3525                    # # # # "Cannot write file %s:\n%s." % (_fileName, "Please check if you have permissions to write"))
3526            # # # # # self.deactivateChangeSensing=False           
3527            # # # # return False           
3528           
3529       
3530        # file = QtCore.QFile(_fileName)
3531       
3532        # if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
3533            # QtGui.QMessageBox.warning(self, "Application",
3534                    # "Cannot write file %s:\n%s." % (_fileName, file.errorString()))
3535            # # self.deactivateChangeSensing=False           
3536            # return False
3537
3538        # outf = QtCore.QTextStream(file)
3539        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
3540        textEditLocal=None
3541        if _editor:
3542            textEditLocal=_editor
3543        else:
3544            textEditLocal=self.editTab.currentWidget()
3545           
3546        # # # # # outf << textEditLocal.text()
3547        # # # # dbgMsg("ENCODING is UTF8=",textEditLocal.isUtf8())
3548        # # # # # txt,encoding=self.decode(textEditLocal.text())
3549        # # # # txt=textEditLocal.text()
3550        # # # # # txt=textEditLocal.text()
3551       
3552        # # # # # # txt=unicode(txt, 'utf-8')
3553        # # # # # # it is important to do this replacement on QString as returned by text() function
3554        # # # # # # otherwise CR LF combo will end up being writte as CR CR LF introducing extra line for every CR LF character
3555        # # # # dbgMsg("FOUND cr lf=",txt.contains("\r\n"))
3556        # # # # dbgMsg("FOUND lf=",txt.contains("\n"))
3557        # # # # dbgMsg("FOUND cr=",txt.contains("\r"))
3558        # # # # txt.replace("\r\n","\n")
3559        # # # # dbgMsg("txt.toAscii()=",txt.toAscii())
3560        # # # # byteArray=txt.toAscii()
3561        # # # # dbgMsg("BYTE ARRAY LENGTH=",byteArray.count()," content=",byteArray)
3562        # # # # # txt.replace("\n","")
3563        # # # # # dbgMsg("txt=",txt)
3564        # # # # # txt=str(txt)
3565        # # # # file.write("a\nb\nc\nd")
3566        # # # # # file.write(txt.toAscii())
3567        # # # # # txt=unicode(textEditLocal.text())
3568        # # # # # txt.encode('ascii')
3569        # # # # # txt=textEditLocal.text()
3570        # # # # # file.write(txt)
3571        # # # # file.close()     
3572       
3573        file = QtCore.QFile(_fileName)
3574        # if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
3575        if not file.open(QtCore.QFile.WriteOnly ):
3576            QtGui.QMessageBox.warning(self, "Application",
3577                    "Cannot write file %s:\n%s." % (fileName, file.errorString()))
3578            # self.deactivateChangeSensing=False           
3579            return False
3580
3581       
3582        # file.open(QIODevice.WriteOnly)
3583        # byteArray=QString("\r\n").toUtf8()
3584        # byteArray=QString("\r\n").toAscii()
3585        txt=textEditLocal.text()
3586        byteArray=txt.toAscii()
3587        file.write(byteArray)       
3588        file.close()
3589       
3590        QtGui.QApplication.restoreOverrideCursor()
3591
3592        dbgMsg("SAVE FILE EDITOR=",_editor,"\n\n\n\n")
3593        if _editor:
3594            self.fileDict[_editor]=[_fileName,os.path.getmtime(_fileName)] # saving new name and new modification time
3595        else:   
3596            self.setCurrentFile(_fileName)
3597            self.fileDict[self.editTab.currentWidget()]=[_fileName,os.path.getmtime(_fileName)] # saving new name and new modification time
3598        self.statusBar().showMessage("File saved", 2000)
3599        if _editor:
3600            textEditLocal.setModified(False)
3601           
3602            index=self.editTab.indexOf(textEditLocal)
3603            self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))           
3604        else :
3605            self.editTab.currentWidget().setModified(False)
3606           
3607            index=self.editTab.indexOf(self.editTab.currentWidget())
3608            self.editTab.setTabIcon(index,QtGui.QIcon(':/icons/document-clean.png'))
3609           
3610        # self.deactivateChangeSensing=False
3611        return True
3612"""       
Note: See TracBrowser for help on using the browser.