]> SALOME platform Git repositories - tools/eficas.git/blob - InterfaceQT/viewManager.py
Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / InterfaceQT / viewManager.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21
22 import os
23 from InterfaceQT import utilIcons 
24 from qt import *
25
26
27 ##fonctions utilitaires
28 def normabspath(path):
29     """
30     Function returning a normalized, absolute path.
31     
32     @param path file path (string)
33     @return absolute, normalized path (string)
34     """
35     return os.path.abspath(path)
36     
37     
38 def samepath(f1, f2):
39     """
40     Function to compare two paths.
41     
42     @param f1 first path for the compare (string)
43     @param f2 second path for the compare (string)
44     @return flag indicating whether the two paths represent the
45         same path on disk.
46     """
47     if f1 is None or f2 is None:
48         return 0
49         
50     if normcasepath(f1) == normcasepath(f2):
51         return 1
52         
53     return 0
54
55 def normcasepath(path):
56     """
57     Function returning a path, that is normalized with respect to its case and references.
58     
59     @param path file path (string)
60     @return case normalized path (string)
61     """
62     return os.path.normcase(os.path.normpath(path))    
63     
64
65
66
67 class ViewManager:
68     """
69     Base class inherited by all specific viewmanager classes.
70     
71     It defines the interface to be implemented by specific
72     viewmanager classes and all common methods.
73     
74     @signal lastEditorClosed emitted after the last editor window was closed
75     @signal editorOpened(string) emitted after an editor window was opened
76     @signal editorSaved(string) emitted after an editor window was saved
77     @signal checkActions(editor) emitted when some actions should be checked
78             for their status
79     @signal cursorChanged(editor) emitted after the cursor position of the active
80             window has changed
81     @signal breakpointToggled(editor) emitted when a breakpoint is toggled.
82     @signal bookmarkToggled(editor) emitted when a bookmark is toggled.
83     """
84     def __init__(self, ui ):
85         """
86         Constructor
87         
88         @param ui reference to the main user interface
89         @param dbs reference to the debug server object
90         """
91         # initialize the instance variables
92         self.ui = ui
93         self.appliEficas = ui
94         self.editors = []
95         self.doubles = {}
96         self.currentEditor = None
97         self.untitledCount = 0
98         self.srHistory = {"search" : QStringList(), "replace" : QStringList()}
99         self.editorsCheckFocusIn = 1
100         self.recent =  QStringList()      
101                 
102         
103         # initialize the central store for api information (used by
104         # autocompletion and calltips)
105         self.apis = {}
106         self.initFileFilters()
107         
108         
109     def initFileFilters(self):
110         """
111         Private method to initialize the lists of supported filename filters.
112         """
113         self.fileFiltersString = self.trUtf8(\
114             'Python Files (*.py);;'
115             'Aster Files (*.com*);;'
116             'Pyrex Files (*.pyx);;'
117             'Quixote Template Files (*.ptl);;'
118             'IDL Files (*.idl);;'
119             'C Files (*.h *.c);;'
120             'C++ Files (*.h *.hpp *.hh *.cxx *.cpp *.cc);;'
121             'C# Files (*.cs);;'
122             'HTML Files (*.html *.htm *.asp *.shtml *.css);;'
123             'PHP Files (*.php *.php3 *.php4 *.php5 *.phtml);;'
124             'XML Files (*.xml *.xsl *.xslt *.dtd);;'
125             'Java Files (*.java);;'
126             'JavaScript Files (*.js);;'
127             'SQL Files (*.sql);;'
128             'Docbook Files (*.docbook);;'
129             'Perl Files (*.pl *.pm *.ph);;'
130             'Shell Files (*.sh);;'
131             'Aster Files (*.com*);;'
132             'All Files (*)')
133
134         fileFilters = QStringList.split(';;', self.fileFiltersString)
135         
136         self.ext2Filter = {}
137         for fileFilter in fileFilters:
138             extensions = QStringList.split('*', fileFilter)
139             for extension in extensions[1:]:
140                 extension = unicode(extension).strip().replace(')', '')
141                 if extension:
142                     self.ext2Filter[extension] = unicode(fileFilter)
143         
144         
145         
146     #####################################################################
147     ## methods above need to be implemented by a subclass
148     #####################################################################
149     
150     def canSplit(self):
151         """
152         public method to signal if splitting of the view is available.
153         
154         @return flag indicating splitting of the view is available.
155         """
156         return 0
157         
158     def addSplit(self):
159         """
160         Public method used to split the current view.
161         """
162         pass
163         
164     def removeSplit(self):
165         """
166         Public method used to remove the current split view.
167         
168         @return Flag indicating successful deletion
169         """
170         return 0
171         
172     def setSplitOrientation(self, orientation):
173         """
174         Public method used to set the orientation of the split view.
175         
176         @param orientation orientation of the split
177                 (QSplitter.Horizontal or QSplitter.Vertical)
178         """
179         pass
180         
181     def eventFilter(self, object, event):
182         """
183         Private method called to filter an event.
184         
185         @param object object, that generated the event (QObject)
186         @param event the event, that was generated by object (QEvent)
187         @return flag indicating if event was filtered out
188         """
189         return 0
190         
191     def focusInEvent(self, event):
192         """
193         Public method called when the viewmanager receives focus.
194         
195         @param event the event object (QFocusEvent)
196         """
197         self.editorActGrp.setEnabled(1)
198         
199     def focusOutEvent(self, event):
200         """
201         Public method called when the viewmanager loses focus.
202         
203         @param event the event object (QFocusEvent)
204         """
205         self.editorActGrp.setEnabled(0)
206         
207     
208     def initEditMenu(self):
209         """
210         Public method to create the Edit menu
211         
212         @return the generated menu
213         """
214         menu = QPopupMenu(self.ui)
215         menu.insertTearOffHandle()
216         self.undoAct.addTo(menu)
217         self.redoAct.addTo(menu)
218         self.revertAct.addTo(menu)
219         menu.insertSeparator()
220         self.cutAct.addTo(menu)
221         self.copyAct.addTo(menu)
222         self.pasteAct.addTo(menu)
223         self.deleteAct.addTo(menu)
224         menu.insertSeparator()
225         self.indentAct.addTo(menu)
226         self.unindentAct.addTo(menu)
227         menu.insertSeparator()
228         self.commentAct.addTo(menu)
229         self.uncommentAct.addTo(menu)
230         self.streamCommentAct.addTo(menu)
231         self.boxCommentAct.addTo(menu)
232         menu.insertSeparator()
233         self.autoCompleteAct.addTo(menu)
234         self.autoCompleteFromDocAct.addTo(menu)
235         self.autoCompleteFromAPIsAct.addTo(menu)
236         menu.insertSeparator()
237         self.searchAct.addTo(menu)
238         self.searchAgainAct.addTo(menu)
239         self.replaceAct.addTo(menu)
240         menu.insertSeparator()
241         self.searchFilesAct.addTo(menu)
242         menu.insertSeparator()
243         self.gotoAct.addTo(menu)
244         self.gotoBraceAct.addTo(menu)
245         menu.insertSeparator()
246         self.selectBraceAct.addTo(menu)
247         self.selectAllAct.addTo(menu)
248         self.deselectAllAct.addTo(menu)
249         menu.insertSeparator()
250         self.shortenEmptyAct.addTo(menu)
251         self.convertEOLAct.addTo(menu)
252         
253         return menu
254         
255     def initEditToolbar(self):
256         """
257         Public method to create the Edit toolbar
258         
259         @return the generated toolbar
260         """
261         tb = QToolBar(self.ui)
262         self.undoAct.addTo(tb)
263         self.redoAct.addTo(tb)
264         tb.addSeparator()
265         self.cutAct.addTo(tb)
266         self.copyAct.addTo(tb)
267         self.pasteAct.addTo(tb)
268         self.deleteAct.addTo(tb)
269         tb.addSeparator()
270         self.indentAct.addTo(tb)
271         self.unindentAct.addTo(tb)
272         tb.addSeparator()
273         self.commentAct.addTo(tb)
274         self.uncommentAct.addTo(tb)
275         
276         return tb
277         
278     ##################################################################
279     ## Initialize the search related actions, search menu and toolbar
280     ##################################################################
281     
282     def initSearchActions(self):
283         """
284         Private method defining the user interface actions for the search commands.
285         """
286         self.searchActGrp = QActionGroup(self)
287         
288         self.searchAct = QAction(self.trUtf8('Search'),
289                 QIconSet(utilIcons.getPixmap("find.png")),
290                 self.trUtf8('&Search...'),
291                 QKeySequence(self.trUtf8("CTRL+F","Search|Search")),
292                 self.searchActGrp)
293         self.searchAct.setStatusTip(self.trUtf8('Search for a text'))
294         self.searchAct.setWhatsThis(self.trUtf8(
295             """<b>Search</b>"""
296             """<p>Search for some text in the current editor. A"""
297             """ dialog is shown to enter the searchtext and options"""
298             """ for the search.</p>"""
299         ))
300         self.connect(self.searchAct,SIGNAL('activated()'),self.handleSearch)
301         self.searchActions.append(self.searchAct)
302         
303         self.searchAgainAct = QAction(self.trUtf8('Search again'),
304                 QIconSet(utilIcons.getPixmap("findNext.png")),
305                 self.trUtf8('Search &again'),
306                 Qt.Key_F3,self.searchActGrp)
307         self.searchAgainAct.setStatusTip(self.trUtf8('Search again for text'))
308         self.searchAgainAct.setWhatsThis(self.trUtf8(
309             """<b>Search again</b>"""
310             """<p>Search again for some text in the current editor."""
311             """ The previously entered searchtext and options are reused.</p>"""
312         ))
313         self.connect(self.searchAgainAct,SIGNAL('activated()'),self.searchDlg.handleFindNext)
314         self.searchActions.append(self.searchAgainAct)
315         
316         self.replaceAct = QAction(self.trUtf8('Replace'),
317                 self.trUtf8('&Replace...'),
318                 QKeySequence(self.trUtf8("CTRL+R","Search|Replace")),
319                 self.searchActGrp)
320         self.replaceAct.setStatusTip(self.trUtf8('Replace some text'))
321         self.replaceAct.setWhatsThis(self.trUtf8(
322             """<b>Replace</b>"""
323             """<p>Search for some text in the current editor and replace it. A"""
324             """ dialog is shown to enter the searchtext, the replacement text"""
325             """ and options for the search and replace.</p>"""
326         ))
327         self.connect(self.replaceAct,SIGNAL('activated()'),self.handleReplace)
328         self.searchActions.append(self.replaceAct)
329         
330         self.gotoAct = QAction(self.trUtf8('Goto Line'),
331                 QIconSet(utilIcons.getPixmap("goto.png")),
332                 self.trUtf8('&Goto Line...'),
333                 QKeySequence(self.trUtf8("CTRL+G","Search|Goto Line")),
334                 self.searchActGrp)
335         self.gotoAct.setStatusTip(self.trUtf8('Goto Line'))
336         self.gotoAct.setWhatsThis(self.trUtf8(
337             """<b>Goto Line</b>"""
338             """<p>Go to a specific line of text in the current editor."""
339             """ A dialog is shown to enter the linenumber.</p>"""
340         ))
341         self.connect(self.gotoAct,SIGNAL('activated()'),self.handleGoto)
342         self.searchActions.append(self.gotoAct)
343         
344         self.gotoBraceAct = QAction(self.trUtf8('Goto Brace'),
345                 QIconSet(utilIcons.getPixmap("gotoBrace.png")),
346                 self.trUtf8('Goto &Brace'),
347                 QKeySequence(self.trUtf8("CTRL+L","Search|Goto Brace")),
348                 self.searchActGrp)
349         self.gotoBraceAct.setStatusTip(self.trUtf8('Goto Brace'))
350         self.gotoBraceAct.setWhatsThis(self.trUtf8(
351             """<b>Goto Brace</b>"""
352             """<p>Go to the matching brace in the current editor.</p>"""
353         ))
354         self.connect(self.gotoBraceAct,SIGNAL('activated()'),self.handleGotoBrace)
355         self.searchActions.append(self.gotoBraceAct)
356         
357         self.searchActGrp.setEnabled(0)
358         
359         self.searchFilesAct = QAction(self.trUtf8('Search in Files'),
360                 QIconSet(utilIcons.getPixmap("projectFind.png")),
361                 self.trUtf8('Search in &Files...'),
362                 QKeySequence(self.trUtf8("SHIFT+CTRL+F","Search|Search Files")),
363                 self)
364         self.searchFilesAct.setStatusTip(self.trUtf8('Search for a text in files'))
365         self.searchFilesAct.setWhatsThis(self.trUtf8(
366             """<b>Search in Files</b>"""
367             """<p>Search for some text in the files of a directory tree"""
368             """ or the project. A dialog is shown to enter the searchtext"""
369             """ and options for the search and to display the result.</p>"""
370         ))
371         self.connect(self.searchFilesAct,SIGNAL('activated()'),self.handleSearchFiles)
372         self.searchActions.append(self.searchFilesAct)
373         
374         
375     ##################################################################
376     ## Initialize the view related actions, view menu and toolbar
377     ##################################################################
378     
379     def initViewActions(self):
380         """
381         Protected method defining the user interface actions for the view commands.
382         """
383         self.viewActGrp = QActionGroup(self)
384         self.viewFoldActGrp = QActionGroup(self)
385
386         self.zoomInAct = QAction(self.trUtf8('Zoom in'),
387                             QIconSet(utilIcons.getPixmap("zoomIn.png")),
388                             self.trUtf8('Zoom &in'),
389                             Qt.CTRL+Qt.Key_Plus, self.viewActGrp)
390         self.zoomInAct.setStatusTip(self.trUtf8('Zoom in on the text'))
391         self.zoomInAct.setWhatsThis(self.trUtf8(
392                 """<b>Zoom in</b>"""
393                 """<p>Zoom in on the text. This makes the text bigger.</p>"""
394                 ))
395         self.connect(self.zoomInAct,SIGNAL('activated()'),self.handleZoomIn)
396         self.viewActions.append(self.zoomInAct)
397         
398         self.zoomOutAct = QAction(self.trUtf8('Zoom out'),
399                             QIconSet(utilIcons.getPixmap("zoomOut.png")),
400                             self.trUtf8('Zoom &out'),
401                             Qt.CTRL+Qt.Key_Minus, self.viewActGrp)
402         self.zoomOutAct.setStatusTip(self.trUtf8('Zoom out on the text'))
403         self.zoomOutAct.setWhatsThis(self.trUtf8(
404                 """<b>Zoom out</b>"""
405                 """<p>Zoom out on the text. This makes the text smaller.</p>"""
406                 ))
407         self.connect(self.zoomOutAct,SIGNAL('activated()'),self.handleZoomOut)
408         self.viewActions.append(self.zoomOutAct)
409         
410         self.zoomToAct = QAction(self.trUtf8('Zoom'),
411                             QIconSet(utilIcons.getPixmap("zoomTo.png")),
412                             self.trUtf8('&Zoom'),
413                             0, self.viewActGrp)
414         self.zoomToAct.setStatusTip(self.trUtf8('Zoom the text'))
415         self.zoomToAct.setWhatsThis(self.trUtf8(
416                 """<b>Zoom</b>"""
417                 """<p>Zoom the text. This opens a dialog where the"""
418                 """ desired size can be entered.</p>"""
419                 ))
420         self.connect(self.zoomToAct,SIGNAL('activated()'),self.handleZoom)
421         self.viewActions.append(self.zoomToAct)
422         
423         self.toggleAllAct = QAction(self.trUtf8('Toggle all folds'),
424                             self.trUtf8('Toggle &all folds'),
425                             0, self.viewFoldActGrp)
426         self.toggleAllAct.setStatusTip(self.trUtf8('Toggle all folds'))
427         self.toggleAllAct.setWhatsThis(self.trUtf8(
428                 """<b>Toggle all folds</b>"""
429                 """<p>Toggle all folds of the current editor.</p>"""
430                 ))
431         self.connect(self.toggleAllAct,SIGNAL('activated()'),self.handleToggleAll)
432         self.viewActions.append(self.toggleAllAct)
433         
434         self.toggleCurrentAct = QAction(self.trUtf8('Toggle current fold'),
435                             self.trUtf8('Toggle &current fold'),
436                             0, self.viewFoldActGrp)
437         self.toggleCurrentAct.setStatusTip(self.trUtf8('Toggle current fold'))
438         self.toggleCurrentAct.setWhatsThis(self.trUtf8(
439                 """<b>Toggle current fold</b>"""
440                 """<p>Toggle the folds of the current line of the current editor.</p>"""
441                 ))
442         self.connect(self.toggleCurrentAct,SIGNAL('activated()'),self.handleToggleCurrent)
443         self.viewActions.append(self.toggleCurrentAct)
444         
445         self.unhighlightAct = QAction(self.trUtf8('Remove all highlights'),
446                             QIconSet(utilIcons.getPixmap("unhighlight.png")),
447                             self.trUtf8('Remove all highlights'),
448                             0, self)
449         self.unhighlightAct.setStatusTip(self.trUtf8('Remove all highlights'))
450         self.unhighlightAct.setWhatsThis(self.trUtf8(
451                 """<b>Remove all highlights</b>"""
452                 """<p>Remove the highlights of all editors.</p>"""
453                 ))
454         self.connect(self.unhighlightAct,SIGNAL('activated()'),self.unhighlight)
455         self.viewActions.append(self.unhighlightAct)
456         
457         self.splitViewAct = QAction(self.trUtf8('Split view'),
458                             QIconSet(utilIcons.getPixmap("splitVertical.png")),
459                             self.trUtf8('&Split view'),
460                             0, self)
461         self.splitViewAct.setStatusTip(self.trUtf8('Add a split to the view'))
462         self.splitViewAct.setWhatsThis(self.trUtf8(
463                 """<b>Split view</b>"""
464                 """<p>Add a split to the view.</p>"""
465                 ))
466         self.connect(self.splitViewAct,SIGNAL('activated()'),self.handleSplitView)
467         self.viewActions.append(self.splitViewAct)
468         
469         self.splitOrientationAct = QAction(self.trUtf8('Arrange horizontally'),
470                             self.trUtf8('Arrange &horizontally'),
471                             0, self, None, 1)
472         self.splitOrientationAct.setStatusTip(self.trUtf8('Arrange the splitted views horizontally'))
473         self.splitOrientationAct.setWhatsThis(self.trUtf8(
474                 """<b>Arrange horizontally</b>"""
475                 """<p>Arrange the splitted views horizontally.</p>"""
476                 ))
477         self.splitOrientationAct.setOn(0)
478         self.connect(self.splitOrientationAct,SIGNAL('activated()'),self.handleSplitOrientation)
479         self.viewActions.append(self.splitOrientationAct)
480         
481         self.splitRemoveAct = QAction(self.trUtf8('Remove split'),
482                             QIconSet(utilIcons.getPixmap("remsplitVertical.png")),
483                             self.trUtf8('&Remove split'),
484                             0, self)
485         self.splitRemoveAct.setStatusTip(self.trUtf8('Remove the current split'))
486         self.splitRemoveAct.setWhatsThis(self.trUtf8(
487                 """<b>Remove split</b>"""
488                 """<p>Remove the current split.</p>"""
489                 ))
490         self.connect(self.splitRemoveAct,SIGNAL('activated()'),self.removeSplit)
491         self.viewActions.append(self.splitRemoveAct)
492         
493         self.viewActGrp.setEnabled(0)
494         self.viewFoldActGrp.setEnabled(0)
495         self.unhighlightAct.setEnabled(0)
496         self.splitViewAct.setEnabled(0)
497         self.splitOrientationAct.setEnabled(0)
498         self.splitRemoveAct.setEnabled(0)
499         
500     def initViewMenu(self):
501         """
502         Public method to create the View menu
503         
504         @return the generated menu
505         """
506         menu = QPopupMenu(self.ui)
507         menu.insertTearOffHandle()
508         self.viewActGrp.addTo(menu)
509         menu.insertSeparator()
510         self.viewFoldActGrp.addTo(menu)
511         menu.insertSeparator()
512         self.unhighlightAct.addTo(menu)
513         if self.canSplit():
514             menu.insertSeparator()
515             self.splitViewAct.addTo(menu)
516             self.splitOrientationAct.addTo(menu)
517             self.splitRemoveAct.addTo(menu)       
518         return menu
519         
520     def initViewToolbar(self):
521         """
522         Public method to create the View toolbar
523         
524         @return the generated toolbar
525         """
526         tb = QToolBar(self.ui)
527         self.viewActGrp.addTo(tb)
528         tb.addSeparator()
529         self.unhighlightAct.addTo(tb)
530         if self.canSplit():
531             tb.addSeparator()
532             self.splitViewAct.addTo(tb)
533             self.splitRemoveAct.addTo(tb)
534         
535         return tb
536         
537     ##################################################################
538     ## Initialize the macro related actions and macro menu
539     ##################################################################
540     
541     def initMacroActions(self):
542         """
543         Private method defining the user interface actions for the macro commands.
544         """
545         self.macroActGrp = QActionGroup(self)
546
547         self.macroStartRecAct = QAction(self.trUtf8('Start Macro Recording'),
548                             self.trUtf8('S&tart Macro Recording'),
549                             0, self.macroActGrp)
550         self.macroStartRecAct.setStatusTip(self.trUtf8('Start Macro Recording'))
551         self.macroStartRecAct.setWhatsThis(self.trUtf8(
552                 """<b>Start Macro Recording</b>"""
553                 """<p>Start recording editor commands into a new macro.</p>"""
554                 ))
555         self.connect(self.macroStartRecAct,SIGNAL('activated()'),self.handleMacroStartRecording)
556         self.macroActions.append(self.macroStartRecAct)
557         
558         self.macroStopRecAct = QAction(self.trUtf8('Stop Macro Recording'),
559                             self.trUtf8('Sto&p Macro Recording'),
560                             0, self.macroActGrp)
561         self.macroStopRecAct.setStatusTip(self.trUtf8('Stop Macro Recording'))
562         self.macroStopRecAct.setWhatsThis(self.trUtf8(
563                 """<b>Stop Macro Recording</b>"""
564                 """<p>Stop recording editor commands into a new macro.</p>"""
565                 ))
566         self.connect(self.macroStopRecAct,SIGNAL('activated()'),self.handleMacroStopRecording)
567         self.macroActions.append(self.macroStopRecAct)
568         
569         self.macroRunAct = QAction(self.trUtf8('Run Macro'),
570                             self.trUtf8('&Run Macro'),
571                             0, self.macroActGrp)
572         self.macroRunAct.setStatusTip(self.trUtf8('Run Macro'))
573         self.macroRunAct.setWhatsThis(self.trUtf8(
574                 """<b>Run Macro</b>"""
575                 """<p>Run a previously recorded editor macro.</p>"""
576                 ))
577         self.connect(self.macroRunAct,SIGNAL('activated()'),self.handleMacroRun)
578         self.macroActions.append(self.macroRunAct)
579         
580         self.macroDeleteAct = QAction(self.trUtf8('Delete Macro'),
581                             self.trUtf8('&Delete Macro'),
582                             0, self.macroActGrp)
583         self.macroDeleteAct.setStatusTip(self.trUtf8('Delete Macro'))
584         self.macroDeleteAct.setWhatsThis(self.trUtf8(
585                 """<b>Delete Macro</b>"""
586                 """<p>Delete a previously recorded editor macro.</p>"""
587                 ))
588         self.connect(self.macroDeleteAct,SIGNAL('activated()'),self.handleMacroDelete)
589         self.macroActions.append(self.macroDeleteAct)
590         
591         self.macroLoadAct = QAction(self.trUtf8('Load Macro'),
592                             self.trUtf8('&Load Macro'),
593                             0, self.macroActGrp)
594         self.macroLoadAct.setStatusTip(self.trUtf8('Load Macro'))
595         self.macroLoadAct.setWhatsThis(self.trUtf8(
596                 """<b>Load Macro</b>"""
597                 """<p>Load an editor macro from a file.</p>"""
598                 ))
599         self.connect(self.macroLoadAct,SIGNAL('activated()'),self.handleMacroLoad)
600         self.macroActions.append(self.macroLoadAct)
601         
602         self.macroSaveAct = QAction(self.trUtf8('Save Macro'),
603                             self.trUtf8('&Save Macro'),
604                             0, self.macroActGrp)
605         self.macroSaveAct.setStatusTip(self.trUtf8('Save Macro'))
606         self.macroSaveAct.setWhatsThis(self.trUtf8(
607                 """<b>Save Macro</b>"""
608                 """<p>Save a previously recorded editor macro to a file.</p>"""
609                 ))
610         self.connect(self.macroSaveAct,SIGNAL('activated()'),self.handleMacroSave)
611         self.macroActions.append(self.macroSaveAct)
612         
613         self.macroActGrp.setEnabled(0)
614         
615     def initMacroMenu(self):
616         """
617         Public method to create the Macro menu
618         
619         @return the generated menu
620         """
621         menu = QPopupMenu(self.ui)
622         menu.insertTearOffHandle()
623         self.macroActGrp.addTo(menu)
624         return menu
625     
626
627     def checkDirty(self, editor):
628         """
629         Private method to check dirty status and open a message window.
630         
631         @param editor editor window to check
632         @return flag indicating successful reset of the dirty flag (boolean)
633         """        
634      
635         if (editor.modified) and (editor in self.doubles.keys()) :
636             res = QMessageBox.warning(
637                      None,
638                      self.trUtf8("Fichier Duplique"),
639                      self.trUtf8("Le fichier ne sera pas sauvegarde."),
640                      self.trUtf8("&Quitter"), 
641                      self.trUtf8("&Annuler"))
642             if res == 0 : return 1
643             return 0
644         if editor.modified:
645             fn = editor.getFileName()
646             if fn is None:
647                 fn = self.trUtf8('Noname')
648             res = QMessageBox.warning(self.parent(), 
649                 self.trUtf8("Fichier Modifie"),
650                 self.trUtf8("Le fichier <b>%1</b> n a pas ete sauvegarde.")
651                     .arg(fn),
652                 self.trUtf8("&Sauvegarder"), self.trUtf8("&Quitter "),
653                 self.trUtf8("&Annuler"), 0, 2)
654             if res == 0:
655                 (ok, newName) = editor.saveFile()
656                 if ok:
657                     self.setEditorName(editor, newName)
658                 return ok
659             elif res == 2:
660                 return  0
661         return 1
662         
663     def checkAllDirty(self):
664         """
665         Public method to check the dirty status of all editors.
666         
667         @return flag indicating successful reset of all dirty flags (boolean)
668         """
669         for editor in self.editors:
670             if not self.checkDirty(editor):
671                 return 0
672                 
673         return 1
674         
675     def closeEditor(self, editor):
676         """
677         Private method to close an editor window.
678         
679         @param editor editor window to be closed
680         @return flag indicating success (boolean)
681         """
682         # save file if necessary
683         if not self.checkDirty(editor):
684             return 0
685             
686         # remove the window
687         self.removeView(editor)
688         self.editors.remove(editor)        
689         if not len(self.editors):
690             self.handleLastEditorClosed()
691             self.emit(PYSIGNAL('lastEditorClosed'), ()) #CS_pbruno connecter signal avec l'appli
692         return 1
693     
694     def handleClose(self):
695         """
696         Public method to close the current window.
697         
698         @return flag indicating success (boolean)
699         """
700         aw = self.activeWindow()
701         if aw is None:
702             return 0
703             
704         res = self.closeEditor(aw)
705         if res and aw == self.currentEditor:
706             self.currentEditor = None
707             
708         return res
709         
710     def handleNewView(self):
711         """
712         Public method to close the current window.
713         
714         @return flag indicating success (boolean)
715         """
716         aw = self.activeWindow()
717         if aw is None:
718             return 0
719             
720         aw.handleNewView()
721         
722             
723     def handleCloseAll(self):
724         """
725         Private method to close all editor windows via file menu.
726         """
727         savedEditors = self.editors[:]
728         retour=1
729         for editor in savedEditors:
730             retour=retour*self.closeEditor(editor)
731         return retour
732             
733     def handleCloseWindow(self, fn):
734         """
735         Public method to close an arbitrary source editor.
736         
737         @param fn filename of editor to be closed
738         @return flag indicating success (boolean)
739         """
740         for editor in self.editors:
741             if samepath(fn, editor.getFileName()):
742                 break
743         else:
744             return 1
745             
746         res = self.closeEditor(editor)
747         if res and editor == self.currentEditor:
748             self.currentEditor = None
749             
750         return res
751         
752     def handleExit(self):
753         """
754         Public method to handle the debugged program terminating.
755         """
756         if self.currentEditor is not None:
757             self.currentEditor.highlight()
758             self.currentEditor = None
759             
760         self.setSbFile()
761
762     def handlePythonFile(self,pyfn,lineno=None):
763         """
764         Public method to handle the user selecting a file for display.
765         
766         @param pyfn name of file to be opened
767         @param lineno line number to place the cursor at
768         """
769         try:
770             self.displayPythonFile(pyfn,lineno)
771         except IOError:
772             pass
773
774         
775     def displayJDC(self,jdc,fn=None):
776         """
777         Public slot to display a file in an editor.
778         
779         @param fn name of file to be opened
780         @param lineno line number to place the cursor at
781         """        
782         titre=None
783         if fn != None : titre=fn.split("/")[-1]
784         newWin, editor = self.getEditor(None, jdc, title = titre )
785         
786         if newWin:
787             editor.fileName=fn
788             self.handleModificationStatusChanged(editor.modified, editor)
789         self.checkActions(editor)
790         
791         # insert filename into list of recently opened files
792         self.addToRecentList(editor.getFileName())
793
794
795         
796     def newEditorView(self, fn, caller):
797         """
798         Public method to create a new editor displaying the given document.
799         
800         @param fn filename of this view
801         @param caller reference to the editor calling this method        
802         """
803         from editor import JDCEditor
804         editor = JDCEditor(fn, None, self, editor=caller)
805         self.editors.append(editor)
806         self.connect(editor, PYSIGNAL('modificationStatusChanged'),
807             self.handleModificationStatusChanged)
808         self.connect(editor, PYSIGNAL('cursorChanged'), self.handleCursorChanged)
809         self.connect(editor, PYSIGNAL('editorSaved'), self.handleEditorSaved)
810         self.connect(editor, PYSIGNAL('breakpointToggled'), self.handleBreakpointToggled)
811         self.connect(editor, PYSIGNAL('bookmarkToggled'), self.handleBookmarkToggled)
812         self.connect(editor, PYSIGNAL('syntaxerrorToggled'), self.handleSyntaxErrorToggled)
813         self.connect(editor, PYSIGNAL('autoCompletionAPIsAvailable'), 
814             self.handleEditoracAPIsAvailable)
815         self.handleEditorOpened()
816         self.emit(PYSIGNAL('editorOpened'), (fn,))
817         
818         self.connect(caller, PYSIGNAL('editorRenamed'), editor.handleRenamed)
819         self.connect(editor, PYSIGNAL('editorRenamed'), caller.handleRenamed)
820         
821         self.addView(editor, fn)
822         self.handleModificationStatusChanged(editor.modified, editor)
823         self.checkActions(editor)
824         
825     def addToRecentList(self, fn):
826         """
827         Public slot to add a filename to the list of recently opened files.
828         
829         @param fn name of the file to be added
830         """
831         self.recent.remove(fn)
832         self.recent.prepend(fn)
833         if len(self.recent) > 9:
834             self.recent = self.recent[:9]
835
836     def toggleWindow(self,w):
837         """
838         Private method to toggle a workspace window.
839         
840         @param w editor window to be toggled
841         """
842         if w.isHidden():
843             w.show()
844         else:
845             w.hide()
846
847     def setFileLine(self,fn,line,error=0,syntaxError=0):
848         """
849         Public method to update the user interface when the current program or line changes.
850         
851         @param fn filename of editor to update (string)
852         @param line line number to highlight (int)
853         @param error flag indicating an error highlight (boolean)
854         @param syntaxError flag indicating a syntax error
855         """
856         self.setSbFile(fn,line)
857
858         try:
859             newWin, self.currentEditor = self.getEditor(fn)
860         except IOError:
861             return
862
863         # Change the highlighted line.
864         self.currentEditor.highlight(line,error,syntaxError)
865
866         self.currentEditor.highlightVisible()
867         self.checkActions(self.currentEditor, 0)
868             
869     def setSbFile(self,fn=None,line=None,pos=None):
870         """
871         Private method to set the file info in the status bar.
872         
873         @param fn filename to display (string)
874         @param line line number to display (int)
875         @param pos character position to display (int)
876         """
877         if fn is None:
878             fn = ''
879             writ = '   '
880         else:
881             if QFileInfo(fn).isWritable():
882                 writ = ' rw'
883             else:
884                 writ = ' ro'
885         
886         self.sbWritable.setText(writ)
887         self.sbFile.setText(self.trUtf8('File: %1').arg(fn,-50))
888
889         if line is None:
890             line = ''
891
892         self.sbLine.setText(self.trUtf8('Line: %1').arg(line,5))
893
894         if pos is None:
895             pos = ''
896             
897         self.sbPos.setText(self.trUtf8('Pos: %1').arg(pos, 5))
898         
899     def unhighlight(self, current=0):
900         """
901         Public method to switch off all highlights.
902         
903         @param current flag indicating only the current editor should be unhighlighted
904                 (boolean)
905         """
906         if current: 
907             if self.currentEditor is not None:
908                 self.currentEditor.highlight()
909         else:
910             for editor in self.editors:
911                 editor.highlight()
912
913     def getOpenFilenames(self):
914         """
915         Public method returning a list of the filenames of all editors.
916         
917         @return list of all opened filenames (list of strings)
918         """
919         filenames = []
920         for editor in self.editors:
921             fn = editor.getFileName()
922             if fn is not None:
923                 filenames.append(fn)
924                 
925         return filenames
926                 
927     def getEditor(self, fn, jdc = None, title = None, units = None):
928         """
929         Private method to return the editor displaying the given file.
930         
931         If there is no editor with the given file, a new editor window is
932         created.
933         
934         @param fn filename to look for
935         @param isPythonFile flag indicating that this is a Python file
936                 even if it doesn't have the .py extension (boolean)
937         @return tuple of two values giving a flag indicating a new window creation and
938             a reference to the editor displaying this file
939         """
940         newWin = 0
941         double=None
942         for editor in self.editors:
943             if samepath(fn, editor.getFileName()):
944                abort = QMessageBox.warning(self,
945                         self.trUtf8("Fichier"),
946                         self.trUtf8("Le fichier <b>%1</b> est deja ouvert.Voulez-vous l ouvrir tel qu'il etait lors du dernier enregistrement") .arg(fn),
947                         self.trUtf8("&Duplication"),
948                         self.trUtf8("&Annuler"), None, 1)
949                if abort:
950                         break
951                double=editor
952         else:
953             from editor import JDCEditor
954             editor = JDCEditor(fn, jdc, self,units=units)
955             if double != None :
956                self.doubles[editor]=double
957                #self.doubles[double]=editor
958             if editor.jdc: # le fichier est bien un jdc            
959                 self.editors.append(editor)
960                 self.connect(editor, PYSIGNAL('modificationStatusChanged'),
961                     self.handleModificationStatusChanged)
962                 self.connect(editor, PYSIGNAL('cursorChanged'), self.handleCursorChanged)
963                 self.connect(editor, PYSIGNAL('editorSaved'), self.handleEditorSaved)
964                 self.connect(editor, PYSIGNAL('breakpointToggled'), self.handleBreakpointToggled)
965                 self.connect(editor, PYSIGNAL('bookmarkToggled'), self.handleBookmarkToggled)
966                 self.connect(editor, PYSIGNAL('syntaxerrorToggled'), self.handleSyntaxErrorToggled)
967                 self.connect(editor, PYSIGNAL('autoCompletionAPIsAvailable'), 
968                     self.handleEditoracAPIsAvailable)
969                 self.handleEditorOpened()
970                 self.emit(PYSIGNAL('editorOpened'), (fn,))
971                 newWin = 1
972             else:
973                 editor.closeIt()
974
975         if newWin:
976             self.addView(editor, fn , title)
977         elif editor.jdc:
978             self.showView(editor, fn)
979             
980         return (newWin, editor)
981         
982         
983     def getOpenEditor(self, fn):
984         """
985         Public method to return the editor displaying the given file.
986         
987         @param fn filename to look for
988         @return a reference to the editor displaying this file or None, if
989             no editor was found
990         """
991         for editor in self.editors:
992             if samepath(fn, editor.getFileName()):
993                 return editor
994                 
995         return None
996
997     def getActiveName(self):
998         """
999         Public method to retrieve the filename of the active window.
1000         
1001         @return filename of active window (string)
1002         """
1003         aw = self.activeWindow()
1004         if aw:
1005             return aw.getFileName()
1006         else:
1007             return None
1008
1009     def saveEditor(self, fn):
1010         """
1011         Public method to save a named editor file.
1012         
1013         @param fn filename of editor to be saved (string)
1014         @return flag indicating success (boolean)
1015         """
1016         for editor in self.editors:
1017             if samepath(fn, editor.getFileName()):
1018                 break
1019         else:
1020             return 1
1021             
1022         if not editor.modified:
1023             return 1
1024         else:
1025             ok, dummy = editor.saveFile()
1026             return ok
1027         
1028     def saveCurrentEditor(self):
1029         """
1030         Public slot to save the contents of the current editor.
1031         """
1032         aw = self.activeWindow()
1033         if aw in self.doubles.keys() :
1034            QMessageBox.warning(
1035                      None,
1036                      self.trUtf8("Fichier Duplique"),
1037                      self.trUtf8("Le fichier ne sera pas sauvegarde."),
1038                      self.trUtf8("&Annuler"))
1039            return
1040         if aw:
1041             ok, newName = aw.saveFile()
1042             if ok:
1043                 self.setEditorName(aw, newName)
1044         else:
1045             return
1046
1047     def saveAsCurrentEditor(self):
1048         """
1049         Public slot to save the contents of the current editor to a new file.
1050         """
1051         aw = self.activeWindow()
1052         if aw:
1053             ok, newName = aw.saveFileAs()
1054             if ok:
1055                 self.setEditorName(aw, newName)
1056         else:
1057             return
1058
1059     def saveAllEditors(self):
1060         """
1061         Public slot to save the contents of all editors.
1062         """
1063         for editor in self.editors:
1064             ok, newName = editor.saveFile()
1065             if ok:
1066                 self.setEditorName(editor, newName)
1067         
1068         # restart autosave timer
1069         if self.autosaveInterval > 0:
1070             self.autosaveTimer.start(self.autosaveInterval * 60000, 1)
1071
1072     def saveCurrentEditorToProject(self):
1073         """
1074         Public slot to save the contents of the current editor to the current project.
1075         """
1076         pro = self.ui.getProject()
1077         path = pro.ppath
1078         aw = self.activeWindow()
1079         if aw:
1080             ok, newName = aw.saveFileAs(path)
1081             if ok:
1082                 self.setEditorName(aw, newName)
1083                 pro.appendFile(newName)
1084         else:
1085             return
1086         
1087     def newIncludeEditor(self) :
1088         self.newEditor(include=1)
1089         
1090     def newEditor(self,include=0):
1091         """
1092         Public slot to generate a new empty editor.
1093         """
1094         from editor import JDCEditor
1095         editor = JDCEditor(None,None,self,include=include)
1096         
1097         self.editors.append(editor)
1098         self.connect(editor, PYSIGNAL('modificationStatusChanged'),
1099             self.handleModificationStatusChanged)
1100         self.connect(editor, PYSIGNAL('cursorChanged'), self.handleCursorChanged)
1101         self.connect(editor, PYSIGNAL('editorSaved'),   self.handleEditorSaved)
1102         self.connect(editor, PYSIGNAL('breakpointToggled'), self.handleBreakpointToggled)
1103         self.connect(editor, PYSIGNAL('bookmarkToggled'), self.handleBookmarkToggled)
1104         self.connect(editor, PYSIGNAL('syntaxerrorToggled'), self.handleSyntaxErrorToggled)
1105         self.connect(editor, PYSIGNAL('autoCompletionAPIsAvailable'), 
1106             self.handleEditoracAPIsAvailable)
1107         self.addView(editor, None)
1108         self.handleEditorOpened()
1109         self.checkActions(editor)
1110         self.emit(PYSIGNAL('editorOpened'), (None,))
1111         
1112     def printCurrentEditor(self):
1113         """
1114         Public slot to print the contents of the current editor.
1115         """
1116         aw = self.activeWindow()
1117         if aw:
1118             aw.printFile()
1119         else:
1120             return
1121
1122     def printCurrentEditorSel(self):
1123         """
1124         Public slot to print the selection of the current editor.
1125         """
1126         aw = self.activeWindow()
1127         if aw:
1128             aw.printSelection()
1129         else:
1130             return
1131
1132     def handlevisuJdcPy(self):
1133         if self.activeWindow()== None : return
1134         self.activeWindow().viewJdcPy()
1135         
1136     def handleViewJdcFichierSource(self):
1137         if self.activeWindow()== None : return
1138         self.activeWindow().viewJdcSource()
1139                 
1140     def handleViewJdcRapport(self):
1141         if self.activeWindow()== None : return
1142         self.activeWindow().viewJdcRapport()
1143         
1144     def handleNewProject(self):
1145         """
1146         Public slot to handle the NewProject signal.
1147         """
1148         self.saveToProjectAct.setEnabled(1)
1149         
1150     def handleProjectOpened(self):
1151         """
1152         Public slot to handle the projectOpened signal.
1153         """
1154         self.saveToProjectAct.setEnabled(1)
1155         
1156     def handleProjectClosed(self):
1157         """
1158         Public slot to handle the projectClosed signal.
1159         """
1160         self.saveToProjectAct.setEnabled(0)
1161         
1162     def handleProjectFileRenamed(self, oldfn, newfn):
1163         """
1164         Public slot to handle the projectFileRenamed signal.
1165         
1166         @param oldfn old filename of the file (string)
1167         @param newfn new filename of the file (string)
1168         """
1169         editor = self.getOpenEditor(oldfn)
1170         if editor:
1171             editor.fileRenamed(newfn)
1172         
1173     def enableEditorsCheckFocusIn(self, enabled):
1174         """
1175         Public method to set a flag enabling the editors to perform focus in checks.
1176         
1177         @param enabled flag indicating focus in checks should be performed (boolean)
1178         """
1179         self.editorsCheckFocusIn = enabled
1180         
1181     def editorsCheckFocusInEnabled(self):
1182         """
1183         Public method returning the flag indicating editors should perform focus in checks.
1184         
1185         @return flag indicating focus in checks should be performed (boolean)
1186         """
1187         return self.editorsCheckFocusIn
1188
1189     def handleFindFileName(self):
1190         """
1191         Private method to handle the search for file action.
1192         """
1193         self.ui.findFileNameDialog.show()
1194         self.ui.findFileNameDialog.raiseW()
1195         self.ui.findFileNameDialog.setActiveWindow()
1196         
1197     ##################################################################
1198     ## Below are the action methods for the edit menu
1199     ##################################################################
1200     
1201     def handleEditUndo(self):
1202         """
1203         Private method to handle the undo action.
1204         """
1205         self.activeWindow().undo()
1206         
1207     def handleEditRedo(self):
1208         """
1209         Private method to handle the redo action.
1210         """
1211         self.activeWindow().redo()
1212         
1213     def handleEditRevert(self):
1214         """
1215         Private method to handle the revert action.
1216         """
1217         self.activeWindow().revertToUnmodified()
1218         
1219     def handleEditCut(self):
1220         """
1221         Private method to handle the cut action.
1222         """
1223         self.activeWindow().cut()
1224         
1225     def handleEditCopy(self):
1226         """
1227         Private method to handle the copy action.
1228         """
1229         self.activeWindow().copy()
1230         
1231     def handleEditPaste(self):
1232         """
1233         Private method to handle the paste action.
1234         """
1235         self.activeWindow().paste()
1236         
1237     def handleEditDelete(self):
1238         """
1239         Private method to handle the delete action.
1240         """
1241         self.activeWindow().clear()
1242         
1243     def handleEditIndent(self):
1244         """
1245         Private method to handle the indent action.
1246         """
1247         self.activeWindow().indentLineOrSelection()
1248         
1249     def handleEditUnindent(self):
1250         """
1251         Private method to handle the unindent action.
1252         """
1253         self.activeWindow().unindentLineOrSelection()
1254         
1255     def handleEditComment(self):
1256         """
1257         Private method to handle the comment action.
1258         """
1259         self.activeWindow().commentLineOrSelection()
1260         
1261     def handleEditUncomment(self):
1262         """
1263         Private method to handle the uncomment action.
1264         """
1265         self.activeWindow().uncommentLineOrSelection()
1266         
1267     def handleEditStreamComment(self):
1268         """
1269         Private method to handle the stream comment action.
1270         """
1271         self.activeWindow().streamCommentLineOrSelection()
1272         
1273     def handleEditBoxComment(self):
1274         """
1275         Private method to handle the box comment action.
1276         """
1277         self.activeWindow().boxCommentLineOrSelection()
1278         
1279     def handleEditSelectBrace(self):
1280         """
1281         Private method to handle the select to brace action.
1282         """
1283         self.activeWindow().selectToMatchingBrace()
1284         
1285     def handleEditSelectAll(self):
1286         """
1287         Private method to handle the select all action.
1288         """
1289         self.activeWindow().selectAll(1)
1290         
1291     def handleEditDeselectAll(self):
1292         """
1293         Private method to handle the select all action.
1294         """
1295         self.activeWindow().selectAll(0)
1296         
1297     def handleConvertEOL(self):
1298         """
1299         Private method to handle the convert line end characters action.
1300         """
1301         aw = self.activeWindow()
1302         aw.convertEols(aw.eolMode())
1303         
1304     def handleShortenEmptyLines(self):
1305         """
1306         Private method to handle the shorten empty lines action.
1307         """
1308         self.activeWindow().handleShortenEmptyLines()
1309         
1310     def handleEditAutoComplete(self):
1311         """
1312         Private method to handle the autocomplete action.
1313         """
1314         aw = self.activeWindow()
1315         aw.autoComplete()
1316         
1317     def handleEditAutoCompleteFromDoc(self):
1318         """
1319         Private method to handle the autocomplete from document action.
1320         """
1321         aw = self.activeWindow()
1322         aw.autoCompleteFromDocument()
1323         
1324     def handleEditAutoCompleteFromAPIs(self):
1325         """
1326         Private method to handle the autocomplete from APIs action.
1327         """
1328         aw = self.activeWindow()
1329         aw.autoCompleteFromAPIs()
1330         
1331     def handleEditoracAPIsAvailable(self, available):
1332         """
1333         Private method to handle the availability of API autocompletion signal.
1334         """
1335         self.autoCompleteFromAPIsAct.setEnabled(available)
1336         
1337     ##################################################################
1338     ## Below are the action and utility methods for the search menu
1339     ##################################################################
1340
1341     def getWord(self, text, index):
1342         """
1343         Private method to get the word at a position.
1344         
1345         @param text text to look at (string or QString)
1346         @param index position to look at (int)
1347         @return the word at that position
1348         """
1349         re = QRegExp('[^\w_]')
1350         start = text.findRev(re, index) + 1
1351         end = text.find(re, index)
1352         if end > start:
1353             word = text.mid(start, end-start)
1354         else:
1355             word = QString('')
1356         return word
1357         
1358     def textForFind(self):
1359         """
1360         Private method to determine the selection or the current word for the next find operation.
1361         
1362         @return selection or current word (QString)
1363         """
1364         aw = self.activeWindow()
1365         if aw is None:
1366             return ''
1367             
1368         if aw.hasSelectedText():
1369             text = aw.selectedText()
1370             if text.contains('\r') or text.contains('\n'):
1371                 # the selection contains at least a newline, it is
1372                 # unlikely to be the expression to search for
1373                 return ''
1374                 
1375             return text
1376             
1377         # no selected text, determine the word at the current position
1378         line, index = aw.getCursorPosition()
1379         return self.getWord(aw.text(line), index)
1380         
1381     def getSRHistory(self, key):
1382         """
1383         Private method to get the search or replace history list.
1384         
1385         @param key list to return (must be 'search' or 'replace')
1386         @return the requested history list (QStringList)
1387         """
1388         return self.srHistory[key]
1389         
1390     def handleSearch(self):
1391         """
1392         Private method to handle the search action.
1393         """
1394         self.searchDlg.showFind(self.textForFind())
1395         
1396     def handleReplace(self):
1397         """
1398         Private method to handle the replace action.
1399         """
1400         self.replaceDlg.showReplace(self.textForFind())
1401         
1402     def handleGoto(self):
1403         """
1404         Private method to handle the goto action.
1405         """
1406         aw = self.activeWindow()
1407         dlg = GotoDialog(self.ui, None, 1)
1408         dlg.selectAll()
1409         if dlg.exec_loop() == QDialog.Accepted:
1410             aw.gotoLine(min(dlg.getLinenumber(), aw.lines()))
1411         
1412     def handleGotoBrace(self):
1413         """
1414         Private method to handle the goto brace action.
1415         """
1416         self.activeWindow().moveToMatchingBrace()
1417         
1418     def handleSearchFiles(self):
1419         """
1420         Private method to handle the search in files action.
1421         """
1422         self.ui.findFilesDialog.show(self.textForFind())
1423         self.ui.findFilesDialog.raiseW()
1424         self.ui.findFilesDialog.setActiveWindow()
1425         
1426     ##################################################################
1427     ## Below are the action methods for the view menu
1428     ##################################################################
1429     
1430     def handleZoomIn(self):
1431         """
1432         Private method to handle the zoom in action.
1433         """
1434         self.activeWindow().zoomIn()
1435         
1436     def handleZoomOut(self):
1437         """
1438         Private method to handle the zoom out action.
1439         """
1440         self.activeWindow().zoomOut()
1441         
1442     def handleZoom(self):
1443         """
1444         Private method to handle the zoom action.
1445         """
1446         aw = self.activeWindow()
1447         dlg = ZoomDialog(aw.getZoom(), self.ui, None, 1)
1448         if dlg.exec_loop() == QDialog.Accepted:
1449             aw.zoomTo(dlg.getZoomSize())
1450             
1451     def handleToggleAll(self):
1452         """
1453         Private method to handle the toggle all folds action.
1454         """
1455         self.activeWindow().foldAll()
1456         
1457     def handleToggleCurrent(self):
1458         """
1459         Private method to handle the toggle current fold action.
1460         """
1461         aw = self.activeWindow()
1462         line, index = aw.getCursorPosition()
1463         aw.foldLine(line)
1464         
1465     def handleSplitView(self):
1466         """
1467         Private method to handle the split view action.
1468         """
1469         self.addSplit()
1470         
1471     def handleSplitOrientation(self):
1472         """
1473         Private method to handle the split orientation action.
1474         """
1475         if self.splitOrientationAct.isOn():
1476             self.setSplitOrientation(QSplitter.Horizontal)
1477             self.splitViewAct.setIconSet(\
1478                 QIconSet(utilIcons.getPixmap("splitHorizontal.png")))
1479             self.splitRemoveAct.setIconSet(\
1480                 QIconSet(utilIcons.getPixmap("remsplitHorizontal.png")))
1481         else:
1482             self.setSplitOrientation(QSplitter.Vertical)
1483             self.splitViewAct.setIconSet(\
1484                 QIconSet(utilIcons.getPixmap("splitVertical.png")))
1485             self.splitRemoveAct.setIconSet(\
1486                 QIconSet(utilIcons.getPixmap("remsplitVertical.png")))
1487     
1488     ##################################################################
1489     ## Below are the action methods for the macro menu
1490     ##################################################################
1491     
1492     def handleMacroStartRecording(self):
1493         """
1494         Private method to handle the start macro recording action.
1495         """
1496         self.activeWindow().handleStartMacroRecording()
1497         
1498     def handleMacroStopRecording(self):
1499         """
1500         Private method to handle the stop macro recording action.
1501         """
1502         self.activeWindow().handleStopMacroRecording()
1503         
1504     def handleMacroRun(self):
1505         """
1506         Private method to handle the run macro action.
1507         """
1508         self.activeWindow().handleRunMacro()
1509         
1510     def handleMacroDelete(self):
1511         """
1512         Private method to handle the delete macro action.
1513         """
1514         self.activeWindow().handleDeleteMacro()
1515         
1516     def handleMacroLoad(self):
1517         """
1518         Private method to handle the load macro action.
1519         """
1520         self.activeWindow().handleLoadMacro()
1521         
1522     def handleMacroSave(self):
1523         """
1524         Private method to handle the save macro action.
1525         """
1526         self.activeWindow().handleSaveMacro()
1527     
1528     ##################################################################
1529     ## Below are the action methods for the bookmarks menu
1530     ##################################################################
1531     
1532     def handleToggleBookmark(self):
1533         """
1534         Private method to handle the toggle bookmark action.
1535         """
1536         self.activeWindow().handleToggleBookmark()
1537         
1538     def handleNextBookmark(self):
1539         """
1540         Private method to handle the next bookmark action.
1541         """
1542         self.activeWindow().handleNextBookmark()
1543     
1544     def handlePreviousBookmark(self):
1545         """
1546         Private method to handle the previous bookmark action.
1547         """
1548         self.activeWindow().handlePreviousBookmark()
1549     
1550     def handleClearAllBookmarks(self):
1551         """
1552         Private method to handle the clear all bookmarks action.
1553         """
1554         for editor in self.editors:
1555             editor.handleClearBookmarks()
1556             
1557         self.bookmarkNextAct.setEnabled(0)
1558         self.bookmarkPreviousAct.setEnabled(0)
1559         self.bookmarkClearAct.setEnabled(0)
1560     
1561     def handleShowBookmarksMenu(self):
1562         """
1563         Private method to handle the show bookmarks menu signal.
1564         """
1565         self.bookmarks = {}
1566         self.bookmarksMenu.clear()
1567         
1568         filenames = self.getOpenFilenames()
1569         filenames.sort()
1570         for filename in filenames:
1571             editor = self.getOpenEditor(filename)
1572             for bookmark in editor.getBookmarks():
1573                 if len(filename) > 50:
1574                     dots = "..."
1575                 else:
1576                     dots = ""
1577                 id = self.bookmarksMenu.insertItem(\
1578                         "%s%s : %d" % (dots, filename[-50:], bookmark))
1579                 self.bookmarks[id] = (filename, bookmark)
1580     
1581     def handleBookmarkSelected(self, id):
1582         """
1583         Private method to handle the bookmark selected signal.
1584         
1585         @param id index of the selected menu entry
1586                 This acts as an index into the list of bookmarks
1587                 that was created, when the bookmarks menu was built.
1588         """
1589         self.displayPythonFile(self.bookmarks[id][0], self.bookmarks[id][1])
1590         
1591     def handleBookmarkToggled(self, editor):
1592         """
1593         Private slot to handle the bookmarkToggled signal.
1594         
1595         It checks some bookmark actions and reemits the signal.
1596         
1597         @param editor editor that sent the signal
1598         """
1599         if editor.hasBookmarks():
1600             self.bookmarkNextAct.setEnabled(1)
1601             self.bookmarkPreviousAct.setEnabled(1)
1602             self.bookmarkClearAct.setEnabled(1)
1603         else:
1604             self.bookmarkNextAct.setEnabled(0)
1605             self.bookmarkPreviousAct.setEnabled(0)
1606             self.bookmarkClearAct.setEnabled(0)
1607         self.emit(PYSIGNAL('bookmarkToggled'), (editor,))
1608     
1609     def handleGotoSyntaxError(self):
1610         """
1611         Private method to handle the goto syntax error action.
1612         """
1613         self.activeWindow().handleGotoSyntaxError()
1614     
1615     def handleClearAllSyntaxErrors(self):
1616         """
1617         Private method to handle the clear all syntax errors action.
1618         """
1619         for editor in self.editors:
1620             editor.handleClearSyntaxError()
1621     
1622     def handleSyntaxErrorToggled(self, editor):
1623         """
1624         Private slot to handle the syntaxerrorToggled signal.
1625         
1626         It checks some syntax error actions and reemits the signal.
1627         
1628         @param editor editor that sent the signal
1629         """
1630         if editor.hasSyntaxErrors():
1631             self.syntaxErrorGotoAct.setEnabled(1)
1632             self.syntaxErrorClearAct.setEnabled(1)
1633         else:
1634             self.syntaxErrorGotoAct.setEnabled(0)
1635             self.syntaxErrorClearAct.setEnabled(0)
1636         self.emit(PYSIGNAL('syntaxerrorToggled'), (editor,))
1637     
1638     ##################################################################
1639     ## Below are general utility methods
1640     ##################################################################
1641     
1642     def handleResetUI(self):
1643         """
1644         Public slot to handle the resetUI signal.
1645         """
1646         editor = self.activeWindow()
1647         if editor is None:
1648             self.setSbFile()
1649         else:
1650             line, pos = editor.getCursorPosition()
1651             self.setSbFile(editor.getFileName(), line+1, pos)
1652         
1653     def closeViewManager(self):
1654         """
1655         Public method to shutdown the viewmanager. 
1656         
1657         If it cannot close all editor windows, it aborts the shutdown process.
1658         
1659         @return flag indicating success (boolean)
1660         """
1661         self.handleCloseAll()
1662         if len(self.editors):
1663             return 0
1664         else:
1665             return 1
1666
1667     def handleLastEditorClosed(self):
1668         """
1669         Private slot to handle the lastEditorClosed signal.
1670         """
1671         self.SauveRecents() 
1672         
1673         
1674     def handleEditorOpened(self):
1675         """
1676         Private slot to handle the editorOpened signal.
1677         """
1678         self.closeActGrp.setEnabled(1)
1679         self.saveActGrp.setEnabled(1)
1680         self.printAct.setEnabled(1)
1681         self.printSelAct.setEnabled(1)
1682         self.editActGrp.setEnabled(1)
1683         self.searchActGrp.setEnabled(1)
1684         self.viewActGrp.setEnabled(1)
1685         self.viewFoldActGrp.setEnabled(1)
1686         self.unhighlightAct.setEnabled(1)
1687         self.splitViewAct.setEnabled(1)
1688         self.splitOrientationAct.setEnabled(1)
1689         self.macroActGrp.setEnabled(1)
1690         self.bookmarkActGrp.setEnabled(1)
1691         
1692         # activate the autosave timer
1693         if not self.autosaveTimer.isActive() and \
1694            self.autosaveInterval > 0:
1695             self.autosaveTimer.start(self.autosaveInterval * 60000, 1)
1696         
1697         
1698     def checkActions(self, editor, setSb=1):
1699         """
1700         Private slot to check some actions for their enable/disable status and set the statusbar info.
1701         
1702         @param editor editor window
1703         @param setSb flag indicating an update of the status bar is wanted (boolean)
1704         """
1705         if editor is not None:
1706             self.saveAct.setEnabled(editor.modified)
1707             self.revertAct.setEnabled(editor.modified)
1708             
1709             lex = editor.getLexer()
1710             if lex is not None:
1711                 self.commentAct.setEnabled(lex.canBlockComment())
1712                 self.uncommentAct.setEnabled(lex.canBlockComment())
1713                 self.streamCommentAct.setEnabled(lex.canStreamComment())
1714                 self.boxCommentAct.setEnabled(lex.canBoxComment())
1715             else:
1716                 self.commentAct.setEnabled(0)
1717                 self.uncommentAct.setEnabled(0)
1718                 self.streamCommentAct.setEnabled(0)
1719                 self.boxCommentAct.setEnabled(0)
1720             
1721             if editor.hasBookmarks():
1722                 self.bookmarkNextAct.setEnabled(1)
1723                 self.bookmarkPreviousAct.setEnabled(1)
1724                 self.bookmarkClearAct.setEnabled(1)
1725             else:
1726                 self.bookmarkNextAct.setEnabled(0)
1727                 self.bookmarkPreviousAct.setEnabled(0)
1728                 self.bookmarkClearAct.setEnabled(0)
1729             
1730             if editor.hasSyntaxErrors():
1731                 self.syntaxErrorGotoAct.setEnabled(1)
1732                 self.syntaxErrorClearAct.setEnabled(1)
1733             else:
1734                 self.syntaxErrorGotoAct.setEnabled(0)
1735                 self.syntaxErrorClearAct.setEnabled(0)
1736             
1737             if editor.canAutoCompleteFromAPIs():
1738                 self.autoCompleteFromAPIsAct.setEnabled(1)
1739             else:
1740                 self.autoCompleteFromAPIsAct.setEnabled(0)
1741                 
1742             if setSb:
1743                 line, pos = editor.getCursorPosition()
1744                 self.setSbFile(editor.getFileName(), line+1, pos)
1745                 
1746             self.emit(PYSIGNAL('checkActions'), (editor,))
1747         
1748     def handlePreferencesChanged(self):
1749         """
1750         Public slot to handle the preferencesChanged signal.
1751         
1752         This method performs the following actions
1753             <ul>
1754             <li>reread the colours for the syntax highlighting</li>
1755             <li>reloads the already created API objetcs</li>
1756             <li>starts or stops the autosave timer</li>
1757             <li><b>Note</b>: changes in viewmanager type are activated
1758               on an application restart.</li>
1759             </ul>
1760         """
1761         # reload api information
1762         for language, api in self.apis.items():
1763             if api is not None:
1764                 apifiles = Preferences.getEditorAPI(language)
1765                 if len(apifiles):
1766                     api.clear()
1767                     for apifile in apifiles:
1768                         api.load(apifile)
1769                 else:
1770                     self.apis[language] = None
1771                     
1772         # reload editor settings
1773         for editor in self.editors:
1774             editor.readSettings()
1775             
1776         # reload the autosave timer setting
1777         self.autosaveInterval = Preferences.getEditor("AutosaveInterval")
1778         if len(self.editors):
1779             if self.autosaveTimer.isActive() and \
1780                self.autosaveInterval == 0:
1781                 self.autosaveTimer.stop()
1782             elif not self.autosaveTimer.isActive() and \
1783                self.autosaveInterval > 0:
1784                 self.autosaveTimer.start(self.autosaveInterval * 60000, 1)
1785         
1786     def handleEditorSaved(self, fn):
1787         """
1788         Public slot to handle the editorSaved signal.
1789         
1790         It simply reemits the signal.
1791         
1792         @param fn filename of the saved editor
1793         """
1794         self.emit(PYSIGNAL('editorSaved'), (fn,))
1795         
1796     def handleCursorChanged(self, fn, line, pos):
1797         """
1798         Private slot to handle the cursorChanged signal. 
1799         
1800         It emits the signal cursorChanged with parameter editor.
1801         
1802         @param fn filename (string)
1803         @param line line number of the cursor (int)
1804         @param pos position in line of the cursor (int)
1805         """
1806         self.setSbFile(fn, line, pos)
1807         self.emit(PYSIGNAL('cursorChanged'), (self.getOpenEditor(fn),))
1808         
1809     def handleBreakpointToggled(self, editor):
1810         """
1811         Private slot to handle the breakpointToggled signal.
1812         
1813         It simply reemits the signal.
1814         
1815         @param editor editor that sent the signal
1816         """
1817         self.emit(PYSIGNAL('breakpointToggled'), (editor,))
1818         
1819             
1820     def getProject(self):
1821         """
1822         Public method to get a reference to the Project object.
1823         
1824         @return Reference to the Project object (Project.Project)
1825         """
1826         return self.ui.getProject()
1827         
1828     def getActions(self, type):
1829         """
1830         Public method to get a list of all actions.
1831         
1832         @param type string denoting the action set to get.
1833                 It must be one of "edit", "file", "search",
1834                 "view" or "window"
1835         @return list of all actions (list of QAction)
1836         """
1837         try:
1838             exec 'actionList = self.%sActions[:]' % type
1839         except:
1840             actionList = []
1841                 
1842         return actionList
1843         
1844     def editorCommand(self, cmd):
1845         """
1846         Private method to send an editor command to the active window.
1847         
1848         @param cmd the scintilla command to be sent
1849         """
1850         aw = self.activeWindow()
1851         if aw:
1852             aw.SendScintilla(cmd)
1853         
1854     ##################################################################
1855     ## Below are protected utility methods
1856     ##################################################################
1857     
1858     def _getOpenStartDir(self):
1859         """
1860         Protected method to return the starting directory for a file open dialog. 
1861         
1862         The appropriate starting directory is calculated
1863         using the following search order, until a match is found:<br />
1864             1: Directory of currently active editor<br />
1865             2: Directory of currently active Project<br />
1866             3: CWD
1867
1868         @return String name of directory to start or None
1869         """
1870         # if we have an active source, return its path
1871         if self.activeWindow() is not None and \
1872            self.activeWindow().getFileName():
1873             return os.path.dirname(self.activeWindow().getFileName())
1874             
1875         # ok, try if there is an active project and return its path
1876         elif self.getProject().isOpen():
1877             return self.getProject().ppath
1878             
1879         else:
1880             try :
1881                userDir=os.path.expanduser("~/Eficas_install/")
1882                return userDir
1883             except :
1884                return ""        
1885
1886
1887     def _getOpenFileFilter(self):
1888         """
1889         Protected method to return the active filename filter for a file open dialog.
1890         
1891         The appropriate filename filter is determined by file extension of
1892         the currently active editor.
1893         
1894         @return name of the filename filter (QString) or None
1895         """
1896         if self.activeWindow() is not None and \
1897            self.activeWindow().getFileName():
1898             ext = os.path.splitext(self.activeWindow().getFileName())[1]
1899             try:
1900                 return QString(self.ext2Filter[ext])
1901             except KeyError:
1902                 return None
1903                 
1904         else:
1905             return None
1906
1907             
1908
1909
1910 """
1911 Module implementing a tabbed viewmanager class.
1912 """
1913
1914
1915
1916 class TabWidget(QTabWidget):
1917     """
1918     Class implementing a custimized TabWidget.
1919     """
1920     def __init__(self, parent):
1921         """
1922         Constructor
1923         
1924         @param parent parent widget (QWidget)
1925         """
1926         QTabWidget.__init__(self, parent)
1927         
1928         self.editors = []
1929         self.curIndex = 0
1930         
1931         self.connect(self, SIGNAL("currentChanged(QWidget *)"), self.handleCurrentChanged)
1932         
1933     def handleCurrentChanged(self):
1934         """
1935         Private slot called by the currentChanged signal.
1936         """
1937         self.curIndex = self.currentPageIndex()
1938         
1939     def addTab(self, editor, title):
1940         """
1941         Overwritten method to add a new tab.
1942         
1943         @param editor the editor object to be added (QScintilla.Editor.Editor)
1944         @param title title for the new tab (string, QString or QTab)
1945         """
1946         QTabWidget.addTab(self, editor, title)
1947         
1948         if not editor in self.editors:
1949             self.editors.append(editor)
1950             self.connect(editor, PYSIGNAL('captionChanged'),
1951                 self.handleCaptionChange)
1952                 
1953     def showPage(self, editor):
1954         """
1955         Overridden method to show a tab.
1956         
1957         @param editor the editor object to be shown (QScintilla.Editor.Editor)
1958         """
1959         QTabWidget.showPage(self, editor)
1960         self.curIndex = self.indexOf(editor)
1961         
1962     def nextTab(self):
1963         """
1964         Public slot used to show the next tab.
1965         """
1966         if self.count():
1967             self.curIndex += 1
1968             if self.curIndex == self.count():
1969                 self.curIndex = 0
1970                 
1971             QTabWidget.showPage(self, self.page(self.curIndex))
1972
1973     def prevTab(self):
1974         """
1975         Public slot used to show the previous tab.
1976         """
1977         if self.count():
1978             self.curIndex -= 1
1979             if self.curIndex == -1:
1980                 self.curIndex = self.count() - 1
1981                 
1982             QTabWidget.showPage(self, self.page(self.curIndex))
1983
1984     def handleCaptionChange(self, cap, editor):
1985         """
1986         Private method to handle Caption change signals from the editor. 
1987         
1988         Updates the listview text to reflect the new caption information.
1989         
1990         @param cap Caption for the editor
1991         @param editor Editor to update the caption for
1992         """
1993         fn = editor.getFileName()
1994         if fn:
1995             txt = os.path.basename(fn)
1996             if editor.isReadOnly():
1997                 txt = '%s (ro)' % txt
1998             self.changeTab(editor, txt)
1999         
2000     def removePage(self, object):
2001         """
2002         Overwritten method to remove a page.
2003         
2004         @param object object to be removed (QObject)
2005         """
2006         QTabWidget.removePage(self, object)
2007         
2008         self.disconnect( object, PYSIGNAL('captionChanged'),
2009                          self.handleCaptionChange )
2010         self.editors.remove(object)
2011         
2012     def hasEditor(self, editor):
2013         """
2014         Public method to check for an editor.
2015         
2016         @param editor editor object to check for
2017         @return flag indicating, whether the editor to be checked belongs
2018             to the list of editors managed by this tab widget.
2019         """
2020         return editor in self.editors
2021         
2022     def hasEditors(self):
2023         """
2024         Public method to test, if any editor is managed.
2025         
2026         @return flag indicating editors are managed
2027         """
2028         return len(self.editors) and 1 or 0
2029         
2030 class Tabview(QSplitter, ViewManager):
2031     """
2032     Class implementing a tabbed viewmanager class embedded in a splitter.
2033     
2034     @signal lastEditorClosed emitted after the last editor window was closed
2035     @signal editorOpened emitted after an editor window was opened
2036     @signal editorSaved emitted after an editor window was saved
2037     """
2038     def __init__(self,parent, ui):
2039         """
2040         Constructor
2041         
2042         @param parent parent widget (QWidget)
2043         @param ui reference to the main user interface
2044         @param dbs reference to the debug server object
2045         """
2046         self.tabWidgets = []
2047         
2048         QSplitter.__init__(self,parent)
2049         ViewManager.__init__(self, ui)
2050         tw = TabWidget(self)
2051         self.tabWidgets.append(tw)
2052         self.currentTabWidget = tw
2053         self.connect(tw, SIGNAL('currentChanged(QWidget*)'),
2054             self.handleCurrentChanged)
2055         tw.installEventFilter(self)
2056         tw.tabBar().installEventFilter(self)
2057         self.setOrientation(QSplitter.Vertical)
2058         
2059     def initViewActions(self):
2060         """
2061         Protected method defining the user interface actions for the view commands.
2062         """
2063         ViewManager.initViewActions(self)
2064         
2065         self.nextTabAct = QAction(self.trUtf8('Show next tab'), 
2066                       self.trUtf8('Show next tab'), 
2067                       QKeySequence(self.trUtf8('Ctrl+Alt+Tab')), self)
2068         self.connect(self.nextTabAct, SIGNAL('activated()'), self.nextTab)
2069         self.viewActions.append(self.nextTabAct)
2070         
2071         self.prevTabAct = QAction(self.trUtf8('Show previous tab'), 
2072                       self.trUtf8('Show previous tab'), 
2073                       QKeySequence(self.trUtf8('Shift+Ctrl+Alt+Tab')), self)
2074         self.connect(self.prevTabAct, SIGNAL('activated()'), self.prevTab)
2075         self.viewActions.append(self.prevTabAct)
2076         
2077     def nextTab(self):
2078         """
2079         Private slot used to show the next tab of the current tabwidget.
2080         """
2081         self.currentTabWidget.nextTab()
2082         
2083     def prevTab(self):
2084         """
2085         Private slot used to show the previous tab of the current tabwidget.
2086         """
2087         self.currentTabWidget.prevTab()
2088         
2089     def canCascade(self):
2090         """
2091         Public method to signal if cascading of managed windows is available.
2092         
2093         @return flag indicating cascading of windows is available
2094         """
2095         return 0
2096         
2097     def canTile(self):
2098         """
2099         Public method to signal if tiling of managed windows is available.
2100         
2101         @return flag indicating tiling of windows is available
2102         """
2103         return 0
2104         
2105     def canSplit(self):
2106         """
2107         public method to signal if splitting of the view is available.
2108         
2109         @return flag indicating splitting of the view is available.
2110         """
2111         return 1
2112         
2113     def tile(self):
2114         """
2115         Public method to tile the managed windows.
2116         """
2117         pass
2118         
2119     def cascade(self):
2120         """
2121         Public method to cascade the managed windows.
2122         """
2123         pass
2124         
2125     def removeAllViews(self):
2126         """
2127         Private method to remove all views (i.e. windows)
2128         """
2129         for win in self.editors:
2130             self.removeView(win)
2131             
2132     def removeView(self, win):
2133         """
2134         Private method to remove a view (i.e. window)
2135         
2136         @param win editor window to be removed
2137         """
2138         for tw in self.tabWidgets:
2139             if tw.hasEditor(win):
2140                 tw.removePage(win)
2141                 break        
2142         win.closeIt()        
2143         
2144         # if this was the last editor in this view, switch to the next, that
2145         # still has open editors
2146         for i in range(self.tabWidgets.index(tw), -1, -1) + \
2147                  range(self.tabWidgets.index(tw) + 1, len(self.tabWidgets)):
2148             if self.tabWidgets[i].hasEditors():
2149                 self.currentTabWidget = self.tabWidgets[i]
2150                 self.activeWindow().setFocus()
2151                 break
2152     
2153     def addView(self, win, fn=None, title=None):
2154         """
2155         Private method to add a view (i.e. window)
2156         
2157         @param win editor window to be added
2158         @param fn filename of this editor
2159         """
2160         win.show()
2161         if fn is None:
2162             if title== None : 
2163                self.untitledCount += 1
2164                self.currentTabWidget.addTab(win, self.trUtf8("Untitled %1").arg(self.untitledCount))
2165             else :
2166                self.currentTabWidget.addTab(win, title)
2167         else:
2168             txt = os.path.basename(fn)
2169             if not QFileInfo(fn).isWritable():
2170                 txt = '%s (ro)' % txt
2171             self.currentTabWidget.addTab(win, txt)
2172             self.currentTabWidget.setTabToolTip(win, os.path.dirname(fn))
2173         self.currentTabWidget.showPage(win)
2174         win.setFocus()
2175     
2176     def showView(self, win, fn=None):
2177         """
2178         Private method to show a view (i.e. window)
2179         
2180         @param win editor window to be shown
2181         @param fn filename of this editor
2182         """
2183         win.show()
2184         for tw in self.tabWidgets:
2185             if tw.hasEditor(win):
2186                 tw.showPage(win)
2187                 self.currentTabWidget = tw
2188                 break
2189         win.setFocus()
2190     
2191     def activeWindow(self):
2192         """
2193         Private method to return the active (i.e. current) window.
2194         
2195         @return reference to the active editor
2196         """
2197         return self.currentTabWidget.currentPage()
2198         
2199     def handleShowWindowMenu(self, windowMenu):
2200         """
2201         Private method to set up the viewmanager part of the Window menu.
2202         
2203         @param windowMenu reference to the window menu
2204         """
2205         pass
2206         
2207     def initWindowActions(self):
2208         """
2209         Define the user interface actions for window handling.
2210         """
2211         pass
2212         
2213     def setEditorName(self, editor, newName):
2214         """
2215         Change the displayed name of the editor.
2216         
2217         @param editor editor window to be changed
2218         @param newName new name to be shown (string or QString)
2219         """
2220         self.currentTabWidget.changeTab(editor, 
2221             os.path.basename(unicode(newName)))
2222         self.currentTabWidget.setTabToolTip(editor, 
2223             os.path.dirname(unicode(newName)))
2224     
2225     def handleModificationStatusChanged(self, m, editor):
2226         """
2227         Private slot to handle the modificationStatusChanged signal.
2228         
2229         @param m flag indicating the modification status (boolean)
2230         @param editor editor window changed
2231         """
2232         for tw in self.tabWidgets:
2233             if tw.hasEditor(editor):
2234                 break
2235         if m:
2236             tw.setTabIconSet(editor, 
2237                 QIconSet(utilIcons.getPixmap("fileModified.png")))
2238         elif editor.hasSyntaxErrors():
2239             tw.setTabIconSet(editor, 
2240                 QIconSet(utilIcons.getPixmap("syntaxError.png")))
2241         else:
2242             tw.setTabIconSet(editor, 
2243                 QIconSet(utilIcons.getPixmap("empty.png")))
2244         self.checkActions(editor)
2245         
2246     def handleSyntaxErrorToggled(self, editor):
2247         """
2248         Private slot to handle the syntaxerrorToggled signal.
2249         
2250         @param editor editor that sent the signal
2251         """
2252         for tw in self.tabWidgets:
2253             if tw.hasEditor(editor):
2254                 break
2255         if editor.hasSyntaxErrors():
2256             tw.setTabIconSet(editor, 
2257                 QIconSet(utilIcons.getPixmap("syntaxError.png")))
2258         else:
2259             tw.setTabIconSet(editor, 
2260                 QIconSet(utilIcons.getPixmap("empty.png")))
2261                 
2262         ViewManager.handleSyntaxErrorToggled(self, editor)
2263         
2264     def addSplit(self):
2265         """
2266         Public method used to split the current view.
2267         """
2268         tw = TabWidget(self)
2269         tw.show()
2270         self.tabWidgets.append(tw)
2271         self.currentTabWidget = self.tabWidgets[-1]
2272         self.connect(tw, SIGNAL('currentChanged(QWidget*)'),
2273             self.handleCurrentChanged)
2274         tw.installEventFilter(self)
2275         tw.tabBar().installEventFilter(self)
2276         self.setSizes([int(100/len(self.tabWidgets))] * len(self.tabWidgets))
2277         self.splitRemoveAct.setEnabled(1)
2278         
2279     def removeSplit(self):
2280         """
2281         Public method used to remove the current split view.
2282         
2283         @return flag indicating successfull removal
2284         """
2285         if len(self.tabWidgets) > 1:
2286             tw = self.currentTabWidget
2287             res = 1
2288             savedEditors = tw.editors[:]
2289             for editor in savedEditors:
2290                 res &= self.closeEditor(editor)
2291             if res:
2292                 i = self.tabWidgets.index(tw)
2293                 if i == len(self.tabWidgets)-1:
2294                     i -= 1
2295                 self.tabWidgets.remove(tw)
2296                 tw.close(1)
2297                 self.currentTabWidget = self.tabWidgets[i]
2298                 if len(self.tabWidgets) == 1:
2299                     self.splitRemoveAct.setEnabled(0)
2300                 return 1
2301                 
2302         return 0
2303         
2304     def setSplitOrientation(self, orientation):
2305         """
2306         Public method used to set the orientation of the split view.
2307         
2308         @param orientation orientation of the split
2309                 (QSplitter.Horizontal or QSplitter.Vertical)
2310         """
2311         self.setOrientation(orientation)
2312         
2313     def handleCurrentChanged(self, editor):
2314         """
2315         Private slot to handle the currentChanged signal.
2316         
2317         @param editor selected editor window
2318         """
2319         self.checkActions(editor)
2320         editor.setFocus()
2321         
2322     def eventFilter(self, watched, event):
2323         """
2324         Method called to filter the event queue.
2325         
2326         @param watched the QObject being watched
2327         @param event the event that occurred
2328         @return always 0
2329         """
2330         if event.type() == QEvent.MouseButtonPress and \
2331            not event.button() == Qt.RightButton:
2332             if isinstance(watched, QTabWidget):
2333                 self.currentTabWidget = watched
2334             elif isinstance(watched, QTabBar):
2335                 self.currentTabWidget = watched.parent()
2336             elif isinstance(watched, QScintilla.Editor.Editor):
2337                 for tw in self.tabWidgets:
2338                     if tw.hasEditor(watched):
2339                         self.currentTabWidget = tw
2340                         break
2341                         
2342             aw = self.activeWindow()
2343             if aw is not None:
2344                 self.checkActions(aw)
2345                 aw.setFocus()
2346             
2347         return 0
2348
2349
2350 class MyTabview(Tabview):
2351     """
2352     Base class inherited by all specific viewmanager classes.
2353     
2354     It defines the interface to be implemented by specific
2355     viewmanager classes and all common methods.
2356     
2357     @signal lastEditorClosed emitted after the last editor window was closed
2358     @signal editorOpened(string) emitted after an editor window was opened
2359     @signal editorSaved(string) emitted after an editor window was saved
2360     @signal checkActions(editor) emitted when some actions should be checked
2361             for their status
2362     @signal cursorChanged(editor) emitted after the cursor position of the active
2363             window has changed
2364     @signal breakpointToggled(editor) emitted when a breakpoint is toggled.
2365     @signal bookmarkToggled(editor) emitted when a bookmark is toggled.
2366     """
2367     def __init__(self, parent, ui):
2368         Tabview.__init__(self, parent, ui)
2369         self.appli=parent
2370         self.code =self.appli.code
2371         self.salome=self.appli.salome
2372         self.initRecent()
2373
2374     def initRecent(self) :
2375        rep=self.appli.CONFIGURATION.rep_user
2376        monFichier=rep+"/listefichiers_"+self.code
2377        index=0
2378        try :
2379            f=open(monFichier)
2380            while ( index < 9) :
2381               ligne=f.readline()
2382               if ligne != "" :
2383                  l=(ligne.split("\n"))[0]
2384                  self.recent.append(l)
2385               index=index+1
2386        except : pass
2387
2388        try    : f.close()
2389        except : pass
2390         
2391     def SauveRecents(self) :
2392        rep=self.appli.CONFIGURATION.rep_user
2393        monFichier=rep+"/listefichiers_"+self.code
2394        try :
2395             f=open(monFichier,'w')
2396             if len(self.recent) == 0 : return
2397             index=0
2398             while ( index <  len(self.recent)):
2399               ligne=str(self.recent[index])+"\n"
2400               f.write(ligne)
2401               index=index+1
2402        except :
2403             pass
2404        try :
2405             f.close()
2406        except :
2407             pass
2408
2409
2410     def checkActions(self, editor, setSb=1):
2411         """
2412         Private slot to check some actions for their enable/disable status and set the statusbar info.
2413         
2414         @param editor editor window
2415         @param setSb flag indicating an update of the status bar is wanted (boolean)
2416         """        
2417         self.emit(PYSIGNAL('checkActions'), (editor,)) 
2418  
2419
2420     def addToRecentList(self, fn):
2421         """
2422         Public slot to add a filename to the list of recently opened files.
2423         
2424         @param fn name of the file to be added
2425         """
2426         self.recent.remove(fn)
2427         self.recent.prepend(fn)
2428         if len(self.recent) > 9:
2429             self.recent = self.recent[:9] 
2430         
2431     def handleOpen(self,fn=None,patron=0,units=None):
2432         """
2433         Public slot to open a Python JDC file.
2434         
2435         @param prog name of file to be opened (string or QString)
2436                patron booleen pour indiquer si le fichier doit etre
2437                       ajoute a la liste des fichiers ouverts recemment
2438         """
2439         # Get the file name if one wasn't specified.
2440         if fn is None:
2441
2442             fn = QFileDialog.getOpenFileName(self._getOpenStartDir(),
2443                         self.trUtf8('JDC Files (*.comm);;''All Files (*)'), self.ui)
2444
2445             if fn.isNull():
2446                 return
2447
2448         fn = normabspath(unicode(fn))
2449
2450         newWin, editor = self.getEditor(fn,units=units)
2451         
2452         if newWin:
2453             self.handleModificationStatusChanged(editor.modified, editor)
2454         self.checkActions(editor)
2455         
2456         # insert filename into list of recently opened files
2457         if patron == 0 : self.addToRecentList(fn)
2458     
2459
2460    ##################################################################
2461    ## Below are protected utility methods
2462    #################################################################
2463     
2464     def _getOpenStartDir(self):
2465         """
2466         Protected method to return the starting directory for a file open dialog. 
2467         
2468         The appropriate starting directory is calculated
2469         using the following search order, until a match is found:<br />
2470             1: Directory of currently active editor<br />
2471             2: Directory of currently active Project<br />
2472             3: CWD
2473
2474         @return String name of directory to start or None
2475         """
2476         # if we have an active source, return its path
2477         if self.activeWindow() is not None and \
2478            self.activeWindow().getFileName():
2479             return os.path.dirname(self.activeWindow().getFileName())
2480             
2481             
2482         else:
2483             # None will cause open dialog to start with cwd
2484             try :
2485                userDir=os.path.expanduser("~/Eficas_install/")
2486                return userDir
2487             except :
2488                return ""        
2489
2490
2491     def handleEditorOpened(self):
2492         """
2493         Private slot to handle the editorOpened signal.
2494         """
2495         pass
2496         
2497     def handleModificationStatusChanged(self, m, editor):
2498         """
2499         Private slot to handle the modificationStatusChanged signal.
2500         
2501         @param m flag indicating the modification status (boolean)
2502         @param editor editor window changed
2503         """
2504         for tw in self.tabWidgets:
2505             if tw.hasEditor(editor):
2506                 break
2507         if m:
2508             #tw.setTabIconSet(editor, 
2509             #    QIconSet(utilIcons.getPixmap("fileModified.png")))
2510             pass
2511         elif editor.hasSyntaxErrors():
2512             tw.setTabIconSet(editor, 
2513                 QIconSet(utilIcons.getPixmap("syntaxError.png")))
2514         else:
2515             tw.setTabIconSet(editor, 
2516                 QIconSet(utilIcons.getPixmap("empty.png")))
2517         self.checkActions(editor)        
2518         
2519         
2520
2521
2522 if __name__=='__main__':
2523     import sys
2524     import prefs 
2525     if hasattr(prefs,'encoding'):
2526        # Hack pour changer le codage par defaut des strings
2527        import sys
2528        reload(sys)
2529        sys.setdefaultencoding(prefs.encoding)
2530        del sys.setdefaultencoding
2531        # Fin hack
2532
2533     #CS_pbruno note: fait implicitement des trucs ces imports (grr)
2534     #import styles
2535     from Editeur import import_code
2536     from Editeur import session
2537
2538     # Analyse des arguments de la ligne de commande
2539     options=session.parse(sys.argv)
2540     code=options.code    
2541     app = QApplication(sys.argv)
2542     
2543     mw = MyTabview(None,None)
2544     app.setMainWidget(mw)
2545     app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
2546     mw.show()
2547     mw.getEditor('azAster.comm')
2548     mw.getEditor('azAster2.comm')
2549     res = app.exec_loop()
2550     sys.exit(res)