diff -r 9986ec0e559a -r 10516539f238 QScintilla/Editor.py --- a/QScintilla/Editor.py Tue Oct 15 22:03:54 2013 +0200 +++ b/QScintilla/Editor.py Fri Oct 18 23:00:41 2013 +0200 @@ -19,9 +19,9 @@ from PyQt4.QtCore import QDir, QTimer, QModelIndex, QFileInfo, pyqtSignal, \ pyqtSlot, QCryptographicHash, QEvent, QDateTime, QRegExp, Qt -from PyQt4.QtGui import QCursor, QPrinter, QPrintDialog, QLineEdit, QActionGroup, \ - QDialog, QAbstractPrintDialog, QInputDialog, QApplication, QMenu, QPalette, QFont, \ - QPixmap, QPainter +from PyQt4.QtGui import QCursor, QPrinter, QPrintDialog, QLineEdit, \ + QActionGroup, QDialog, QAbstractPrintDialog, QInputDialog, QApplication, \ + QMenu, QPalette, QFont, QPixmap, QPainter from PyQt4.Qsci import QsciScintilla, QsciMacro, QsciStyledText from E5Gui.E5Application import e5App @@ -42,41 +42,44 @@ """ Class implementing the editor component of the eric5 IDE. - @signal modificationStatusChanged(bool, QsciScintillaCompat) emitted when the - modification status has changed + @signal modificationStatusChanged(bool, QsciScintillaCompat) emitted when + the modification status has changed @signal undoAvailable(bool) emitted to signal the undo availability @signal redoAvailable(bool) emitted to signal the redo availability @signal cursorChanged(str, int, int) emitted when the cursor position - was changed + was changed @signal cursorLineChanged(int) emitted when the cursor line was changed @signal editorAboutToBeSaved(str) emitted before the editor is saved @signal editorSaved(str) emitted after the editor has been saved @signal editorRenamed(str) emitted after the editor got a new name - (i.e. after a 'Save As') - @signal captionChanged(str, QsciScintillaCompat) emitted when the caption is - updated. Typically due to a readOnly attribute change. - @signal breakpointToggled(QsciScintillaCompat) emitted when a breakpoint is toggled - @signal bookmarkToggled(QsciScintillaCompat) emitted when a bookmark is toggled + (i.e. after a 'Save As') + @signal captionChanged(str, QsciScintillaCompat) emitted when the caption + is updated. Typically due to a readOnly attribute change. + @signal breakpointToggled(QsciScintillaCompat) emitted when a breakpoint + is toggled + @signal bookmarkToggled(QsciScintillaCompat) emitted when a bookmark is + toggled @signal syntaxerrorToggled(QsciScintillaCompat) emitted when a syntax error - was discovered + was discovered @signal autoCompletionAPIsAvailable(bool) emitted after the autocompletion - function has been configured - @signal coverageMarkersShown(bool) emitted after the coverage markers have been - shown or cleared - @signal taskMarkersUpdated(QsciScintillaCompat) emitted when the task markers - were updated - @signal changeMarkersUpdated(QsciScintillaCompat) emitted when the change markers - were updated - @signal showMenu(str, QMenu, QsciScintillaCompat) emitted when a menu is about - to be shown. The name of the menu, a reference to the menu and a reference - to the editor are given. + function has been configured + @signal coverageMarkersShown(bool) emitted after the coverage markers have + been shown or cleared + @signal taskMarkersUpdated(QsciScintillaCompat) emitted when the task + markers were updated + @signal changeMarkersUpdated(QsciScintillaCompat) emitted when the change + markers were updated + @signal showMenu(str, QMenu, QsciScintillaCompat) emitted when a menu is + about to be shown. The name of the menu, a reference to the menu and + a reference to the editor are given. @signal languageChanged(str) emitted when the editors language was set. The - language is passed as a parameter. - @signal eolChanged(str) emitted when the editors eol type was set. The eol string - is passed as a parameter. + language is passed as a parameter. + @signal eolChanged(str) emitted when the editors eol type was set. The eol + string is passed as a parameter. @signal encodingChanged(str) emitted when the editors encoding was set. The encoding name is passed as a parameter. - @signal lastEditPositionAvailable() emitted when a last edit position is available + @signal lastEditPositionAvailable() emitted when a last edit position is + available @signal refreshed() emitted to signal a refresh of the editor contents """ modificationStatusChanged = pyqtSignal(bool, QsciScintillaCompat) @@ -138,10 +141,12 @@ @param dbs reference to the debug server object @param fn name of the file to be opened (string). If it is None, a new (empty) editor is opened - @param vm reference to the view manager object (ViewManager.ViewManager) + @param vm reference to the view manager object + (ViewManager.ViewManager) @param filetype type of the source file (string) @param editor reference to an Editor object, if this is a cloned view @param tv reference to the task viewer object + @exception IOError raised to indicate an issue accessing the file """ super(Editor, self).__init__() self.setAttribute(Qt.WA_DeleteOnClose) @@ -253,9 +258,11 @@ self.__unifiedMargins = True # define the margins markers - self.__changeMarkerSaved = self.markerDefine(self.__createChangeMarkerPixmap( + self.__changeMarkerSaved = self.markerDefine( + self.__createChangeMarkerPixmap( "OnlineChangeTraceMarkerSaved")) - self.__changeMarkerUnsaved = self.markerDefine(self.__createChangeMarkerPixmap( + self.__changeMarkerUnsaved = self.markerDefine( + self.__createChangeMarkerPixmap( "OnlineChangeTraceMarkerUnsaved")) self.breakpoint = \ self.markerDefine(UI.PixmapCache.getPixmap("break.png")) @@ -304,6 +311,9 @@ # set the text display self.__setTextDisplay() + # initialize the online syntax check timer + self.__initOnlineSyntaxCheck() + self.isResourcesFile = False if editor is None: if self.fileName is not None: @@ -314,8 +324,10 @@ self.trUtf8("""<p>The size of the file <b>{0}</b>""" """ is <b>{1} KB</b>.""" """ Do you really want to load it?</p>""")\ - .format(self.fileName, - QFileInfo(self.fileName).size() // 1024), + .format( + self.fileName, + QFileInfo(self.fileName).size() // + 1024), icon=E5MessageBox.Warning) if not res: raise IOError() @@ -365,13 +377,13 @@ self.setWhatsThis(self.trUtf8( """<b>A Source Editor Window</b>""" """<p>This window is used to display and edit a source file.""" - """ You can open as many of these as you like. The name of the file""" - """ is displayed in the window's titlebar.</p>""" - """<p>In order to set breakpoints just click in the space between""" - """ the line numbers and the fold markers. Via the context menu""" - """ of the margins they may be edited.</p>""" - """<p>In order to set bookmarks just Shift click in the space between""" - """ the line numbers and the fold markers.</p>""" + """ You can open as many of these as you like. The name of the""" + """ file is displayed in the window's titlebar.</p>""" + """<p>In order to set breakpoints just click in the space""" + """ between the line numbers and the fold markers. Via the""" + """ context menu of the margins they may be edited.</p>""" + """<p>In order to set bookmarks just Shift click in the space""" + """ between the line numbers and the fold markers.</p>""" """<p>These actions can be reversed via the context menu.</p>""" """<p>Ctrl clicking on a syntax error marker shows some info""" """ about this error.</p>""" @@ -428,16 +440,14 @@ # connect signals after loading the text self.textChanged.connect(self.__textChanged) - # initialize the online syntax check timer - self.__initOnlineSyntaxCheck() - # initialize the online change trace timer self.__initOnlineChangeTrace() if self.fileName and \ self.project.isOpen() and \ self.project.isProjectSource(self.fileName): - self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged) + self.project.projectPropertiesChanged.connect( + self.__projectPropertiesChanged) self.grabGesture(Qt.PinchGesture) @@ -476,7 +486,7 @@ """ Public method to add a clone to our list. - @param clone reference to the cloned editor (Editor) + @param editor reference to the cloned editor (Editor) """ self.__clones.append(editor) @@ -489,7 +499,7 @@ """ Public method to remove a clone from our list. - @param clone reference to the cloned editor (Editor) + @param editor reference to the cloned editor (Editor) """ if editor in self.__clones: editor.editorRenamed.disconnect(self.fileRenamed) @@ -502,7 +512,9 @@ """ Private method to generate a dummy filename for binding a lexer. - @param line0 first line of text to use in the generation process (string) + @param line0 first line of text to use in the generation process + (string) + @return dummy file name to be used for binding a lexer (string) """ bindName = "" line0 = line0.lower() @@ -581,7 +593,7 @@ def __initContextMenu(self): """ - Private method used to setup the context menu + Private method used to setup the context menu. """ self.miniMenu = Preferences.getEditor("MiniContextMenu") @@ -640,7 +652,8 @@ self.menu.addAction(UI.PixmapCache.getIcon("editComment.png"), self.trUtf8('Comment'), self.commentLineOrSelection) self.menuActs["Uncomment"] = \ - self.menu.addAction(UI.PixmapCache.getIcon("editUncomment.png"), + self.menu.addAction( + UI.PixmapCache.getIcon("editUncomment.png"), self.trUtf8('Uncomment'), self.uncommentLineOrSelection) self.menuActs["StreamComment"] = \ self.menu.addAction(self.trUtf8('Stream Comment'), @@ -652,7 +665,8 @@ self.menu.addAction(self.trUtf8('Select to brace'), self.selectToMatchingBrace) self.menu.addAction(self.trUtf8('Select all'), self.__selectAll) - self.menu.addAction(self.trUtf8('Deselect all'), self.__deselectAll) + self.menu.addAction( + self.trUtf8('Deselect all'), self.__deselectAll) self.menu.addSeparator() self.menuActs["SpellCheck"] = \ self.menu.addAction(UI.PixmapCache.getIcon("spellchecking.png"), @@ -686,7 +700,8 @@ self.menu.addAction(self.trUtf8("Typing aids enabled"), self.__toggleTypingAids) self.menuActs["TypingAidsEnabled"].setCheckable(True) - self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None) + self.menuActs["TypingAidsEnabled"].setEnabled( + self.completer is not None) self.menuActs["TypingAidsEnabled"].setChecked( self.completer is not None and self.completer.isEnabled()) self.menuActs["AutoCompletionEnable"] = \ @@ -740,11 +755,14 @@ self.__menus["Spelling"] = self.spellingMenu self.spellingMenu.aboutToShow.connect(self.__showContextMenuSpelling) - self.spellingMenu.triggered.connect(self.__contextMenuSpellingTriggered) + self.spellingMenu.triggered.connect( + self.__contextMenuSpellingTriggered) def __initContextMenuAutocompletion(self): """ Private method used to setup the Checks context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8('Autocomplete')) @@ -771,6 +789,8 @@ def __initContextMenuChecks(self): """ Private method used to setup the Checks context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8('Check')) menu.aboutToShow.connect(self.__showContextMenuChecks) @@ -779,20 +799,22 @@ def __initContextMenuShow(self): """ Private method used to setup the Show context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8('Show')) menu.addAction(self.trUtf8('Code metrics...'), self.__showCodeMetrics) - self.coverageMenuAct = \ - menu.addAction(self.trUtf8('Code coverage...'), self.__showCodeCoverage) - self.coverageShowAnnotationMenuAct = \ - menu.addAction(self.trUtf8('Show code coverage annotations'), - self.codeCoverageShowAnnotations) - self.coverageHideAnnotationMenuAct = \ - menu.addAction(self.trUtf8('Hide code coverage annotations'), - self.__codeCoverageHideAnnotations) - self.profileMenuAct = \ - menu.addAction(self.trUtf8('Profile data...'), self.__showProfileData) + self.coverageMenuAct = menu.addAction( + self.trUtf8('Code coverage...'), self.__showCodeCoverage) + self.coverageShowAnnotationMenuAct = menu.addAction( + self.trUtf8('Show code coverage annotations'), + self.codeCoverageShowAnnotations) + self.coverageHideAnnotationMenuAct = menu.addAction( + self.trUtf8('Hide code coverage annotations'), + self.__codeCoverageHideAnnotations) + self.profileMenuAct = menu.addAction( + self.trUtf8('Profile data...'), self.__showProfileData) menu.aboutToShow.connect(self.__showContextMenuShow) @@ -801,6 +823,8 @@ def __initContextMenuGraphics(self): """ Private method used to setup the diagrams context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8('Diagrams')) @@ -824,6 +848,8 @@ def __initContextMenuLanguages(self): """ Private method used to setup the Languages context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8("Languages")) @@ -840,7 +866,8 @@ languages = sorted(list(supportedLanguages.keys())) for language in languages: if language != "Guessed": - self.supportedLanguages[language] = supportedLanguages[language][:2] + self.supportedLanguages[language] = \ + supportedLanguages[language][:2] act = menu.addAction( UI.PixmapCache.getIcon(supportedLanguages[language][2]), self.supportedLanguages[language][0]) @@ -865,6 +892,8 @@ def __initContextMenuEncodings(self): """ Private method used to setup the Encodings context sub menu. + + @return reference to the generated menu (QMenu) """ self.supportedEncodings = {} @@ -887,6 +916,8 @@ def __initContextMenuEol(self): """ Private method to setup the eol context sub menu. + + @return reference to the generated menu (QMenu) """ self.supportedEols = {} @@ -923,6 +954,8 @@ def __initContextMenuExporters(self): """ Private method used to setup the Exporters context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8("Export as")) @@ -939,7 +972,7 @@ def __initContextMenuMargins(self): """ - Private method used to setup the context menu for the margins + Private method used to setup the context menu for the margins. """ self.marginMenuActs = {} @@ -950,7 +983,8 @@ def __initContextMenuSeparateMargins(self): """ - Private method used to setup the context menu for the separated margins + Private method used to setup the context menu for the separated + margins. """ # bookmark margin self.bmMarginMenu = QMenu() @@ -976,7 +1010,8 @@ self.bpMarginMenu.addAction(self.trUtf8('Toggle breakpoint'), self.menuToggleBreakpoint) self.marginMenuActs["TempBreakpoint"] = \ - self.bpMarginMenu.addAction(self.trUtf8('Toggle temporary breakpoint'), + self.bpMarginMenu.addAction( + self.trUtf8('Toggle temporary breakpoint'), self.__menuToggleTemporaryBreakpoint) self.marginMenuActs["EditBreakpoint"] = \ self.bpMarginMenu.addAction(self.trUtf8('Edit breakpoint...'), @@ -1003,7 +1038,8 @@ self.indicMarginMenu.addAction(self.trUtf8('Goto syntax error'), self.gotoSyntaxError) self.marginMenuActs["ShowSyntaxError"] = \ - self.indicMarginMenu.addAction(self.trUtf8('Show syntax error message'), + self.indicMarginMenu.addAction( + self.trUtf8('Show syntax error message'), self.__showSyntaxError) self.marginMenuActs["ClearSyntaxError"] = \ self.indicMarginMenu.addAction(self.trUtf8('Clear syntax error'), @@ -1026,7 +1062,8 @@ self.indicMarginMenu.addAction(self.trUtf8('Next uncovered line'), self.nextUncovered) self.marginMenuActs["PreviousCoverageMarker"] = \ - self.indicMarginMenu.addAction(self.trUtf8('Previous uncovered line'), + self.indicMarginMenu.addAction( + self.trUtf8('Previous uncovered line'), self.previousUncovered) self.indicMarginMenu.addSeparator() self.marginMenuActs["NextTaskMarker"] = \ @@ -1047,7 +1084,7 @@ def __initContextMenuUnifiedMargins(self): """ - Private method used to setup the context menu for the unified margins + Private method used to setup the context menu for the unified margins. """ self.marginMenu = QMenu() @@ -1090,7 +1127,8 @@ self.marginMenu.addAction(self.trUtf8('Toggle breakpoint'), self.menuToggleBreakpoint) self.marginMenuActs["TempBreakpoint"] = \ - self.marginMenu.addAction(self.trUtf8('Toggle temporary breakpoint'), + self.marginMenu.addAction( + self.trUtf8('Toggle temporary breakpoint'), self.__menuToggleTemporaryBreakpoint) self.marginMenuActs["EditBreakpoint"] = \ self.marginMenu.addAction(self.trUtf8('Edit breakpoint...'), @@ -1165,8 +1203,9 @@ else: E5MessageBox.critical(self, self.trUtf8("Export source"), - self.trUtf8("""<p>No exporter available for the """ - """export format <b>{0}</b>. Aborting...</p>""")\ + self.trUtf8( + """<p>No exporter available for the """ + """export format <b>{0}</b>. Aborting...</p>""")\ .format(exporterFormat)) else: E5MessageBox.critical(self, @@ -1175,7 +1214,8 @@ def __showContextMenuLanguages(self): """ - Private slot handling the aboutToShow signal of the languages context menu. + Private slot handling the aboutToShow signal of the languages context + menu. """ if self.apiLanguage.startswith("Pygments|"): self.pygmentsSelAct.setText( @@ -1247,7 +1287,8 @@ self.setLanguage("dummy.pygments", pyname=pyname) else: self.filetype = language - self.setLanguage(self.supportedLanguages[language][1], propagate=propagate) + self.setLanguage(self.supportedLanguages[language][1], + propagate=propagate) self.__autoSyntaxCheck() def __resetLanguage(self, propagate=True): @@ -1280,9 +1321,10 @@ """ Public method to set a lexer language. - @param filename filename used to determine the associated lexer language (string) - @param initTextDisplay flag indicating an initialization of the text display - is required as well (boolean) + @param filename filename used to determine the associated lexer + language (string) + @param initTextDisplay flag indicating an initialization of the text + display is required as well (boolean) @keyparam propagate flag indicating to propagate the change (boolean) @keyparam pyname name of the pygments lexer to use (string) """ @@ -1328,7 +1370,8 @@ def __showContextMenuEncodings(self): """ - Private slot handling the aboutToShow signal of the encodings context menu. + Private slot handling the aboutToShow signal of the encodings context + menu. """ self.showMenu.emit("Encodings", self.encodingsMenu, self) @@ -1346,7 +1389,8 @@ Private method to check the selected encoding of the encodings submenu. """ try: - self.supportedEncodings[self.__normalizedEncoding()].setChecked(True) + self.supportedEncodings[self.__normalizedEncoding()]\ + .setChecked(True) except (AttributeError, KeyError): pass @@ -1354,6 +1398,7 @@ """ Private slot to handle a change of the encoding. + @param encoding changed encoding (string) @keyparam propagate flag indicating to propagate the change (boolean) """ self.encoding = encoding @@ -1415,7 +1460,8 @@ """ Private slot to set the correct lexer depending on language. - @param filename filename used to determine the associated lexer language (string) + @param filename filename used to determine the associated lexer + language (string) @keyparam pyname name of the pygments lexer to use (string) """ if self.lexer_ is not None and \ @@ -1424,7 +1470,8 @@ language = "" if self.project.isOpen() and self.project.isProjectFile(filename): - language = self.project.getEditorLexerAssoc(os.path.basename(filename)) + language = self.project.getEditorLexerAssoc( + os.path.basename(filename)) if not language: ext = os.path.splitext(filename)[1] if ext in [".py", ".pyw"]: @@ -1518,7 +1565,8 @@ names for Pygments (boolean) @return language of the editor (string) """ - if self.apiLanguage == "Guessed" or self.apiLanguage.startswith("Pygments|"): + if self.apiLanguage == "Guessed" or \ + self.apiLanguage.startswith("Pygments|"): lang = self.lexer_.name() if normalized: # adjust some Pygments lexer names @@ -1608,7 +1656,8 @@ # do spell checking doSpelling = True if self.lastLine == line: - start, end = self.getWordBoundaries(line, index, useWordChars=False) + start, end = self.getWordBoundaries( + line, index, useWordChars=False) if start <= self.lastIndex and self.lastIndex <= end: doSpelling = False if doSpelling: @@ -1661,10 +1710,11 @@ def getFileTypeByFlag(self): """ - Public method to return the type of the file, if it was set by an eflag: marker. - - @return type of the displayed file, if set by an eflag: marker or an empty - string (string) + Public method to return the type of the file, if it was set by an + eflag: marker. + + @return type of the displayed file, if set by an eflag: marker or an + empty string (string) """ if self.filetypeByFlag: return self.filetype @@ -1726,7 +1776,8 @@ self.project.isOpen() and \ self.project.isProjectFile(self.fileName): isProjectPy2 = \ - self.project.getProjectLanguage() in ["Python", "Python2"] + self.project.getProjectLanguage() in ["Python", + "Python2"] if isProjectPy2: self.filetype = "Python2" return isProjectPy2 @@ -1768,7 +1819,8 @@ if Preferences.getProject("DeterminePyFromProject") and \ self.project.isOpen() and \ self.project.isProjectFile(self.fileName): - isProjectPy3 = self.project.getProjectLanguage() in ["Python3"] + isProjectPy3 = \ + self.project.getProjectLanguage() in ["Python3"] if isProjectPy3: self.filetype = "Python3" return isProjectPy3 @@ -1803,7 +1855,8 @@ return True if self.fileName is not None and \ - os.path.splitext(self.fileName)[1] in self.dbs.getExtensions('Ruby'): + os.path.splitext(self.fileName)[1] in \ + self.dbs.getExtensions('Ruby'): self.filetype = "Ruby" return True @@ -1819,10 +1872,11 @@ def highlight(self, line=None, error=False, syntaxError=False): """ - Public method to highlight (or de-highlight) a particular line. + Public method to highlight [or de-highlight] a particular line. @param line line number to highlight (integer) - @param error flag indicating whether the error highlight should be used (boolean) + @param error flag indicating whether the error highlight should be + used (boolean) @param syntaxError flag indicating a syntax error (boolean) """ if line is None: @@ -1842,7 +1896,8 @@ else: if self.lastCurrMarker is not None: self.markerDeleteHandle(self.lastCurrMarker) - self.lastCurrMarker = self.markerAdd(line - 1, self.currentline) + self.lastCurrMarker = self.markerAdd(line - 1, + self.currentline) self.lastHighlight = self.lastCurrMarker self.setCursorPosition(line - 1, 0) @@ -1857,12 +1912,12 @@ else: return 1 - ############################################################################ + ########################################################################### ## Breakpoint handling methods below - ############################################################################ + ########################################################################### - def __modified(self, pos, mtype, text, length, linesAdded, line, foldNow, foldPrev, - token, annotationLinesAdded): + def __modified(self, pos, mtype, text, length, linesAdded, line, foldNow, + foldPrev, token, annotationLinesAdded): """ Private method to handle changes of the number of lines. @@ -1875,20 +1930,24 @@ @param foldNow new fold level (integer) @param foldPrev previous fold level (integer) @param token ??? - @param annotationLinesAdded number of added/deleted annotation lines (integer) + @param annotationLinesAdded number of added/deleted annotation lines + (integer) """ if mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) and \ linesAdded != 0: if self.breaks: bps = [] # list of breakpoints - for handle, (ln, cond, temp, enabled, ignorecount) in self.breaks.items(): + for handle, (ln, cond, temp, enabled, ignorecount) in \ + self.breaks.items(): line = self.markerLine(handle) + 1 if ln != line: bps.append((ln, line)) - self.breaks[handle] = (line, cond, temp, enabled, ignorecount) + self.breaks[handle] = (line, cond, temp, enabled, + ignorecount) self.inLinesChanged = True for ln, line in sorted(bps, reverse=linesAdded > 0): - index1 = self.breakpointModel.getBreakPointIndex(self.fileName, ln) + index1 = self.breakpointModel.getBreakPointIndex( + self.fileName, ln) index2 = self.breakpointModel.index(index1.row(), 1) self.breakpointModel.setData(index2, line) self.inLinesChanged = False @@ -1899,7 +1958,8 @@ """ for handle in list(self.breaks.keys()): self.markerDeleteHandle(handle) - self.__addBreakPoints(QModelIndex(), 0, self.breakpointModel.rowCount() - 1) + self.__addBreakPoints( + QModelIndex(), 0, self.breakpointModel.rowCount() - 1) def __deleteBreakPoints(self, parentIndex, start, end): """ @@ -1919,19 +1979,25 @@ """ Private slot to set changed breakpoints. - @param indexes indexes of changed breakpoints. + @param startIndex start index of the breakpoints being changed + (QModelIndex) + @param endIndex end index of the breakpoints being changed + (QModelIndex) """ if not self.inLinesChanged: - self.__addBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) + self.__addBreakPoints(QModelIndex(), startIndex.row(), + endIndex.row()) def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): """ - Private slot to handle the dataAboutToBeChanged signal of the breakpoint model. + Private slot to handle the dataAboutToBeChanged signal of the + breakpoint model. @param startIndex start index of the rows to be changed (QModelIndex) @param endIndex end index of the rows to be changed (QModelIndex) """ - self.__deleteBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) + self.__deleteBreakPoints(QModelIndex(), startIndex.row(), + endIndex.row()) def __addBreakPoints(self, parentIndex, start, end): """ @@ -1946,7 +2012,8 @@ fn, line, cond, temp, enabled, ignorecount = \ self.breakpointModel.getBreakPointByIndex(index)[:6] if fn == self.fileName: - self.newBreakpointWithProperties(line, (cond, temp, enabled, ignorecount)) + self.newBreakpointWithProperties( + line, (cond, temp, enabled, ignorecount)) def clearBreakpoint(self, line): """ @@ -2000,9 +2067,11 @@ for handle, (ln, _, _, _, _) in list(self.breaks.items()): if self.markerLine(handle) == line - 1: # delete breakpoint or toggle it to the next state - index = self.breakpointModel.getBreakPointIndex(self.fileName, line) + index = self.breakpointModel.getBreakPointIndex( + self.fileName, line) if Preferences.getDebugger("ThreeStateBreakPoints") and \ - not self.breakpointModel.isBreakPointTemporaryByIndex(index): + not self.breakpointModel.isBreakPointTemporaryByIndex( + index): self.breakpointModel.deleteBreakPointByIndex(index) self.__addBreakPoint(line, True) else: @@ -2031,7 +2100,8 @@ @param line line number of the breakpoint (integer) """ - for handle, (ln, cond, temp, enabled, ignorecount) in list(self.breaks.items()): + for handle, (ln, cond, temp, enabled, ignorecount) in \ + self.breaks.items(): if self.markerLine(handle) == line - 1: break else: @@ -2043,7 +2113,8 @@ def curLineHasBreakpoint(self): """ - Public method to check for the presence of a breakpoint at the current line. + Public method to check for the presence of a breakpoint at the current + line. @return flag indicating the presence of a breakpoint (boolean) """ @@ -2060,7 +2131,8 @@ def __menuToggleTemporaryBreakpoint(self): """ - Private slot to handle the 'Toggle temporary breakpoint' context menu action. + Private slot to handle the 'Toggle temporary breakpoint' context menu + action. """ if self.line < 0: self.line, index = self.getCursorPosition() @@ -2080,7 +2152,8 @@ def __menuToggleBreakpointEnabled(self): """ - Private slot to handle the 'Enable/Disable breakpoint' context menu action. + Private slot to handle the 'Enable/Disable breakpoint' context menu + action. """ if self.line < 0: self.line, index = self.getCursorPosition() @@ -2099,7 +2172,8 @@ if self.line < 0: self.line, index = self.getCursorPosition() found = False - for handle, (ln, cond, temp, enabled, ignorecount) in list(self.breaks.items()): + for handle, (ln, cond, temp, enabled, ignorecount) in \ + self.breaks.items(): if self.markerLine(handle) == self.line: found = True break @@ -2149,7 +2223,8 @@ bpline = self.markerFindPrevious(line, self.breakpointMask) if bpline < 0: # wrap around - bpline = self.markerFindPrevious(self.lines() - 1, self.breakpointMask) + bpline = self.markerFindPrevious( + self.lines() - 1, self.breakpointMask) if bpline >= 0: self.setCursorPosition(bpline, 0) self.ensureLineVisible(bpline) @@ -2163,6 +2238,8 @@ def __clearBreakpoints(self, fileName): """ Private slot to clear all breakpoints. + + @param fileName name of the file (string) """ idxList = [] for handle, (ln, _, _, _, _) in list(self.breaks.items()): @@ -2172,9 +2249,9 @@ if idxList: self.breakpointModel.deleteBreakPoints(idxList) - ############################################################################ + ########################################################################### ## Bookmark handling methods below - ############################################################################ + ########################################################################### def toggleBookmark(self, line): """ @@ -2257,7 +2334,8 @@ bmline = self.markerFindPrevious(line, 1 << self.bookmark) if bmline < 0: # wrap around - bmline = self.markerFindPrevious(self.lines() - 1, 1 << self.bookmark) + bmline = self.markerFindPrevious( + self.lines() - 1, 1 << self.bookmark) if bmline >= 0: self.setCursorPosition(bmline, 0) self.ensureLineVisible(bmline) @@ -2271,9 +2349,9 @@ self.bookmarks = [] self.bookmarkToggled.emit(self) - ############################################################################ + ########################################################################### ## Printing methods below - ############################################################################ + ########################################################################### def printFile(self): """ @@ -2332,13 +2410,14 @@ """ Private slot to generate a print preview. - @param printer reference to the printer object (QScintilla.Printer.Printer) + @param printer reference to the printer object + (QScintilla.Printer.Printer) """ printer.printRange(self) - ############################################################################ + ########################################################################### ## Task handling methods below - ############################################################################ + ########################################################################### def hasTaskMarkers(self): """ @@ -2377,7 +2456,8 @@ taskline = self.markerFindPrevious(line, 1 << self.taskmarker) if taskline < 0: # wrap around - taskline = self.markerFindPrevious(self.lines() - 1, 1 << self.taskmarker) + taskline = self.markerFindPrevious( + self.lines() - 1, 1 << self.taskmarker) if taskline >= 0: self.setCursorPosition(taskline, 0) self.ensureLineVisible(taskline) @@ -2388,10 +2468,14 @@ """ from Tasks.Task import Task markers = { - Task.TypeWarning: Preferences.getTasks("TasksWarningMarkers").split(), - Task.TypeNote: Preferences.getTasks("TasksNoteMarkers").split(), - Task.TypeTodo: Preferences.getTasks("TasksTodoMarkers").split(), - Task.TypeFixme: Preferences.getTasks("TasksFixmeMarkers").split(), + Task.TypeWarning: + Preferences.getTasks("TasksWarningMarkers").split(), + Task.TypeNote: + Preferences.getTasks("TasksNoteMarkers").split(), + Task.TypeTodo: + Preferences.getTasks("TasksTodoMarkers").split(), + Task.TypeFixme: + Preferences.getTasks("TasksFixmeMarkers").split(), } txtList = self.text().split(self.getLineSeparator()) @@ -2412,8 +2496,8 @@ if index > -1: task = line[index:] self.markerAdd(lineIndex, self.taskmarker) - self.taskViewer.addFileTask(task, self.fileName, lineIndex + 1, - taskType) + self.taskViewer.addFileTask( + task, self.fileName, lineIndex + 1, taskType) self.__hasTaskMarkers = True shouldBreak = True break @@ -2421,9 +2505,9 @@ break self.taskMarkersUpdated.emit(self) - ############################################################################ + ########################################################################### ## Change tracing methods below - ############################################################################ + ########################################################################### def __createChangeMarkerPixmap(self, key, size=16, width=4): """ @@ -2437,7 +2521,8 @@ pixmap = QPixmap(size, size) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) - painter.fillRect(size - 4, 0, 4, size, Preferences.getEditorColour(key)) + painter.fillRect(size - 4, 0, 4, size, + Preferences.getEditorColour(key)) painter.end() return pixmap @@ -2570,36 +2655,47 @@ changeline = self.markerFindPrevious(line, self.changeMarkersMask) if changeline < 0: # wrap around - changeline = self.markerFindPrevious(self.lines() - 1, self.changeMarkersMask) + changeline = self.markerFindPrevious( + self.lines() - 1, self.changeMarkersMask) if changeline >= 0: self.setCursorPosition(changeline, 0) self.ensureLineVisible(changeline) - ############################################################################ + ########################################################################### ## Flags handling methods below - ############################################################################ + ########################################################################### def __processFlags(self): """ Private method to extract flags and process them. + + @return list of change flags (list of string) """ txt = self.text() flags = Utilities.extractFlags(txt) + changedFlags = [] + # Flag 1: FileType if "FileType" in flags: + oldFiletype = self.filetype if isinstance(flags["FileType"], str): self.filetype = flags["FileType"] self.filetypeByFlag = True + if oldFiletype != self.filetype: + changedFlags.append("FileType") else: if self.filetype != "" and self.filetypeByFlag: self.filetype = "" self.filetypeByFlag = False self.__bindName(txt.splitlines()[0]) + changedFlags.append("FileType") + + return changedFlags - ############################################################################ + ########################################################################### ## File handling methods below - ############################################################################ + ########################################################################### def checkDirty(self): """ @@ -2647,8 +2743,8 @@ Public slot to read the text from a file. @param fn filename to read from (string) - @param createIt flag indicating the creation of a new file, if the given - one doesn't exist (boolean) + @param createIt flag indicating the creation of a new file, if the + given one doesn't exist (boolean) """ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) @@ -2792,11 +2888,13 @@ if not path and self.fileName is not None: path = os.path.dirname(self.fileName) if not path: - path = Preferences.getMultiProject("Workspace") or Utilities.getHomeDir() + path = Preferences.getMultiProject("Workspace") or \ + Utilities.getHomeDir() from . import Lexers if self.fileName: - filterPattern = "(*{0})".format(os.path.splitext(self.fileName)[1]) + filterPattern = "(*{0})".format( + os.path.splitext(self.fileName)[1]) for filter in Lexers.getSaveFileFiltersList(True): if filterPattern in filter: defaultFilter = filter @@ -2836,7 +2934,8 @@ return False # save to project, if a project is loaded - if self.project.isOpen() and self.project.startswithProjectPath(fn): + if self.project.isOpen() and \ + self.project.startswithProjectPath(fn): self.setEolModeByEolString(self.project.getEolString()) self.convertEols(self.eolMode()) else: @@ -2851,8 +2950,8 @@ self.setReadOnly(False) self.setWindowTitle(self.fileName) # get eric specific flags - self.__processFlags() - if not self.__lexerReset: + changedFlags = self.__processFlags() + if not self.__lexerReset and "FileType" in changedFlags: self.setLanguage(self.fileName) if saveas: @@ -2861,7 +2960,8 @@ self.editorRenamed.emit(self.fileName) # save to project, if a project is loaded - if self.project.isOpen() and self.project.startswithProjectPath(fn): + if self.project.isOpen() and \ + self.project.startswithProjectPath(fn): self.project.appendFile(self.fileName) self.addedToProject() self.setLanguage(self.fileName) @@ -2883,9 +2983,10 @@ Public slot to save a file with a new name. @param path directory to save the file in (string) - @keyparam toProject flag indicating a save to project operation (boolean) - @return tuple of two values (boolean, string) giving a success indicator and - the name of the saved file + @keyparam toProject flag indicating a save to project operation + (boolean) + @return tuple of two values (boolean, string) giving a success + indicator and the name of the saved file """ return self.saveFile(True, path) @@ -2919,9 +3020,9 @@ self.editorRenamed.emit(self.fileName) self.inFileRenamed = False - ############################################################################ + ########################################################################### ## Utility methods below - ############################################################################ + ########################################################################### def ensureVisible(self, line): """ @@ -2984,7 +3085,8 @@ self.setMonospaced(True) else: if self.lexer_: - self.lexer_.readSettings(Preferences.Prefs.settings, "Scintilla") + self.lexer_.readSettings( + Preferences.Prefs.settings, "Scintilla") self.lexer_.initProperties() self.setMonospaced(False) self.__setMarginsDisplay() @@ -3029,7 +3131,8 @@ @param line number of line to look at (int) @param index position to look at (int) - @param direction direction to look in (0 = whole word, 1 = left, 2 = right) + @param direction direction to look in (0 = whole word, 1 = left, + 2 = right) @keyparam useWordChars flag indicating to use the wordCharacters method (boolean) @return the word at that position (string) @@ -3125,8 +3228,8 @@ def getSearchText(self, selectionOnly=False): """ - Public method to determine the selection or the current word for the next - search operation. + Public method to determine the selection or the current word for the + next search operation. @param selectionOnly flag indicating that only selected text should be returned (boolean) @@ -3176,21 +3279,22 @@ return self.clearSearchIndicators() - ok = self.findFirstTarget(word, False, self.caseSensitive(), True, 0, 0) + ok = self.findFirstTarget(word, False, self.caseSensitive(), True, + 0, 0) while ok: tgtPos, tgtLen = self.getFoundTarget() self.setSearchIndicator(tgtPos, tgtLen) ok = self.findNextTarget() self.__markedText = word - ############################################################################ + ########################################################################### ## Comment handling methods below - ############################################################################ + ########################################################################### def __isCommentedLine(self, line, commentStr): """ - Private method to check, if the given line is a comment line as produced - by the configured comment rules. + Private method to check, if the given line is a comment line as + produced by the configured comment rules. @param line text of the line to check (string) @param commentStr comment string to check against (string) @@ -3218,7 +3322,8 @@ # check if line starts with our comment string (i.e. was commented # by our comment...() slots if self.hasSelectedText() and \ - self.__isCommentedLine(self.text(self.getSelection()[0]), commentStr): + self.__isCommentedLine(self.text(self.getSelection()[0]), + commentStr): self.uncommentLineOrSelection() elif not self.__isCommentedLine(self.text(line), commentStr): # it doesn't, so comment the line or selection @@ -3254,7 +3359,8 @@ if Preferences.getEditor("CommentColumn0"): self.insertAt(self.lexer_.commentStr(), line, 0) else: - self.insertAt(self.lexer_.commentStr(), line, self.indentation(line)) + self.insertAt(self.lexer_.commentStr(), line, + self.indentation(line)) self.endUndoAction() def uncommentLine(self): @@ -3343,8 +3449,10 @@ if Preferences.getEditor("CommentColumn0"): self.setSelection(line, 0, line, len(commentStr)) else: - self.setSelection(line, self.indentation(line), - line, self.indentation(line) + len(commentStr)) + self.setSelection(line, + self.indentation(line), + line, + self.indentation(line) + len(commentStr)) self.removeSelectedText() # adjust selection start @@ -3501,9 +3609,9 @@ else: self.boxCommentLine() - ############################################################################ + ########################################################################### ## Indentation handling methods below - ############################################################################ + ########################################################################### def __indentLine(self, indent=True): """ @@ -3554,11 +3662,13 @@ self.endUndoAction() if indent: if indexTo == 0: - self.setSelection(lineFrom, indexFrom + self.indentationWidth(), - lineTo, 0) + self.setSelection( + lineFrom, indexFrom + self.indentationWidth(), + lineTo, 0) else: - self.setSelection(lineFrom, indexFrom + self.indentationWidth(), - lineTo, indexTo + self.indentationWidth()) + self.setSelection( + lineFrom, indexFrom + self.indentationWidth(), + lineTo, indexTo + self.indentationWidth()) else: indexStart = indexFrom - self.indentationWidth() if indexStart < 0: @@ -3570,7 +3680,7 @@ def indentLineOrSelection(self): """ - Public slot to indent the current line or current selection + Public slot to indent the current line or current selection. """ if self.hasSelectedText(): self.__indentSelection(True) @@ -3651,6 +3761,8 @@ def gotoMethodClass(self, goUp=False): """ Public method to go to the next Python method or class definition. + + @param goUp flag indicating the move direction (boolean) """ if self.isPy3File() or self.isPy2File() or self.isRubyFile(): lineNo = self.getCursorPosition()[0] @@ -3697,9 +3809,9 @@ else: lineNo += 1 - ############################################################################ + ########################################################################### ## Setup methods below - ############################################################################ + ########################################################################### def readSettings(self): """ @@ -3783,14 +3895,14 @@ """ Private method to set the line marker colours. """ - self.setMarkerForegroundColor(Preferences.getEditorColour("CurrentMarker"), - self.currentline) - self.setMarkerBackgroundColor(Preferences.getEditorColour("CurrentMarker"), - self.currentline) - self.setMarkerForegroundColor(Preferences.getEditorColour("ErrorMarker"), - self.errorline) - self.setMarkerBackgroundColor(Preferences.getEditorColour("ErrorMarker"), - self.errorline) + self.setMarkerForegroundColor( + Preferences.getEditorColour("CurrentMarker"), self.currentline) + self.setMarkerBackgroundColor( + Preferences.getEditorColour("CurrentMarker"), self.currentline) + self.setMarkerForegroundColor( + Preferences.getEditorColour("ErrorMarker"), self.errorline) + self.setMarkerBackgroundColor( + Preferences.getEditorColour("ErrorMarker"), self.errorline) def __setMarginsDisplay(self): """ @@ -3798,8 +3910,10 @@ """ # set the settings for all margins self.setMarginsFont(Preferences.getEditorOtherFonts("MarginsFont")) - self.setMarginsForegroundColor(Preferences.getEditorColour("MarginsForeground")) - self.setMarginsBackgroundColor(Preferences.getEditorColour("MarginsBackground")) + self.setMarginsForegroundColor( + Preferences.getEditorColour("MarginsForeground")) + self.setMarginsBackgroundColor( + Preferences.getEditorColour("MarginsBackground")) # reset standard margins settings for margin in range(5): @@ -3897,7 +4011,8 @@ """ linenoMargin = Preferences.getEditor("LinenoMargin") if linenoMargin: - self.setMarginWidth(self.__linenoMargin, '8' * (len(str(self.lines())) + 1)) + self.setMarginWidth( + self.__linenoMargin, '8' * (len(str(self.lines())) + 1)) def __setTextDisplay(self): """ @@ -3908,7 +4023,8 @@ if self.lexer_ and self.lexer_.alwaysKeepTabs(): self.setIndentationsUseTabs(True) else: - self.setIndentationsUseTabs(Preferences.getEditor("TabForIndentation")) + self.setIndentationsUseTabs( + Preferences.getEditor("TabForIndentation")) self.setTabIndents(Preferences.getEditor("TabIndents")) self.setBackspaceUnindents(Preferences.getEditor("TabIndents")) self.setIndentationGuides(Preferences.getEditor("IndentationGuides")) @@ -3986,7 +4102,8 @@ self.clearAllIndicators(self.searchIndicator) self.spellingIndicator = QsciScintilla.INDIC_CONTAINER + 1 - self.indicatorDefine(self.spellingIndicator, QsciScintilla.INDIC_SQUIGGLE, + self.indicatorDefine( + self.spellingIndicator, QsciScintilla.INDIC_SQUIGGLE, Preferences.getEditorColour("SpellingMarkers")) self.__setSpelling() @@ -4005,7 +4122,8 @@ self.setColor(Preferences.getEditorColour("EditAreaForeground")) self.setPaper(Preferences.getEditorColour("EditAreaBackground")) - self.setVirtualSpaceOptions(Preferences.getEditor("VirtualSpaceOptions")) + self.setVirtualSpaceOptions( + Preferences.getEditor("VirtualSpaceOptions")) def __setEolMode(self): """ @@ -4066,20 +4184,23 @@ calltipsStyle = Preferences.getEditor("CallTipsStyle") if calltipsStyle == QsciScintilla.CallTipsNoContext: self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) - elif calltipsStyle == QsciScintilla.CallTipsNoAutoCompletionContext: - self.setCallTipsStyle(QsciScintilla.CallTipsNoAutoCompletionContext) + elif calltipsStyle == \ + QsciScintilla.CallTipsNoAutoCompletionContext: + self.setCallTipsStyle( + QsciScintilla.CallTipsNoAutoCompletionContext) else: self.setCallTipsStyle(QsciScintilla.CallTipsContext) try: - self.setCallTipsPosition(Preferences.getEditor("CallTipsPosition")) + self.setCallTipsPosition( + Preferences.getEditor("CallTipsPosition")) except AttributeError: pass else: self.setCallTipsStyle(QsciScintilla.CallTipsNone) - ############################################################################ + ########################################################################### ## Autocompletion handling methods below - ############################################################################ + ########################################################################### def canAutoCompleteFromAPIs(self): """ @@ -4110,12 +4231,14 @@ """ Public method to enable/disable autocompletion. - @param enable flag indicating the desired autocompletion status (boolean) + @param enable flag indicating the desired autocompletion status + (boolean) """ if enable: self.setAutoCompletionThreshold( Preferences.getEditor("AutoCompletionThreshold")) - autoCompletionSource = Preferences.getEditor("AutoCompletionSource") + autoCompletionSource = \ + Preferences.getEditor("AutoCompletionSource") if autoCompletionSource == QsciScintilla.AcsDocument: self.setAutoCompletionSource(QsciScintilla.AcsDocument) elif autoCompletionSource == QsciScintilla.AcsAPIs: @@ -4172,7 +4295,8 @@ def __isStartChar(self, ch): """ - Private method to check, if a character is an autocompletion start character. + Private method to check, if a character is an autocompletion start + character. @param ch character to be checked (one character string) @return flag indicating the result (boolean) @@ -4231,7 +4355,8 @@ """ Public method to start autocompletion. - @keyparam auto flag indicating a call from the __charAdded method (boolean) + @keyparam auto flag indicating a call from the __charAdded method + (boolean) @keyparam context flag indicating to complete a context (boolean) """ if auto and self.autoCompletionThreshold() == -1: @@ -4260,8 +4385,8 @@ """ pos = self.currentPosition() - # move backward to the start of the current calltip working out which argument - # to highlight + # move backward to the start of the current calltip working out + # which argument to highlight commas = 0 found = False ch, pos = self.__getCharacter(pos) @@ -4271,7 +4396,8 @@ elif ch == ')': depth = 1 - # ignore everything back to the start of the corresponding parenthesis + # ignore everything back to the start of the corresponding + # parenthesis ch, pos = self.__getCharacter(pos) while ch: if ch == ')': @@ -4350,7 +4476,8 @@ depth -= 1 if astart != aend: - self.SendScintilla(QsciScintilla.SCI_CALLTIPSETHLT, astart + 1, aend) + self.SendScintilla(QsciScintilla.SCI_CALLTIPSETHLT, + astart + 1, aend) def __adjustedCallTipPosition(self, ctshift, pos): """ @@ -4443,7 +4570,8 @@ if self.__unifiedMargins: self.marginMenu.popup(evt.globalPos()) else: - if self.__marginNumber(evt.x()) in [self.__bmMargin, self.__linenoMargin]: + if self.__marginNumber(evt.x()) in [self.__bmMargin, + self.__linenoMargin]: self.bmMarginMenu.popup(evt.globalPos()) elif self.__marginNumber(evt.x()) == self.__bpMargin: self.bpMarginMenu.popup(evt.globalPos()) @@ -4474,17 +4602,22 @@ self.menuActs["Diagrams"].setEnabled(False) if not self.miniMenu: if self.lexer_ is not None: - self.menuActs["Comment"].setEnabled(self.lexer_.canBlockComment()) - self.menuActs["Uncomment"].setEnabled(self.lexer_.canBlockComment()) - self.menuActs["StreamComment"].setEnabled(self.lexer_.canStreamComment()) - self.menuActs["BoxComment"].setEnabled(self.lexer_.canBoxComment()) + self.menuActs["Comment"].setEnabled( + self.lexer_.canBlockComment()) + self.menuActs["Uncomment"].setEnabled( + self.lexer_.canBlockComment()) + self.menuActs["StreamComment"].setEnabled( + self.lexer_.canStreamComment()) + self.menuActs["BoxComment"].setEnabled( + self.lexer_.canBoxComment()) else: self.menuActs["Comment"].setEnabled(False) self.menuActs["Uncomment"].setEnabled(False) self.menuActs["StreamComment"].setEnabled(False) self.menuActs["BoxComment"].setEnabled(False) - self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None) + self.menuActs["TypingAidsEnabled"].setEnabled( + self.completer is not None) self.menuActs["TypingAidsEnabled"].setChecked( self.completer is not None and self.completer.isEnabled()) @@ -4525,7 +4658,8 @@ coEnable = False # first check if the file belongs to a project - if self.project.isOpen() and self.project.isProjectSource(self.fileName): + if self.project.isOpen() and \ + self.project.isProjectSource(self.fileName): fn = self.project.getMainScript(True) if fn is not None: tfn = Utilities.getTestFileName(fn) @@ -4568,9 +4702,11 @@ def __showContextMenuGraphics(self): """ - Private slot handling the aboutToShow signal of the diagrams context menu. - """ - if self.project.isOpen() and self.project.isProjectSource(self.fileName): + Private slot handling the aboutToShow signal of the diagrams context + menu. + """ + if self.project.isOpen() and \ + self.project.isProjectSource(self.fileName): self.applicationDiagramMenuAct.setEnabled(True) else: self.applicationDiagramMenuAct.setEnabled(False) @@ -4579,7 +4715,8 @@ def __showContextMenuMargin(self): """ - Private slot handling the aboutToShow signal of the margins context menu. + Private slot handling the aboutToShow signal of the margins context + menu. """ if self.fileName and \ (self.isPy3File() or self.isPy2File() or self.isRubyFile()): @@ -4674,7 +4811,8 @@ def __showContextMenuChecks(self): """ - Private slot handling the aboutToShow signal of the checks context menu. + Private slot handling the aboutToShow signal of the checks context + menu. """ self.showMenu.emit("Checks", self.checksMenu, self) @@ -4747,16 +4885,25 @@ if line1Text in ["", "\r", "\n", "\r\n"]: return + if line0Text.rstrip("\r\n\\ \t").endswith(("'", '"')) and \ + line1Text.lstrip().startswith(("'", '"')): + # merging multi line strings + startChars = "\r\n\\ \t'\"" + endChars = " \t'\"" + else: + startChars = "\r\n\\ \t" + endChars = " \t" + # determine start index startIndex = len(line0Text) - while startIndex > 0 and line0Text[startIndex - 1] in "\r\n\\ \t": + while startIndex > 0 and line0Text[startIndex - 1] in startChars: startIndex -= 1 if startIndex == 0: return # determine end index endIndex = 0 - while line1Text[endIndex] in " \t": + while line1Text[endIndex] in endChars: endIndex += 1 self.setSelection(curLine, startIndex, curLine + 1, endIndex) @@ -4767,7 +4914,8 @@ def shortenEmptyLines(self): """ - Public slot to compress lines consisting solely of whitespace characters. + Public slot to compress lines consisting solely of whitespace + characters. """ searchRE = r"^[ \t]+$" @@ -4807,6 +4955,8 @@ return if Preferences.getEditor("AutoCheckSyntax"): + if Preferences.getEditor("OnlineSyntaxCheck"): + self.__onlineSyntaxCheckTimer.stop() self.clearSyntaxError() self.clearFlakesWarnings() @@ -4818,7 +4968,6 @@ for warning in warnings: self.toggleFlakesWarning( warning[2], True, warning[3]) - return def __initOnlineSyntaxCheck(self): @@ -4854,7 +5003,8 @@ def __getCodeCoverageFile(self): """ - Private method to get the filename of the file containing coverage info. + Private method to get the filename of the file containing coverage + info. @return filename of the coverage file (string) """ @@ -4862,7 +5012,8 @@ # first check if the file belongs to a project and there is # a project coverage file - if self.project.isOpen() and self.project.isProjectSource(self.fileName): + if self.project.isOpen() and \ + self.project.isProjectSource(self.fileName): fn = self.project.getMainScript(True) if fn is not None: tfn = Utilities.getTestFileName(fn) @@ -4927,7 +5078,8 @@ def codeCoverageShowAnnotations(self, silent=False): """ - Public method to handle the show code coverage annotations context menu action. + Public method to handle the show code coverage annotations context + menu action. @param silent flag indicating to not show any dialog (boolean) """ @@ -4959,7 +5111,8 @@ def __codeCoverageHideAnnotations(self): """ - Private method to handle the hide code coverage annotations context menu action. + Private method to handle the hide code coverage annotations context + menu action. """ for handle in self.notcoveredMarkers: self.markerDeleteHandle(handle) @@ -4970,6 +5123,8 @@ def hasCoverageMarkers(self): """ Public method to test, if there are coverage markers. + + @return flag indicating the presence of coverage markers (boolean) """ return len(self.notcoveredMarkers) > 0 @@ -5002,7 +5157,8 @@ ucline = self.markerFindPrevious(line, 1 << self.notcovered) if ucline < 0: # wrap around - ucline = self.markerFindPrevious(self.lines() - 1, 1 << self.notcovered) + ucline = self.markerFindPrevious( + self.lines() - 1, 1 << self.notcovered) if ucline >= 0: self.setCursorPosition(ucline, 0) self.ensureLineVisible(ucline) @@ -5015,7 +5171,8 @@ # first check if the file belongs to a project and there is # a project profile file - if self.project.isOpen() and self.project.isProjectSource(self.fileName): + if self.project.isOpen() and \ + self.project.isProjectSource(self.fileName): fn = self.project.getMainScript(True) if fn is not None: tfn = Utilities.getTestFileName(fn) @@ -5065,21 +5222,23 @@ def __lmBbookmarks(self): """ - Private method to handle the 'LMB toggles bookmark' context menu action. + Private method to handle the 'LMB toggles bookmark' context menu + action. """ self.marginMenuActs["LMBbookmarks"].setChecked(True) self.marginMenuActs["LMBbreakpoints"].setChecked(False) def __lmBbreakpoints(self): """ - Private method to handle the 'LMB toggles breakpoint' context menu action. + Private method to handle the 'LMB toggles breakpoint' context menu + action. """ self.marginMenuActs["LMBbookmarks"].setChecked(True) self.marginMenuActs["LMBbreakpoints"].setChecked(False) - ############################################################################ + ########################################################################### ## Syntax error handling methods below - ############################################################################ + ########################################################################### def toggleSyntaxError(self, line, index, error, msg="", show=False): """ @@ -5186,16 +5345,16 @@ self.trUtf8("Syntax Error"), self.trUtf8("No syntax error message available.")) - ############################################################################ + ########################################################################### ## Flakes warning handling methods below - ############################################################################ + ########################################################################### def toggleFlakesWarning(self, line, warning, msg="", warningType=WarningCode): """ Public method to toggle a flakes warning indicator. - Note: This method is used to set PEP 8 warnings as well. + Note: This method is used to set code style warnings as well. @param line line number of the flakes warning @param warning flag indicating if the warning marker should be @@ -5279,7 +5438,8 @@ fwline = self.markerFindPrevious(line, 1 << self.warning) if fwline < 0: # wrap around - fwline = self.markerFindPrevious(self.lines() - 1, 1 << self.warning) + fwline = self.markerFindPrevious( + self.lines() - 1, 1 << self.warning) if fwline >= 0: self.setCursorPosition(fwline, 0) self.ensureLineVisible(fwline) @@ -5308,43 +5468,50 @@ if self.markerLine(handle) == line: E5MessageBox.warning(self, self.trUtf8("Warning"), - '\n'.join(self.warnings[handle])) + '\n'.join([w[0] for w in self.warnings[handle]])) break else: E5MessageBox.warning(self, self.trUtf8("Warning"), self.trUtf8("No warning messages available.")) - ############################################################################ + ########################################################################### ## Annotation handling methods below - ############################################################################ + ########################################################################### def __setAnnotationStyles(self): """ Private slot to define the style used by inline annotations. """ if hasattr(QsciScintilla, "annotate"): - self.annotationWarningStyle = QsciScintilla.STYLE_LASTPREDEFINED + 1 - self.SendScintilla(QsciScintilla.SCI_STYLESETFORE, + self.annotationWarningStyle = \ + QsciScintilla.STYLE_LASTPREDEFINED + 1 + self.SendScintilla( + QsciScintilla.SCI_STYLESETFORE, self.annotationWarningStyle, Preferences.getEditorColour("AnnotationsWarningForeground")) - self.SendScintilla(QsciScintilla.SCI_STYLESETBACK, + self.SendScintilla( + QsciScintilla.SCI_STYLESETBACK, self.annotationWarningStyle, Preferences.getEditorColour("AnnotationsWarningBackground")) self.annotationErrorStyle = self.annotationWarningStyle + 1 - self.SendScintilla(QsciScintilla.SCI_STYLESETFORE, + self.SendScintilla( + QsciScintilla.SCI_STYLESETFORE, self.annotationErrorStyle, Preferences.getEditorColour("AnnotationsErrorForeground")) - self.SendScintilla(QsciScintilla.SCI_STYLESETBACK, + self.SendScintilla( + QsciScintilla.SCI_STYLESETBACK, self.annotationErrorStyle, Preferences.getEditorColour("AnnotationsErrorBackground")) self.annotationStyleStyle = self.annotationErrorStyle + 1 - self.SendScintilla(QsciScintilla.SCI_STYLESETFORE, + self.SendScintilla( + QsciScintilla.SCI_STYLESETFORE, self.annotationStyleStyle, Preferences.getEditorColour("AnnotationsStyleForeground")) - self.SendScintilla(QsciScintilla.SCI_STYLESETBACK, + self.SendScintilla( + QsciScintilla.SCI_STYLESETBACK, self.annotationStyleStyle, Preferences.getEditorColour("AnnotationsStyleBackground")) @@ -5377,26 +5544,22 @@ errorAnnotations.append( self.trUtf8("Error: {0}").format(msg)) - wLen = len(warningAnnotations) - eLen = len(errorAnnotations) - sLen = len(styleAnnotations) annotations = [] - - if sLen: + if styleAnnotations: annotationStyleTxt = "\n".join(styleAnnotations) - if wLen: + if warningAnnotations or errorAnnotations: annotationStyleTxt += "\n" annotations.append(QsciStyledText(annotationStyleTxt, self.annotationStyleStyle)) - if wLen: + if warningAnnotations: annotationWarningTxt = "\n".join(warningAnnotations) - if eLen: + if errorAnnotations: annotationWarningTxt += "\n" annotations.append(QsciStyledText(annotationWarningTxt, self.annotationWarningStyle)) - if eLen: + if errorAnnotations: annotationErrorTxt = "\n".join(errorAnnotations) annotations.append(QsciStyledText(annotationErrorTxt, self.annotationErrorStyle)) @@ -5412,7 +5575,8 @@ """ if hasattr(QsciScintilla, "annotate"): self.clearAnnotations() - for handle in list(self.warnings.keys()) + list(self.syntaxerrors.keys()): + for handle in list(self.warnings.keys()) + \ + list(self.syntaxerrors.keys()): line = self.markerLine(handle) self.__setAnnotation(line) @@ -5424,8 +5588,8 @@ """ Private method to select a macro name from the list of macros. - @return Tuple of macro name and a flag, indicating, if the user pressed ok or - canceled the operation. (string, boolean) + @return Tuple of macro name and a flag, indicating, if the user + pressed ok or canceled the operation. (string, boolean) """ qs = [] for s in list(self.macros.keys()): @@ -5475,7 +5639,8 @@ except IOError: E5MessageBox.critical(self, self.trUtf8("Error loading macro"), - self.trUtf8("<p>The macro file <b>{0}</b> could not be read.</p>") + self.trUtf8( + "<p>The macro file <b>{0}</b> could not be read.</p>") .format(fname)) return @@ -5533,7 +5698,8 @@ except IOError: E5MessageBox.critical(self, self.trUtf8("Error saving macro"), - self.trUtf8("<p>The macro file <b>{0}</b> could not be written.</p>") + self.trUtf8( + "<p>The macro file <b>{0}</b> could not be written.</p>") .format(fname)) return @@ -5607,6 +5773,7 @@ method. @param alsoDelete ignored + @return flag indicating a successful close of the editor (boolean) """ return self.vm.closeEditor(self) @@ -5664,7 +5831,8 @@ This method checks for modifications of the current file and rereads it upon request. The cursor is placed at the current position - assuming, that it is in the vicinity of the old position after the reread. + assuming, that it is in the vicinity of the old position after the + reread. @param event the event object (QFocusEvent) """ @@ -5688,8 +5856,9 @@ self.refresh() else: msg = self.trUtf8( - """<p>The file <b>{0}</b> has been changed while it was opened in""" - """ eric5. Reread it?</p>""").format(self.fileName) + """<p>The file <b>{0}</b> has been changed while it""" + """ was opened in eric5. Reread it?</p>""")\ + .format(self.fileName) yesDefault = True if self.isModified(): msg += self.trUtf8( @@ -5733,7 +5902,6 @@ with the QWorkspace. @param evt the event, that was generated (QEvent) - @return flag indicating if the event could be processed (bool) """ if evt.type() == QEvent.WindowStateChange and \ self.fileName is not None: @@ -5829,7 +5997,8 @@ """ if self.fileName is None: return - readOnly = not QFileInfo(self.fileName).isWritable() or self.isReadOnly() + readOnly = not QFileInfo(self.fileName).isWritable() or \ + self.isReadOnly() if not bForce and (readOnly == self.isReadOnly()): return cap = self.fileName @@ -5973,6 +6142,8 @@ def __initContextMenuResources(self): """ Private method used to setup the Resources context sub menu. + + @return reference to the generated menu (QMenu) """ menu = QMenu(self.trUtf8('Resources')) @@ -5994,7 +6165,8 @@ def __showContextMenuResources(self): """ - Private slot handling the aboutToShow signal of the resources context menu. + Private slot handling the aboutToShow signal of the resources context + menu. """ self.showMenu.emit("Resources", self.resourcesMenu, self) @@ -6060,7 +6232,8 @@ def __addLocalizedResource(self): """ - Private method to handle the Add localized resource context menu action. + Private method to handle the Add localized resource context menu + action. """ from Project.AddLanguageDialog import AddLanguageDialog dlg = AddLanguageDialog(self) @@ -6094,7 +6267,8 @@ if not self.checkDirty(): return - self.classDiagram = UMLDialog(UMLDialog.ClassDiagram, self.project, self.fileName, + self.classDiagram = UMLDialog( + UMLDialog.ClassDiagram, self.project, self.fileName, self, noAttrs=False) self.classDiagram.show() @@ -6106,14 +6280,15 @@ if not self.checkDirty(): return - package = os.path.isdir(self.fileName) and self.fileName \ - or os.path.dirname(self.fileName) + package = os.path.isdir(self.fileName) and \ + self.fileName or os.path.dirname(self.fileName) res = E5MessageBox.yesNo(self, self.trUtf8("Package Diagram"), self.trUtf8("""Include class attributes?"""), yesDefault=True) - self.packageDiagram = UMLDialog(UMLDialog.PackageDiagram, self.project, package, - self, noAttrs=not res) + self.packageDiagram = UMLDialog( + UMLDialog.PackageDiagram, self.project, package, + self, noAttrs=not res) self.packageDiagram.show() def __showImportsDiagram(self): @@ -6125,12 +6300,13 @@ return package = os.path.isdir(self.fileName) and self.fileName \ - or os.path.dirname(self.fileName) + or os.path.dirname(self.fileName) res = E5MessageBox.yesNo(self, self.trUtf8("Imports Diagram"), self.trUtf8("""Include imports from external modules?""")) - self.importsDiagram = UMLDialog(UMLDialog.ImportsDiagram, self.project, package, - self, showExternalImports=res) + self.importsDiagram = UMLDialog( + UMLDialog.ImportsDiagram, self.project, package, + self, showExternalImports=res) self.importsDiagram.show() def __showApplicationDiagram(self): @@ -6142,8 +6318,9 @@ self.trUtf8("Application Diagram"), self.trUtf8("""Include module names?"""), yesDefault=True) - self.applicationDiagram = UMLDialog(UMLDialog.ApplicationDiagram, self.project, - self, noModules=not res) + self.applicationDiagram = UMLDialog( + UMLDialog.ApplicationDiagram, self.project, + self, noModules=not res) self.applicationDiagram.show() def __loadDiagram(self): @@ -6151,7 +6328,8 @@ Private slot to load a diagram from file. """ from Graphics.UMLDialog import UMLDialog - self.loadedDiagram = UMLDialog(UMLDialog.NoDiagram, self.project, parent=self) + self.loadedDiagram = UMLDialog( + UMLDialog.NoDiagram, self.project, parent=self) if self.loadedDiagram.load(): self.loadedDiagram.show(fromFile=True) else: @@ -6193,7 +6371,8 @@ e5App().getObject("TemplateViewer").getTemplateNames( tmplName, self.getLanguage()) if len(templateNames) == 1: - self.__applyTemplate(templateNames[0], self.getLanguage()) + self.__applyTemplate(templateNames[0], + self.getLanguage()) return elif len(templateNames) > 1: self.showUserList(TemplateCompletionListID, @@ -6252,7 +6431,8 @@ self.__setSpellingLanguage(self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel) - self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged) + self.project.projectPropertiesChanged.connect( + self.__projectPropertiesChanged) def projectOpened(self): """ @@ -6260,7 +6440,8 @@ """ if self.fileName and \ self.project.isProjectSource(self.fileName): - self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged) + self.project.projectPropertiesChanged.connect( + self.__projectPropertiesChanged) self.setSpellingForProject() def projectClosed(self): @@ -6294,7 +6475,8 @@ Private method to initialize the spell checking functionality. """ if Preferences.getEditor("SpellCheckingEnabled"): - self.__spellCheckStringsOnly = Preferences.getEditor("SpellCheckStringsOnly") + self.__spellCheckStringsOnly = Preferences.getEditor( + "SpellCheckStringsOnly") if self.spell is None: from .SpellChecker import SpellChecker self.spell = SpellChecker(self, self.spellingIndicator, @@ -6326,7 +6508,8 @@ """ if Preferences.getEditor("AutoSpellCheckingEnabled"): try: - self.SCN_CHARADDED.connect(self.__spellCharAdded, Qt.UniqueConnection) + self.SCN_CHARADDED.connect( + self.__spellCharAdded, Qt.UniqueConnection) except TypeError: pass self.spell.checkDocumentIncrementally() @@ -6339,8 +6522,8 @@ def isSpellCheckRegion(self, pos): """ - Public method to check, if the given position is within a region, that should - be spell checked. + Public method to check, if the given position is within a region, that + should be spell checked. @param pos position to be checked (integer) @return flag indicating pos is in a spell check region (boolean) @@ -6361,8 +6544,10 @@ """ if self.spell: if not chr(charNumber).isalnum(): - self.spell.checkWord(self.positionBefore(self.currentPosition()), True) - elif self.hasIndicator(self.spellingIndicator, self.currentPosition()): + self.spell.checkWord( + self.positionBefore(self.currentPosition()), True) + elif self.hasIndicator( + self.spellingIndicator, self.currentPosition()): self.spell.checkWord(self.currentPosition()) def checkSpelling(self): @@ -6411,10 +6596,12 @@ word = self.getWord(line, index) suggestions = self.spell.getSuggestions(word) for suggestion in suggestions[:5]: - self.spellingSuggActs.append(self.spellingMenu.addAction(suggestion)) + self.spellingSuggActs.append( + self.spellingMenu.addAction(suggestion)) if suggestions: self.spellingMenu.addSeparator() - self.spellingMenu.addAction(UI.PixmapCache.getIcon("spellchecking.png"), + self.spellingMenu.addAction( + UI.PixmapCache.getIcon("spellchecking.png"), self.trUtf8("Check spelling..."), self.__checkSpellingWord) self.spellingMenu.addAction(self.trUtf8("Add to dictionary"), self.__addToSpellingDictionary) @@ -6425,7 +6612,8 @@ def __contextMenuSpellingTriggered(self, action): """ - Private slot to handle the selection of a suggestion of the spelling context menu. + Private slot to handle the selection of a suggestion of the spelling + context menu. @param action reference to the action that was selected (QAction) """ @@ -6441,20 +6629,23 @@ def __addToSpellingDictionary(self): """ - Private slot to add the word below the spelling context menu to the dictionary. + Private slot to add the word below the spelling context menu to the + dictionary. """ line, index = self.lineIndexFromPosition(self.spellingMenuPos) word = self.getWord(line, index) self.spell.add(word) wordStart, wordEnd = self.getWordBoundaries(line, index) - self.clearIndicator(self.spellingIndicator, line, wordStart, line, wordEnd) + self.clearIndicator(self.spellingIndicator, line, wordStart, + line, wordEnd) if Preferences.getEditor("AutoSpellCheckingEnabled"): self.spell.checkDocumentIncrementally() def __removeFromSpellingDictionary(self): """ - Private slot to remove the word below the context menu to the dictionary. + Private slot to remove the word below the context menu to the + dictionary. """ line, index = self.lineIndexFromPosition(self.spellingMenuPos) word = self.getWord(line, index) @@ -6481,9 +6672,9 @@ """ Public method to get some share status info. - @return tuple indicating, if the editor is sharable, the sharing status, - if it is inside a locally initiated shared edit session and - if it is inside a remotely initiated shared edit session + @return tuple indicating, if the editor is sharable, the sharing + status, if it is inside a locally initiated shared edit session + and if it is inside a remotely initiated shared edit session (boolean, boolean, boolean, boolean) """ return self.fileName is not None and \ @@ -6608,7 +6799,7 @@ def __processStartEditCommand(self, argsString): """ - Private slot to process a remote StartEdit command + Private slot to process a remote StartEdit command. @param argsString string containing the command parameters (string) """ @@ -6655,7 +6846,7 @@ def __processEndEditCommand(self, argsString): """ - Private slot to process a remote EndEdit command + Private slot to process a remote EndEdit command. @param argsString string containing the command parameters (string) """ @@ -6694,7 +6885,7 @@ def __processRequestSyncCommand(self, argsString): """ - Private slot to process a remote RequestSync command + Private slot to process a remote RequestSync command. @param argsString string containing the command parameters (string) """ @@ -6710,7 +6901,7 @@ def __processSyncCommand(self, argsString): """ - Private slot to process a remote Sync command + Private slot to process a remote Sync command. @param argsString string containing the command parameters (string) """ @@ -6809,7 +7000,8 @@ endLine = max(origStartLine, origEndLine) endIndex = max(origStartIndex, origEndIndex) - # step 1: extract the text of the rectangular selection and the lines + # step 1: extract the text of the rectangular selection and + # the lines selText = {} txtLines = {} for line in range(startLine, endLine + 1): @@ -6821,8 +7013,9 @@ except ValueError: E5MessageBox.critical(self, self.trUtf8("Sort Lines"), - self.trUtf8("""The selection contains illegal data for a""" - """ numerical sort.""")) + self.trUtf8( + """The selection contains illegal data for a""" + """ numerical sort.""")) return if txt in selText: