6 """ |
6 """ |
7 Module implementing the viewmanager base class. |
7 Module implementing the viewmanager base class. |
8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 import re |
|
12 |
11 |
13 from PyQt4.QtCore import QSignalMapper, QTimer, QFileInfo, pyqtSignal, QRegExp, \ |
12 from PyQt4.QtCore import QSignalMapper, QTimer, QFileInfo, pyqtSignal, QRegExp, \ |
14 QObject, Qt, QUrl |
13 QObject, Qt |
15 from PyQt4.QtGui import QColor, QKeySequence, QLineEdit, QToolBar, QWidgetAction, \ |
14 from PyQt4.QtGui import QColor, QKeySequence, QLineEdit, QToolBar, QWidgetAction, \ |
16 QDialog, QApplication, QMenu, QPalette, QComboBox, QPixmap |
15 QDialog, QApplication, QMenu, QPalette, QComboBox, QPixmap |
17 from PyQt4.Qsci import QsciScintilla |
16 from PyQt4.Qsci import QsciScintilla |
18 |
17 |
19 from E5Gui.E5Application import e5App |
18 from E5Gui.E5Application import e5App |
88 Base class inherited by all specific viewmanager classes. |
87 Base class inherited by all specific viewmanager classes. |
89 |
88 |
90 It defines the interface to be implemented by specific |
89 It defines the interface to be implemented by specific |
91 viewmanager classes and all common methods. |
90 viewmanager classes and all common methods. |
92 |
91 |
|
92 @signal changeCaption(str) emitted if a change of the caption is necessary |
|
93 @signal editorChanged(str) emitted when the current editor has changed |
|
94 @signal editorChangedEd(Editor) emitted when the current editor has changed |
93 @signal lastEditorClosed() emitted after the last editor window was closed |
95 @signal lastEditorClosed() emitted after the last editor window was closed |
94 @signal editorOpened(str) emitted after an editor window was opened |
96 @signal editorOpened(str) emitted after an editor window was opened |
95 @signal editorOpenedEd(Editor) emitted after an editor window was opened |
97 @signal editorOpenedEd(Editor) emitted after an editor window was opened |
96 @signal editorClosed(str) emitted just before an editor window gets closed |
98 @signal editorClosed(str) emitted just before an editor window gets closed |
97 @signal editorClosedEd(Editor) emitted just before an editor window gets closed |
99 @signal editorClosedEd(Editor) emitted just before an editor window gets closed |
98 @signal editorSaved(str) emitted after an editor window was saved |
100 @signal editorSaved(str) emitted after an editor window was saved |
99 @signal checkActions(Editor) emitted when some actions should be checked |
101 @signal checkActions(Editor) emitted when some actions should be checked |
100 for their status |
102 for their status |
101 @signal cursorChanged(Editor) emitted after the cursor position of the active |
103 @signal cursorChanged(Editor) emitted after the cursor position of the active |
102 window has changed |
104 window has changed |
103 @signal breakpointToggled(Editor) emitted when a breakpoint is toggled. |
105 @signal breakpointToggled(Editor) emitted when a breakpoint is toggled |
104 @signal bookmarkToggled(Editor) emitted when a bookmark is toggled. |
106 @signal bookmarkToggled(Editor) emitted when a bookmark is toggled |
|
107 @signal syntaxerrorToggled(Editor) emitted when a syntax error is toggled |
|
108 @signal previewStateChanged(bool) emitted to signal a change in the preview state |
|
109 @signal editorLanguageChanged(Editor) emitted to signal a change of an |
|
110 editor's language |
|
111 @signal editorTextChanged(Editor) emitted to signal a change of an editor's text |
105 """ |
112 """ |
|
113 changeCaption = pyqtSignal(str) |
|
114 editorChanged = pyqtSignal(str) |
|
115 editorChangedEd = pyqtSignal(Editor) |
106 lastEditorClosed = pyqtSignal() |
116 lastEditorClosed = pyqtSignal() |
107 editorOpened = pyqtSignal(str) |
117 editorOpened = pyqtSignal(str) |
108 editorOpenedEd = pyqtSignal(Editor) |
118 editorOpenedEd = pyqtSignal(Editor) |
109 editorClosed = pyqtSignal(str) |
119 editorClosed = pyqtSignal(str) |
110 editorClosedEd = pyqtSignal(Editor) |
120 editorClosedEd = pyqtSignal(Editor) |
112 checkActions = pyqtSignal(Editor) |
122 checkActions = pyqtSignal(Editor) |
113 cursorChanged = pyqtSignal(Editor) |
123 cursorChanged = pyqtSignal(Editor) |
114 breakpointToggled = pyqtSignal(Editor) |
124 breakpointToggled = pyqtSignal(Editor) |
115 bookmarkToggled = pyqtSignal(Editor) |
125 bookmarkToggled = pyqtSignal(Editor) |
116 syntaxerrorToggled = pyqtSignal(Editor) |
126 syntaxerrorToggled = pyqtSignal(Editor) |
|
127 previewStateChanged = pyqtSignal(bool) |
|
128 editorLanguageChanged = pyqtSignal(Editor) |
|
129 editorTextChanged = pyqtSignal(Editor) |
117 |
130 |
118 def __init__(self): |
131 def __init__(self): |
119 """ |
132 """ |
120 Constructor |
133 Constructor |
121 """ |
134 """ |
3036 |
3049 |
3037 self.previewAct = E5Action(QApplication.translate('ViewManager', |
3050 self.previewAct = E5Action(QApplication.translate('ViewManager', |
3038 'Preview'), |
3051 'Preview'), |
3039 UI.PixmapCache.getIcon("previewer.png"), |
3052 UI.PixmapCache.getIcon("previewer.png"), |
3040 QApplication.translate('ViewManager', 'Preview'), |
3053 QApplication.translate('ViewManager', 'Preview'), |
3041 0, 0, self, 'vm_preview') |
3054 0, 0, self, 'vm_preview', True) |
3042 self.previewAct.setStatusTip(QApplication.translate('ViewManager', |
3055 self.previewAct.setStatusTip(QApplication.translate('ViewManager', |
3043 'Preview the current file in the web browser')) |
3056 'Preview the current file in the web browser')) |
3044 self.previewAct.setWhatsThis(QApplication.translate('ViewManager', |
3057 self.previewAct.setWhatsThis(QApplication.translate('ViewManager', |
3045 """<b>Preview</b>""" |
3058 """<b>Preview</b>""" |
3046 """<p>This opens the web browser with a preview of""" |
3059 """<p>This opens the web browser with a preview of""" |
3047 """ the current file.</p>""" |
3060 """ the current file.</p>""" |
3048 )) |
3061 )) |
3049 self.previewAct.triggered[()].connect(self.__previewEditor) |
3062 self.previewAct.setChecked(Preferences.getUI("ShowFilePreview")) |
|
3063 self.previewAct.toggled[bool].connect(self.__previewEditor) |
3050 self.viewActions.append(self.previewAct) |
3064 self.viewActions.append(self.previewAct) |
3051 |
3065 |
3052 self.viewActGrp.setEnabled(False) |
3066 self.viewActGrp.setEnabled(False) |
3053 self.viewFoldActGrp.setEnabled(False) |
3067 self.viewFoldActGrp.setEnabled(False) |
3054 self.unhighlightAct.setEnabled(False) |
3068 self.unhighlightAct.setEnabled(False) |
3055 self.splitViewAct.setEnabled(False) |
3069 self.splitViewAct.setEnabled(False) |
3056 self.splitOrientationAct.setEnabled(False) |
3070 self.splitOrientationAct.setEnabled(False) |
3057 self.splitRemoveAct.setEnabled(False) |
3071 self.splitRemoveAct.setEnabled(False) |
3058 self.nextSplitAct.setEnabled(False) |
3072 self.nextSplitAct.setEnabled(False) |
3059 self.prevSplitAct.setEnabled(False) |
3073 self.prevSplitAct.setEnabled(False) |
3060 self.previewAct.setEnabled(False) |
3074 self.previewAct.setEnabled(True) |
3061 |
3075 |
3062 def initViewMenu(self): |
3076 def initViewMenu(self): |
3063 """ |
3077 """ |
3064 Public method to create the View menu |
3078 Public method to create the View menu |
3065 |
3079 |
3561 'Automatic spell checking'), |
3575 'Automatic spell checking'), |
3562 UI.PixmapCache.getIcon("autospellchecking.png"), |
3576 UI.PixmapCache.getIcon("autospellchecking.png"), |
3563 QApplication.translate('ViewManager', |
3577 QApplication.translate('ViewManager', |
3564 '&Automatic spell checking'), |
3578 '&Automatic spell checking'), |
3565 0, 0, |
3579 0, 0, |
3566 self.spellingActGrp, 'vm_spelling_autospellcheck') |
3580 self.spellingActGrp, 'vm_spelling_autospellcheck', True) |
3567 self.autoSpellCheckAct.setStatusTip(QApplication.translate('ViewManager', |
3581 self.autoSpellCheckAct.setStatusTip(QApplication.translate('ViewManager', |
3568 '(De-)Activate automatic spell checking')) |
3582 '(De-)Activate automatic spell checking')) |
3569 self.autoSpellCheckAct.setWhatsThis(QApplication.translate('ViewManager', |
3583 self.autoSpellCheckAct.setWhatsThis(QApplication.translate('ViewManager', |
3570 """<b>Automatic spell checking</b>""" |
3584 """<b>Automatic spell checking</b>""" |
3571 """<p>Activate or deactivate the automatic spell checking function of""" |
3585 """<p>Activate or deactivate the automatic spell checking function of""" |
3572 """ all editors.</p>""" |
3586 """ all editors.</p>""" |
3573 )) |
3587 )) |
3574 self.autoSpellCheckAct.setCheckable(True) |
|
3575 self.autoSpellCheckAct.setChecked( |
3588 self.autoSpellCheckAct.setChecked( |
3576 Preferences.getEditor("AutoSpellCheckingEnabled")) |
3589 Preferences.getEditor("AutoSpellCheckingEnabled")) |
3577 self.autoSpellCheckAct.triggered[()].connect(self.__setAutoSpellChecking) |
3590 self.autoSpellCheckAct.triggered[()].connect(self.__setAutoSpellChecking) |
3578 self.spellingActions.append(self.autoSpellCheckAct) |
3591 self.spellingActions.append(self.autoSpellCheckAct) |
3579 |
3592 |
3870 editor.selectionChanged.connect(self.__searchWidget.selectionChanged) |
3883 editor.selectionChanged.connect(self.__searchWidget.selectionChanged) |
3871 editor.selectionChanged.connect(self.__replaceWidget.selectionChanged) |
3884 editor.selectionChanged.connect(self.__replaceWidget.selectionChanged) |
3872 editor.lastEditPositionAvailable.connect(self.__lastEditPositionAvailable) |
3885 editor.lastEditPositionAvailable.connect(self.__lastEditPositionAvailable) |
3873 editor.zoomValueChanged.connect(self.zoomValueChanged) |
3886 editor.zoomValueChanged.connect(self.zoomValueChanged) |
3874 |
3887 |
|
3888 editor.languageChanged.connect(lambda: self.editorLanguageChanged.emit(editor)) |
|
3889 editor.textChanged.connect(lambda: self.editorTextChanged.emit(editor)) |
|
3890 |
3875 def newEditorView(self, fn, caller, filetype=""): |
3891 def newEditorView(self, fn, caller, filetype=""): |
3876 """ |
3892 """ |
3877 Public method to create a new editor displaying the given document. |
3893 Public method to create a new editor displaying the given document. |
3878 |
3894 |
3879 @param fn filename of this view |
3895 @param fn filename of this view |
5131 self.splitViewAct.setIcon( |
5147 self.splitViewAct.setIcon( |
5132 UI.PixmapCache.getIcon("splitVertical.png")) |
5148 UI.PixmapCache.getIcon("splitVertical.png")) |
5133 self.splitRemoveAct.setIcon( |
5149 self.splitRemoveAct.setIcon( |
5134 UI.PixmapCache.getIcon("remsplitVertical.png")) |
5150 UI.PixmapCache.getIcon("remsplitVertical.png")) |
5135 |
5151 |
5136 def __previewEditor(self): |
5152 def __previewEditor(self, checked): |
5137 """ |
5153 """ |
5138 Private method to preview the contents of the current editor in a web browser. |
5154 Private slot to handle a change of the preview selection state. |
5139 """ |
5155 |
5140 aw = self.activeWindow() |
5156 @param checked state of the action (boolean) |
5141 if aw is not None and aw.isPreviewable(): |
5157 """ |
5142 fn = aw.getFileName() |
5158 Preferences.setUI("ShowFilePreview", checked) |
5143 if fn: |
5159 self.previewStateChanged.emit(checked) |
5144 project = e5App().getObject("Project") |
|
5145 if project.isProjectFile(fn): |
|
5146 baseUrl = QUrl.fromLocalFile(project.getAbsoluteUniversalPath(fn)) |
|
5147 fullName = project.getAbsoluteUniversalPath(fn) |
|
5148 rootPath = project.getProjectPath() |
|
5149 else: |
|
5150 baseUrl = QUrl.fromLocalFile(fn) |
|
5151 fullName = fn |
|
5152 rootPath = os.path.dirname(os.path.abspath(fn)) |
|
5153 else: |
|
5154 baseUrl = QUrl() |
|
5155 fullName = "" |
|
5156 rootPath = "" |
|
5157 txt = self.__processSSI(aw.text(), fullName, rootPath) |
|
5158 previewer = self.ui.getHelpViewer(preview=True).previewer() |
|
5159 previewer.setHtml(txt, baseUrl) |
|
5160 |
|
5161 def __processSSI(self, txt, filename, root): |
|
5162 """ |
|
5163 Private method to process the given text for SSI statements. |
|
5164 |
|
5165 Note: Only a limited subset of SSI statements are supported. |
|
5166 |
|
5167 @param txt text to be processed (string) |
|
5168 @param filename name of the file associated with the given text (string) |
|
5169 @param root directory of the document root (string) |
|
5170 @return processed text (string) |
|
5171 """ |
|
5172 if not filename: |
|
5173 return txt |
|
5174 |
|
5175 # SSI include |
|
5176 incRe = re.compile( |
|
5177 r"""<!--#include[ \t]+(virtual|file)=[\"']([^\"']+)[\"']\s*-->""", |
|
5178 re.IGNORECASE) |
|
5179 baseDir = os.path.dirname(os.path.abspath(filename)) |
|
5180 docRoot = root if root != "" else baseDir |
|
5181 while True: |
|
5182 incMatch = incRe.search(txt) |
|
5183 if incMatch is None: |
|
5184 break |
|
5185 |
|
5186 if incMatch.group(1) == "virtual": |
|
5187 incFile = Utilities.normjoinpath(docRoot, incMatch.group(2)) |
|
5188 elif incMatch.group(1) == "file": |
|
5189 incFile = Utilities.normjoinpath(baseDir, incMatch.group(2)) |
|
5190 else: |
|
5191 incFile = "" |
|
5192 if os.path.exists(incFile): |
|
5193 try: |
|
5194 f = open(incFile, "r") |
|
5195 incTxt = f.read() |
|
5196 f.close() |
|
5197 except (IOError, OSError): |
|
5198 # remove SSI include |
|
5199 incTxt = "" |
|
5200 else: |
|
5201 # remove SSI include |
|
5202 incTxt = "" |
|
5203 txt = txt[:incMatch.start(0)] + incTxt + txt[incMatch.end(0):] |
|
5204 |
|
5205 return txt |
|
5206 |
5160 |
5207 ################################################################## |
5161 ################################################################## |
5208 ## Below are the action methods for the macro menu |
5162 ## Below are the action methods for the macro menu |
5209 ################################################################## |
5163 ################################################################## |
5210 |
5164 |
5643 self.viewActGrp.setEnabled(False) |
5597 self.viewActGrp.setEnabled(False) |
5644 self.viewFoldActGrp.setEnabled(False) |
5598 self.viewFoldActGrp.setEnabled(False) |
5645 self.unhighlightAct.setEnabled(False) |
5599 self.unhighlightAct.setEnabled(False) |
5646 self.splitViewAct.setEnabled(False) |
5600 self.splitViewAct.setEnabled(False) |
5647 self.splitOrientationAct.setEnabled(False) |
5601 self.splitOrientationAct.setEnabled(False) |
5648 self.previewAct.setEnabled(False) |
5602 self.previewAct.setEnabled(True) |
5649 self.macroActGrp.setEnabled(False) |
5603 self.macroActGrp.setEnabled(False) |
5650 self.bookmarkActGrp.setEnabled(False) |
5604 self.bookmarkActGrp.setEnabled(False) |
5651 self.__enableSpellingActions() |
5605 self.__enableSpellingActions() |
5652 self.__setSbFile(zoom=0) |
5606 self.__setSbFile(zoom=0) |
5653 |
5607 |
5718 |
5672 |
5719 self.undoAct.setEnabled(editor.isUndoAvailable()) |
5673 self.undoAct.setEnabled(editor.isUndoAvailable()) |
5720 self.redoAct.setEnabled(editor.isRedoAvailable()) |
5674 self.redoAct.setEnabled(editor.isRedoAvailable()) |
5721 self.gotoLastEditAct.setEnabled(editor.isLastEditPositionAvailable()) |
5675 self.gotoLastEditAct.setEnabled(editor.isLastEditPositionAvailable()) |
5722 |
5676 |
5723 self.previewAct.setEnabled(editor.isPreviewable()) |
5677 ## self.previewAct.setEnabled(editor.isPreviewable()) |
5724 |
5678 ## |
5725 lex = editor.getLexer() |
5679 lex = editor.getLexer() |
5726 if lex is not None: |
5680 if lex is not None: |
5727 self.commentAct.setEnabled(lex.canBlockComment()) |
5681 self.commentAct.setEnabled(lex.canBlockComment()) |
5728 self.uncommentAct.setEnabled(lex.canBlockComment()) |
5682 self.uncommentAct.setEnabled(lex.canBlockComment()) |
5729 self.streamCommentAct.setEnabled(lex.canStreamComment()) |
5683 self.streamCommentAct.setEnabled(lex.canStreamComment()) |