258 self.__unifiedMargins = True |
258 self.__unifiedMargins = True |
259 |
259 |
260 # define the margins markers |
260 # define the margins markers |
261 self.__changeMarkerSaved = self.markerDefine( |
261 self.__changeMarkerSaved = self.markerDefine( |
262 self.__createChangeMarkerPixmap( |
262 self.__createChangeMarkerPixmap( |
263 "OnlineChangeTraceMarkerSaved")) |
263 "OnlineChangeTraceMarkerSaved")) |
264 self.__changeMarkerUnsaved = self.markerDefine( |
264 self.__changeMarkerUnsaved = self.markerDefine( |
265 self.__createChangeMarkerPixmap( |
265 self.__createChangeMarkerPixmap( |
266 "OnlineChangeTraceMarkerUnsaved")) |
266 "OnlineChangeTraceMarkerUnsaved")) |
267 self.breakpoint = \ |
267 self.breakpoint = \ |
268 self.markerDefine(UI.PixmapCache.getPixmap("break.png")) |
268 self.markerDefine(UI.PixmapCache.getPixmap("break.png")) |
269 self.cbreakpoint = \ |
269 self.cbreakpoint = \ |
270 self.markerDefine(UI.PixmapCache.getPixmap("cBreak.png")) |
270 self.markerDefine(UI.PixmapCache.getPixmap("cBreak.png")) |
271 self.tbreakpoint = \ |
271 self.tbreakpoint = \ |
322 res = E5MessageBox.yesNo( |
322 res = E5MessageBox.yesNo( |
323 self, |
323 self, |
324 self.trUtf8("Open File"), |
324 self.trUtf8("Open File"), |
325 self.trUtf8("""<p>The size of the file <b>{0}</b>""" |
325 self.trUtf8("""<p>The size of the file <b>{0}</b>""" |
326 """ is <b>{1} KB</b>.""" |
326 """ is <b>{1} KB</b>.""" |
327 """ Do you really want to load it?</p>""")\ |
327 """ Do you really want to load it?</p>""") |
328 .format( |
328 .format(self.fileName, |
329 self.fileName, |
329 QFileInfo(self.fileName).size() // 1024), |
330 QFileInfo(self.fileName).size() // |
|
331 1024), |
|
332 icon=E5MessageBox.Warning) |
330 icon=E5MessageBox.Warning) |
333 if not res: |
331 if not res: |
334 raise IOError() |
332 raise IOError() |
335 self.readFile(self.fileName, True) |
333 self.readFile(self.fileName, True) |
336 bindName = self.__bindName(self.text(0)) |
334 bindName = self.__bindName(self.text(0)) |
1178 E5MessageBox.critical( |
1176 E5MessageBox.critical( |
1179 self, |
1177 self, |
1180 self.trUtf8("Export source"), |
1178 self.trUtf8("Export source"), |
1181 self.trUtf8( |
1179 self.trUtf8( |
1182 """<p>No exporter available for the """ |
1180 """<p>No exporter available for the """ |
1183 """export format <b>{0}</b>. Aborting...</p>""")\ |
1181 """export format <b>{0}</b>. Aborting...</p>""") |
1184 .format(exporterFormat)) |
1182 .format(exporterFormat)) |
1185 else: |
1183 else: |
1186 E5MessageBox.critical( |
1184 E5MessageBox.critical( |
1187 self, |
1185 self, |
1188 self.trUtf8("Export source"), |
1186 self.trUtf8("Export source"), |
1189 self.trUtf8("""No export format given. Aborting...""")) |
1187 self.trUtf8("""No export format given. Aborting...""")) |
1279 |
1277 |
1280 self.apiLanguage = "" |
1278 self.apiLanguage = "" |
1281 self.lexer_ = None |
1279 self.lexer_ = None |
1282 self.__lexerReset = True |
1280 self.__lexerReset = True |
1283 self.setLexer() |
1281 self.setLexer() |
1284 self.setMonospaced(self.useMonospaced) |
|
1285 if self.completer is not None: |
1282 if self.completer is not None: |
1286 self.completer.setEnabled(False) |
1283 self.completer.setEnabled(False) |
1287 self.completer = None |
1284 self.completer = None |
|
1285 useMonospaced = self.useMonospaced |
1288 self.__setTextDisplay() |
1286 self.__setTextDisplay() |
|
1287 self.setMonospaced(useMonospaced) |
|
1288 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) |
1289 |
1289 |
1290 if not self.inLanguageChanged and propagate: |
1290 if not self.inLanguageChanged and propagate: |
1291 self.inLanguageChanged = True |
1291 self.inLanguageChanged = True |
1292 self.languageChanged.emit(self.apiLanguage) |
1292 self.languageChanged.emit(self.apiLanguage) |
1293 self.inLanguageChanged = False |
1293 self.inLanguageChanged = False |
1302 @param initTextDisplay flag indicating an initialization of the text |
1302 @param initTextDisplay flag indicating an initialization of the text |
1303 display is required as well (boolean) |
1303 display is required as well (boolean) |
1304 @keyparam propagate flag indicating to propagate the change (boolean) |
1304 @keyparam propagate flag indicating to propagate the change (boolean) |
1305 @keyparam pyname name of the pygments lexer to use (string) |
1305 @keyparam pyname name of the pygments lexer to use (string) |
1306 """ |
1306 """ |
|
1307 self.menuActs["MonospacedFont"].setChecked(False) |
|
1308 |
1307 self.__lexerReset = False |
1309 self.__lexerReset = False |
1308 self.__bindLexer(filename, pyname=pyname) |
1310 self.__bindLexer(filename, pyname=pyname) |
1309 self.__bindCompleter(filename) |
1311 self.__bindCompleter(filename) |
1310 self.recolor() |
1312 self.recolor() |
1311 self.__checkLanguage() |
1313 self.__checkLanguage() |
1738 |
1740 |
1739 if self.filetype == "": |
1741 if self.filetype == "": |
1740 # 1) Determine by first line |
1742 # 1) Determine by first line |
1741 line0 = self.text(0) |
1743 line0 = self.text(0) |
1742 if line0.startswith("#!") and \ |
1744 if line0.startswith("#!") and \ |
1743 ("python2" in line0 or \ |
1745 ("python2" in line0 or |
1744 ("python" in line0 and not "python3" in line0)): |
1746 ("python" in line0 and not "python3" in line0)): |
1745 self.filetype = "Python2" |
1747 self.filetype = "Python2" |
1746 return True |
1748 return True |
1747 |
1749 |
1748 if self.fileName is not None: |
1750 if self.fileName is not None: |
1749 ext = os.path.splitext(self.fileName)[1] |
1751 ext = os.path.splitext(self.fileName)[1] |
2446 Public slot to extract all tasks. |
2448 Public slot to extract all tasks. |
2447 """ |
2449 """ |
2448 from Tasks.Task import Task |
2450 from Tasks.Task import Task |
2449 markers = { |
2451 markers = { |
2450 Task.TypeWarning: |
2452 Task.TypeWarning: |
2451 Preferences.getTasks("TasksWarningMarkers").split(), |
2453 Preferences.getTasks("TasksWarningMarkers").split(), |
2452 Task.TypeNote: |
2454 Task.TypeNote: |
2453 Preferences.getTasks("TasksNoteMarkers").split(), |
2455 Preferences.getTasks("TasksNoteMarkers").split(), |
2454 Task.TypeTodo: |
2456 Task.TypeTodo: |
2455 Preferences.getTasks("TasksTodoMarkers").split(), |
2457 Preferences.getTasks("TasksTodoMarkers").split(), |
2456 Task.TypeFixme: |
2458 Task.TypeFixme: |
2457 Preferences.getTasks("TasksFixmeMarkers").split(), |
2459 Preferences.getTasks("TasksFixmeMarkers").split(), |
2458 } |
2460 } |
2459 txtList = self.text().split(self.getLineSeparator()) |
2461 txtList = self.text().split(self.getLineSeparator()) |
2460 |
2462 |
2461 # clear all task markers and tasks |
2463 # clear all task markers and tasks |
2462 self.markerDeleteAll(self.taskmarker) |
2464 self.markerDeleteAll(self.taskmarker) |
2688 fn = self.noName |
2690 fn = self.noName |
2689 res = E5MessageBox.okToClearData( |
2691 res = E5MessageBox.okToClearData( |
2690 self, |
2692 self, |
2691 self.trUtf8("File Modified"), |
2693 self.trUtf8("File Modified"), |
2692 self.trUtf8("<p>The file <b>{0}</b> has unsaved changes.</p>") |
2694 self.trUtf8("<p>The file <b>{0}</b> has unsaved changes.</p>") |
2693 .format(fn), |
2695 .format(fn), |
2694 self.saveFile) |
2696 self.saveFile) |
2695 if res: |
2697 if res: |
2696 self.vm.setEditorName(self, self.fileName) |
2698 self.vm.setEditorName(self, self.fileName) |
2697 return res |
2699 return res |
2698 |
2700 |
2746 fileEol = self.detectEolString(txt) |
2748 fileEol = self.detectEolString(txt) |
2747 |
2749 |
2748 modified = False |
2750 modified = False |
2749 if (not Preferences.getEditor("TabForIndentation")) and \ |
2751 if (not Preferences.getEditor("TabForIndentation")) and \ |
2750 Preferences.getEditor("ConvertTabsOnLoad") and \ |
2752 Preferences.getEditor("ConvertTabsOnLoad") and \ |
2751 not (self.lexer_ and \ |
2753 not (self.lexer_ and |
2752 self.lexer_.alwaysKeepTabs()): |
2754 self.lexer_.alwaysKeepTabs()): |
2753 txtExpanded = txt.expandtabs(Preferences.getEditor("TabWidth")) |
2755 txtExpanded = txt.expandtabs(Preferences.getEditor("TabWidth")) |
2754 if txtExpanded != txt: |
2756 if txtExpanded != txt: |
2755 modified = True |
2757 modified = True |
2756 txt = txtExpanded |
2758 txt = txtExpanded |
2841 E5MessageBox.critical( |
2843 E5MessageBox.critical( |
2842 self, |
2844 self, |
2843 self.trUtf8('Save File'), |
2845 self.trUtf8('Save File'), |
2844 self.trUtf8('<p>The file <b>{0}</b> could not be saved.<br/>' |
2846 self.trUtf8('<p>The file <b>{0}</b> could not be saved.<br/>' |
2845 'Reason: {1}</p>') |
2847 'Reason: {1}</p>') |
2846 .format(fn, str(why))) |
2848 .format(fn, str(why))) |
2847 return False |
2849 return False |
2848 |
2850 |
2849 def saveFile(self, saveas=False, path=None): |
2851 def saveFile(self, saveas=False, path=None): |
2850 """ |
2852 """ |
2851 Public slot to save the text to a file. |
2853 Public slot to save the text to a file. |
3315 self.commentLineOrSelection() |
3317 self.commentLineOrSelection() |
3316 else: |
3318 else: |
3317 # determine the start of the comment block |
3319 # determine the start of the comment block |
3318 begline = line |
3320 begline = line |
3319 while begline > 0 and \ |
3321 while begline > 0 and \ |
3320 self.__isCommentedLine(self.text(begline - 1), commentStr): |
3322 self.__isCommentedLine(self.text(begline - 1), commentStr): |
3321 begline -= 1 |
3323 begline -= 1 |
3322 # determine the end of the comment block |
3324 # determine the end of the comment block |
3323 endline = line |
3325 endline = line |
3324 lines = self.lines() |
3326 lines = self.lines() |
3325 while endline < lines and \ |
3327 while endline < lines and \ |
3326 self.__isCommentedLine(self.text(endline + 1), commentStr): |
3328 self.__isCommentedLine(self.text(endline + 1), commentStr): |
3327 endline += 1 |
3329 endline += 1 |
3328 |
3330 |
3329 self.setSelection(begline, 0, endline, self.lineLength(endline)) |
3331 self.setSelection(begline, 0, endline, self.lineLength(endline)) |
3330 self.uncommentLineOrSelection() |
3332 self.uncommentLineOrSelection() |
3331 |
3333 |
4658 tbasename = os.path.splitext(tfn)[0] |
4660 tbasename = os.path.splitext(tfn)[0] |
4659 prEnable = prEnable or \ |
4661 prEnable = prEnable or \ |
4660 os.path.isfile("{0}.profile".format(basename)) or \ |
4662 os.path.isfile("{0}.profile".format(basename)) or \ |
4661 os.path.isfile("{0}.profile".format(tbasename)) |
4663 os.path.isfile("{0}.profile".format(tbasename)) |
4662 coEnable = ( |
4664 coEnable = ( |
4663 coEnable or \ |
4665 coEnable or |
4664 os.path.isfile("{0}.coverage".format(basename)) or \ |
4666 os.path.isfile("{0}.coverage".format(basename)) or |
4665 os.path.isfile("{0}.coverage".format(tbasename))) and \ |
4667 os.path.isfile("{0}.coverage".format(tbasename))) and \ |
4666 self.project.isPy3Project() |
4668 self.project.isPy3Project() |
4667 |
4669 |
4668 # now check ourself |
4670 # now check ourself |
4669 fn = self.getFileName() |
4671 fn = self.getFileName() |
4673 tbasename = os.path.splitext(tfn)[0] |
4675 tbasename = os.path.splitext(tfn)[0] |
4674 prEnable = prEnable or \ |
4676 prEnable = prEnable or \ |
4675 os.path.isfile("{0}.profile".format(basename)) or \ |
4677 os.path.isfile("{0}.profile".format(basename)) or \ |
4676 os.path.isfile("{0}.profile".format(tbasename)) |
4678 os.path.isfile("{0}.profile".format(tbasename)) |
4677 coEnable = ( |
4679 coEnable = ( |
4678 coEnable or \ |
4680 coEnable or |
4679 os.path.isfile("{0}.coverage".format(basename)) or \ |
4681 os.path.isfile("{0}.coverage".format(basename)) or |
4680 os.path.isfile("{0}.coverage".format(tbasename))) and \ |
4682 os.path.isfile("{0}.coverage".format(tbasename))) and \ |
4681 self.isPy3File() |
4683 self.isPy3File() |
4682 |
4684 |
4683 # now check for syntax errors |
4685 # now check for syntax errors |
4684 if self.hasSyntaxErrors(): |
4686 if self.hasSyntaxErrors(): |
4933 Public slot to check the autosave flags. |
4935 Public slot to check the autosave flags. |
4934 |
4936 |
4935 @return flag indicating this editor should be saved (boolean) |
4937 @return flag indicating this editor should be saved (boolean) |
4936 """ |
4938 """ |
4937 return self.fileName is not None and \ |
4939 return self.fileName is not None and \ |
4938 not self.autosaveManuallyDisabled and \ |
4940 not self.autosaveManuallyDisabled and \ |
4939 not self.isReadOnly() |
4941 not self.isReadOnly() |
4940 |
4942 |
4941 |
4943 |
4942 def __autoSyntaxCheck(self): |
4944 def __autoSyntaxCheck(self): |
4943 """ |
4945 """ |
4944 Private method to perform an automatic syntax check of the file. |
4946 Private method to perform an automatic syntax check of the file. |
5639 E5MessageBox.critical( |
5641 E5MessageBox.critical( |
5640 self, |
5642 self, |
5641 self.trUtf8("Error loading macro"), |
5643 self.trUtf8("Error loading macro"), |
5642 self.trUtf8( |
5644 self.trUtf8( |
5643 "<p>The macro file <b>{0}</b> could not be read.</p>") |
5645 "<p>The macro file <b>{0}</b> could not be read.</p>") |
5644 .format(fname)) |
5646 .format(fname)) |
5645 return |
5647 return |
5646 |
5648 |
5647 if len(lines) != 2: |
5649 if len(lines) != 2: |
5648 E5MessageBox.critical( |
5650 E5MessageBox.critical( |
5649 self, |
5651 self, |
5650 self.trUtf8("Error loading macro"), |
5652 self.trUtf8("Error loading macro"), |
5651 self.trUtf8("<p>The macro file <b>{0}</b> is corrupt.</p>") |
5653 self.trUtf8("<p>The macro file <b>{0}</b> is corrupt.</p>") |
5652 .format(fname)) |
5654 .format(fname)) |
5653 return |
5655 return |
5654 |
5656 |
5655 macro = QsciMacro(lines[1], self) |
5657 macro = QsciMacro(lines[1], self) |
5656 self.macros[lines[0].strip()] = macro |
5658 self.macros[lines[0].strip()] = macro |
5657 |
5659 |
5701 E5MessageBox.critical( |
5703 E5MessageBox.critical( |
5702 self, |
5704 self, |
5703 self.trUtf8("Error saving macro"), |
5705 self.trUtf8("Error saving macro"), |
5704 self.trUtf8( |
5706 self.trUtf8( |
5705 "<p>The macro file <b>{0}</b> could not be written.</p>") |
5707 "<p>The macro file <b>{0}</b> could not be written.</p>") |
5706 .format(fname)) |
5708 .format(fname)) |
5707 return |
5709 return |
5708 |
5710 |
5709 def macroRecordingStart(self): |
5711 def macroRecordingStart(self): |
5710 """ |
5712 """ |
5711 Public method to start macro recording. |
5713 Public method to start macro recording. |
6132 else: |
6134 else: |
6133 E5MessageBox.information( |
6135 E5MessageBox.information( |
6134 self, |
6136 self, |
6135 self.trUtf8("Drop Error"), |
6137 self.trUtf8("Drop Error"), |
6136 self.trUtf8("""<p><b>{0}</b> is not a file.</p>""") |
6138 self.trUtf8("""<p><b>{0}</b> is not a file.</p>""") |
6137 .format(fname)) |
6139 .format(fname)) |
6138 event.acceptProposedAction() |
6140 event.acceptProposedAction() |
6139 else: |
6141 else: |
6140 super(Editor, self).dropEvent(event) |
6142 super(Editor, self).dropEvent(event) |
6141 |
6143 |
6142 self.inDragDrop = False |
6144 self.inDragDrop = False |
6232 self.trUtf8("Alias for file <b>{0}</b>:").format(relFile), |
6234 self.trUtf8("Alias for file <b>{0}</b>:").format(relFile), |
6233 QLineEdit.Normal, |
6235 QLineEdit.Normal, |
6234 relFile) |
6236 relFile) |
6235 if ok and alias: |
6237 if ok and alias: |
6236 line, index = self.getCursorPosition() |
6238 line, index = self.getCursorPosition() |
6237 self.insert(' <file alias="{1}">{0}</file>\n'\ |
6239 self.insert(' <file alias="{1}">{0}</file>\n' |
6238 .format(relFile, alias)) |
6240 .format(relFile, alias)) |
6239 self.setCursorPosition(line + 1, index) |
6241 self.setCursorPosition(line + 1, index) |
6240 |
6242 |
6241 def __addLocalizedResource(self): |
6243 def __addLocalizedResource(self): |
6242 """ |
6244 """ |
6386 self.getLanguage()) |
6388 self.getLanguage()) |
6387 return |
6389 return |
6388 elif len(templateNames) > 1: |
6390 elif len(templateNames) > 1: |
6389 self.showUserList( |
6391 self.showUserList( |
6390 TemplateCompletionListID, |
6392 TemplateCompletionListID, |
6391 ["{0}?{1:d}".format(t, self.TemplateImageID) \ |
6393 ["{0}?{1:d}".format(t, self.TemplateImageID) |
6392 for t in templateNames]) |
6394 for t in templateNames]) |
6393 return |
6395 return |
6394 |
6396 |
6395 super(Editor, self).editorCommand(cmd) |
6397 super(Editor, self).editorCommand(cmd) |
6396 |
6398 |
6542 """ |
6544 """ |
6543 if self.__spellCheckStringsOnly: |
6545 if self.__spellCheckStringsOnly: |
6544 style = self.styleAt(pos) |
6546 style = self.styleAt(pos) |
6545 if self.lexer_ is not None: |
6547 if self.lexer_ is not None: |
6546 return self.lexer_.isCommentStyle(style) or \ |
6548 return self.lexer_.isCommentStyle(style) or \ |
6547 self.lexer_.isStringStyle(style) |
6549 self.lexer_.isStringStyle(style) |
6548 return True |
6550 return True |
6549 |
6551 |
6550 @pyqtSlot(int) |
6552 @pyqtSlot(int) |
6551 def __spellCharAdded(self, charNumber): |
6553 def __spellCharAdded(self, charNumber): |
6552 """ |
6554 """ |
6688 status, if it is inside a locally initiated shared edit session |
6690 status, if it is inside a locally initiated shared edit session |
6689 and if it is inside a remotely initiated shared edit session |
6691 and if it is inside a remotely initiated shared edit session |
6690 (boolean, boolean, boolean, boolean) |
6692 (boolean, boolean, boolean, boolean) |
6691 """ |
6693 """ |
6692 return self.fileName is not None and \ |
6694 return self.fileName is not None and \ |
6693 self.project.isOpen() and \ |
6695 self.project.isOpen() and \ |
6694 self.project.isProjectFile(self.fileName), \ |
6696 self.project.isProjectFile(self.fileName), \ |
6695 self.__isShared, self.__inSharedEdit, self.__inRemoteSharedEdit |
6697 self.__isShared, self.__inSharedEdit, self.__inRemoteSharedEdit |
6696 |
6698 |
6697 def shareConnected(self, connected): |
6699 def shareConnected(self, connected): |
6698 """ |
6700 """ |
6699 Public slot to handle a change of the connected state. |
6701 Public slot to handle a change of the connected state. |
6700 |
6702 |