src/eric7/QScintilla/Editor.py

branch
eric7-maintenance
changeset 10349
df7edc29cbfb
parent 10272
7ae72d1df070
parent 10345
175e6f023126
child 10460
3b34efa2857c
equal deleted inserted replaced
10273:e075c8fe07fd 10349:df7edc29cbfb
29 Qt, 29 Qt,
30 QTimer, 30 QTimer,
31 pyqtSignal, 31 pyqtSignal,
32 pyqtSlot, 32 pyqtSlot,
33 ) 33 )
34 from PyQt6.QtGui import QActionGroup, QFont, QPainter, QPalette, QPixmap 34 from PyQt6.QtGui import QAction, QActionGroup, QFont, QPainter, QPalette, QPixmap
35 from PyQt6.QtPrintSupport import ( 35 from PyQt6.QtPrintSupport import (
36 QAbstractPrintDialog, 36 QAbstractPrintDialog,
37 QPrintDialog, 37 QPrintDialog,
38 QPrinter, 38 QPrinter,
39 QPrintPreviewDialog, 39 QPrintPreviewDialog,
147 mouseDoubleClick = pyqtSignal(QPoint, Qt.MouseButton) 147 mouseDoubleClick = pyqtSignal(QPoint, Qt.MouseButton)
148 148
149 WarningCode = 1 149 WarningCode = 1
150 WarningPython = 2 150 WarningPython = 2
151 WarningStyle = 3 151 WarningStyle = 3
152 WarningInfo = 4
153 WarningError = 5
152 154
153 # Autocompletion icon definitions 155 # Autocompletion icon definitions
154 ClassID = 1 156 ClassID = 1
155 ClassProtectedID = 2 157 ClassProtectedID = 2
156 ClassPrivateID = 3 158 ClassPrivateID = 3
249 # bookmarks are just a list of handles to the 251 # bookmarks are just a list of handles to the
250 # bookmark markers 252 # bookmark markers
251 self.syntaxerrors = {} 253 self.syntaxerrors = {}
252 # key: marker handle 254 # key: marker handle
253 # value: list of (error message, error index) 255 # value: list of (error message, error index)
254 self.warnings = {} 256 self._warnings = {}
255 # key: marker handle 257 # key: marker handle
256 # value: list of (warning message, warning type) 258 # value: list of (warning message, warning type)
257 self.notcoveredMarkers = [] # just a list of marker handles 259 self.notcoveredMarkers = [] # just a list of marker handles
258 self.showingNotcoveredMarkers = False 260 self.showingNotcoveredMarkers = False
259 261
312 Preferences.getEditor("MarkOccurrencesTimeout") 314 Preferences.getEditor("MarkOccurrencesTimeout")
313 ) 315 )
314 self.__markOccurrencesTimer.timeout.connect(self.__markOccurrences) 316 self.__markOccurrencesTimer.timeout.connect(self.__markOccurrences)
315 self.__markedText = "" 317 self.__markedText = ""
316 self.__searchIndicatorLines = [] 318 self.__searchIndicatorLines = []
319
320 # set the autosave attributes
321 self.__autosaveInterval = Preferences.getEditor("AutosaveIntervalSeconds")
322 self.__autosaveManuallyDisabled = False
323
324 # initialize the autosave timer
325 self.__autosaveTimer = QTimer(self)
326 self.__autosaveTimer.setObjectName("AutosaveTimer")
327 self.__autosaveTimer.setSingleShot(True)
328 self.__autosaveTimer.timeout.connect(self.__autosave)
317 329
318 # initialize some spellchecking stuff 330 # initialize some spellchecking stuff
319 self.spell = None 331 self.spell = None
320 self.lastLine = 0 332 self.lastLine = 0
321 self.lastIndex = 0 333 self.lastIndex = 0
546 bnd = req.boundedTo(self.vm.size()) 558 bnd = req.boundedTo(self.vm.size())
547 559
548 if bnd.width() < req.width() or bnd.height() < req.height(): 560 if bnd.width() < req.width() or bnd.height() < req.height():
549 self.resize(bnd) 561 self.resize(bnd)
550 562
551 # set the autosave flag
552 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0
553 self.autosaveManuallyDisabled = False
554
555 # code coverage related attributes 563 # code coverage related attributes
556 self.__coverageFile = "" 564 self.__coverageFile = ""
557 565
558 self.__initContextMenu() 566 self.__initContextMenu()
559 self.__initContextMenuMargins() 567 self.__initContextMenuMargins()
569 # it's a clone 577 # it's a clone
570 self.__languageChanged(editor.apiLanguage, propagate=False) 578 self.__languageChanged(editor.apiLanguage, propagate=False)
571 self.__encodingChanged(editor.encoding, propagate=False) 579 self.__encodingChanged(editor.encoding, propagate=False)
572 self.__spellLanguageChanged(editor.getSpellingLanguage(), propagate=False) 580 self.__spellLanguageChanged(editor.getSpellingLanguage(), propagate=False)
573 # link the warnings to the original editor 581 # link the warnings to the original editor
574 self.warnings = editor.warnings 582 self._warnings = editor._warnings
575 583
576 self.setAcceptDrops(True) 584 self.setAcceptDrops(True)
577 585
578 # breakpoint handling 586 # breakpoint handling
579 self.breakpointModel = self.dbs.getBreakPointModel() 587 self.breakpointModel = self.dbs.getBreakPointModel()
955 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) 963 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced)
956 self.menuActs["AutosaveEnable"] = self.menu.addAction( 964 self.menuActs["AutosaveEnable"] = self.menu.addAction(
957 self.tr("Autosave enabled"), self.__autosaveEnable 965 self.tr("Autosave enabled"), self.__autosaveEnable
958 ) 966 )
959 self.menuActs["AutosaveEnable"].setCheckable(True) 967 self.menuActs["AutosaveEnable"].setCheckable(True)
960 self.menuActs["AutosaveEnable"].setChecked(self.autosaveEnabled) 968 self.menuActs["AutosaveEnable"].setChecked(self.__autosaveInterval > 0)
961 self.menuActs["TypingAidsEnabled"] = self.menu.addAction( 969 self.menuActs["TypingAidsEnabled"] = self.menu.addAction(
962 self.tr("Typing aids enabled"), self.__toggleTypingAids 970 self.tr("Typing aids enabled"), self.__toggleTypingAids
963 ) 971 )
964 self.menuActs["TypingAidsEnabled"].setCheckable(True) 972 self.menuActs["TypingAidsEnabled"].setCheckable(True)
965 self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None) 973 self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None)
1537 self, 1545 self,
1538 self.tr("Export source"), 1546 self.tr("Export source"),
1539 self.tr("""No export format given. Aborting..."""), 1547 self.tr("""No export format given. Aborting..."""),
1540 ) 1548 )
1541 1549
1550 @pyqtSlot()
1542 def __showContextMenuLanguages(self): 1551 def __showContextMenuLanguages(self):
1543 """ 1552 """
1544 Private slot handling the aboutToShow signal of the languages context 1553 Private slot handling the aboutToShow signal of the languages context
1545 menu. 1554 menu.
1546 """ 1555 """
1603 1612
1604 self.__docstringGenerator = None 1613 self.__docstringGenerator = None
1605 1614
1606 def __languageChanged(self, language, propagate=True): 1615 def __languageChanged(self, language, propagate=True):
1607 """ 1616 """
1608 Private slot handling a change of a connected editor's language. 1617 Private method handling a change of a connected editor's language.
1609 1618
1610 @param language language to be set (string) 1619 @param language language to be set (string)
1611 @param propagate flag indicating to propagate the change (boolean) 1620 @param propagate flag indicating to propagate the change (boolean)
1612 """ 1621 """
1613 if language == "": 1622 if language == "":
1708 if act: 1717 if act:
1709 act.setChecked(False) 1718 act.setChecked(False)
1710 else: 1719 else:
1711 self.supportedLanguages[self.apiLanguage][2].setChecked(True) 1720 self.supportedLanguages[self.apiLanguage][2].setChecked(True)
1712 1721
1722 @pyqtSlot()
1713 def projectLexerAssociationsChanged(self): 1723 def projectLexerAssociationsChanged(self):
1714 """ 1724 """
1715 Public slot to handle changes of the project lexer associations. 1725 Public slot to handle changes of the project lexer associations.
1716 """ 1726 """
1717 self.setLanguage(self.fileName) 1727 self.setLanguage(self.fileName)
1718 1728
1729 @pyqtSlot()
1719 def __showContextMenuEncodings(self): 1730 def __showContextMenuEncodings(self):
1720 """ 1731 """
1721 Private slot handling the aboutToShow signal of the encodings context 1732 Private slot handling the aboutToShow signal of the encodings context
1722 menu. 1733 menu.
1723 """ 1734 """
1738 Private method to check the selected encoding of the encodings submenu. 1749 Private method to check the selected encoding of the encodings submenu.
1739 """ 1750 """
1740 with contextlib.suppress(AttributeError, KeyError): 1751 with contextlib.suppress(AttributeError, KeyError):
1741 (self.supportedEncodings[self.__normalizedEncoding()].setChecked(True)) 1752 (self.supportedEncodings[self.__normalizedEncoding()].setChecked(True))
1742 1753
1754 @pyqtSlot(str)
1743 def __encodingChanged(self, encoding, propagate=True): 1755 def __encodingChanged(self, encoding, propagate=True):
1744 """ 1756 """
1745 Private slot to handle a change of the encoding. 1757 Private slot to handle a change of the encoding.
1746 1758
1747 @param encoding changed encoding (string) 1759 @param encoding changed encoding
1748 @param propagate flag indicating to propagate the change (boolean) 1760 @type str
1761 @param propagate flag indicating to propagate the change
1762 @type bool
1749 """ 1763 """
1750 self.encoding = encoding 1764 self.encoding = encoding
1751 self.__checkEncoding() 1765 self.__checkEncoding()
1752 1766
1753 if not self.inEncodingChanged and propagate: 1767 if not self.inEncodingChanged and propagate:
1768 encoding.replace("-default", "") 1782 encoding.replace("-default", "")
1769 .replace("-guessed", "") 1783 .replace("-guessed", "")
1770 .replace("-selected", "") 1784 .replace("-selected", "")
1771 ) 1785 )
1772 1786
1787 @pyqtSlot()
1773 def __showContextMenuEol(self): 1788 def __showContextMenuEol(self):
1774 """ 1789 """
1775 Private slot handling the aboutToShow signal of the eol context menu. 1790 Private slot handling the aboutToShow signal of the eol context menu.
1776 """ 1791 """
1777 self.showMenu.emit("Eol", self.eolMenu, self) 1792 self.showMenu.emit("Eol", self.eolMenu, self)
1791 Private method to check the selected eol type of the eol submenu. 1806 Private method to check the selected eol type of the eol submenu.
1792 """ 1807 """
1793 with contextlib.suppress(AttributeError, TypeError): 1808 with contextlib.suppress(AttributeError, TypeError):
1794 self.supportedEols[self.getLineSeparator()].setChecked(True) 1809 self.supportedEols[self.getLineSeparator()].setChecked(True)
1795 1810
1811 @pyqtSlot()
1796 def __eolChanged(self): 1812 def __eolChanged(self):
1797 """ 1813 """
1798 Private slot to handle a change of the eol mode. 1814 Private slot to handle a change of the eol mode.
1799 """ 1815 """
1800 self.__checkEol() 1816 self.__checkEol()
1803 self.inEolChanged = True 1819 self.inEolChanged = True
1804 eol = self.getLineSeparator() 1820 eol = self.getLineSeparator()
1805 self.eolChanged.emit(eol) 1821 self.eolChanged.emit(eol)
1806 self.inEolChanged = False 1822 self.inEolChanged = False
1807 1823
1824 @pyqtSlot()
1808 def __showContextMenuSpellCheck(self): 1825 def __showContextMenuSpellCheck(self):
1809 """ 1826 """
1810 Private slot handling the aboutToShow signal of the spell check 1827 Private slot handling the aboutToShow signal of the spell check
1811 context menu. 1828 context menu.
1812 """ 1829 """
1820 ) 1837 )
1821 self.menuActs["SpellCheckLanguages"].setEnabled(spellingAvailable) 1838 self.menuActs["SpellCheckLanguages"].setEnabled(spellingAvailable)
1822 1839
1823 self.showMenu.emit("SpellCheck", self.spellCheckMenu, self) 1840 self.showMenu.emit("SpellCheck", self.spellCheckMenu, self)
1824 1841
1842 @pyqtSlot()
1825 def __showContextMenuSpellLanguages(self): 1843 def __showContextMenuSpellLanguages(self):
1826 """ 1844 """
1827 Private slot handling the aboutToShow signal of the spell check 1845 Private slot handling the aboutToShow signal of the spell check
1828 languages context menu. 1846 languages context menu.
1829 """ 1847 """
1838 """ 1856 """
1839 language = act.data() 1857 language = act.data()
1840 self.__setSpellingLanguage(language) 1858 self.__setSpellingLanguage(language)
1841 self.spellLanguageChanged.emit(language) 1859 self.spellLanguageChanged.emit(language)
1842 1860
1861 @pyqtSlot()
1843 def __checkSpellLanguage(self): 1862 def __checkSpellLanguage(self):
1844 """ 1863 """
1845 Private slot to check the selected spell check language action. 1864 Private slot to check the selected spell check language action.
1846 """ 1865 """
1847 language = self.getSpellingLanguage() 1866 language = self.getSpellingLanguage()
1848 with contextlib.suppress(AttributeError, KeyError): 1867 with contextlib.suppress(AttributeError, KeyError):
1849 self.supportedSpellLanguages[language].setChecked(True) 1868 self.supportedSpellLanguages[language].setChecked(True)
1850 1869
1870 @pyqtSlot(str)
1851 def __spellLanguageChanged(self, language, propagate=True): 1871 def __spellLanguageChanged(self, language, propagate=True):
1852 """ 1872 """
1853 Private slot to handle a change of the spell check language. 1873 Private slot to handle a change of the spell check language.
1854 1874
1855 @param language new spell check language 1875 @param language new spell check language
1865 self.spellLanguageChanged.emit(language) 1885 self.spellLanguageChanged.emit(language)
1866 self.__inSpellLanguageChanged = False 1886 self.__inSpellLanguageChanged = False
1867 1887
1868 def __bindLexer(self, filename, pyname=""): 1888 def __bindLexer(self, filename, pyname=""):
1869 """ 1889 """
1870 Private slot to set the correct lexer depending on language. 1890 Private method to set the correct lexer depending on language.
1871 1891
1872 @param filename filename used to determine the associated lexer 1892 @param filename filename used to determine the associated lexer
1873 language (string) 1893 language
1874 @param pyname name of the pygments lexer to use (string) 1894 @type str
1895 @param pyname name of the pygments lexer to use
1896 @type str
1875 """ 1897 """
1876 if self.lexer_ is not None and ( 1898 if self.lexer_ is not None and (
1877 self.lexer_.lexer() == "container" or self.lexer_.lexer() is None 1899 self.lexer_.lexer() == "container" or self.lexer_.lexer() is None
1878 ): 1900 ):
1879 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded) 1901 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded)
1981 self.__setAnnotationStyles() 2003 self.__setAnnotationStyles()
1982 2004
1983 self.lexer_.setDefaultColor(self.lexer_.color(0)) 2005 self.lexer_.setDefaultColor(self.lexer_.color(0))
1984 self.lexer_.setDefaultPaper(self.lexer_.paper(0)) 2006 self.lexer_.setDefaultPaper(self.lexer_.paper(0))
1985 2007
2008 @pyqtSlot(int)
1986 def __styleNeeded(self, position): 2009 def __styleNeeded(self, position):
1987 """ 2010 """
1988 Private slot to handle the need for more styling. 2011 Private slot to handle the need for more styling.
1989 2012
1990 @param position end position, that needs styling (integer) 2013 @param position end position, that needs styling
2014 @type int
1991 """ 2015 """
1992 self.lexer_.styleText(self.getEndStyled(), position) 2016 self.lexer_.styleText(self.getEndStyled(), position)
1993 2017
1994 def getLexer(self): 2018 def getLexer(self):
1995 """ 2019 """
2031 """ 2055 """
2032 return self.apiLanguage 2056 return self.apiLanguage
2033 2057
2034 def __bindCompleter(self, filename): 2058 def __bindCompleter(self, filename):
2035 """ 2059 """
2036 Private slot to set the correct typing completer depending on language. 2060 Private method to set the correct typing completer depending on language.
2037 2061
2038 @param filename filename used to determine the associated typing 2062 @param filename filename used to determine the associated typing
2039 completer language (string) 2063 completer language
2064 @type str
2040 """ 2065 """
2041 if self.completer is not None: 2066 if self.completer is not None:
2042 self.completer.setEnabled(False) 2067 self.completer.setEnabled(False)
2043 self.completer = None 2068 self.completer = None
2044 2069
2059 2084
2060 @return the completer object (CompleterBase) 2085 @return the completer object (CompleterBase)
2061 """ 2086 """
2062 return self.completer 2087 return self.completer
2063 2088
2089 @pyqtSlot(bool)
2064 def __modificationChanged(self, m): 2090 def __modificationChanged(self, m):
2065 """ 2091 """
2066 Private slot to handle the modificationChanged signal. 2092 Private slot to handle the modificationChanged signal.
2067 2093
2068 It emits the signal modificationStatusChanged with parameters 2094 It emits the signal modificationStatusChanged with parameters
2069 m and self. 2095 m and self.
2070 2096
2071 @param m modification status 2097 @param m modification status
2098 @type bool
2072 """ 2099 """
2073 if not m and bool(self.fileName) and pathlib.Path(self.fileName).exists(): 2100 if not m and bool(self.fileName) and pathlib.Path(self.fileName).exists():
2074 self.lastModified = pathlib.Path(self.fileName).stat().st_mtime 2101 self.lastModified = pathlib.Path(self.fileName).stat().st_mtime
2075 self.modificationStatusChanged.emit(m, self) 2102 self.modificationStatusChanged.emit(m, self)
2076 self.undoAvailable.emit(self.isUndoAvailable()) 2103 self.undoAvailable.emit(self.isUndoAvailable())
2077 self.redoAvailable.emit(self.isRedoAvailable()) 2104 self.redoAvailable.emit(self.isRedoAvailable())
2078 2105
2106 if not m:
2107 self.__autosaveTimer.stop()
2108
2109 @pyqtSlot(int, int)
2079 def __cursorPositionChanged(self, line, index): 2110 def __cursorPositionChanged(self, line, index):
2080 """ 2111 """
2081 Private slot to handle the cursorPositionChanged signal. 2112 Private slot to handle the cursorPositionChanged signal.
2082 2113
2083 It emits the signal cursorChanged with parameters fileName, 2114 It emits the signal cursorChanged with parameters fileName,
2084 line and pos. 2115 line and pos.
2085 2116
2086 @param line line number of the cursor 2117 @param line line number of the cursor
2118 @type int
2087 @param index position in line of the cursor 2119 @param index position in line of the cursor
2120 @type int
2088 """ 2121 """
2089 self.cursorChanged.emit(self.fileName, line + 1, index) 2122 self.cursorChanged.emit(self.fileName, line + 1, index)
2090 2123
2091 if Preferences.getEditor("MarkOccurrencesEnabled"): 2124 if Preferences.getEditor("MarkOccurrencesEnabled"):
2092 self.__markOccurrencesTimer.stop()
2093 self.__markOccurrencesTimer.start() 2125 self.__markOccurrencesTimer.start()
2094 2126
2095 if self.lastLine != line: 2127 if self.lastLine != line:
2096 self.cursorLineChanged.emit(line) 2128 self.cursorLineChanged.emit(line)
2097 2129
2110 self.__markerMap.update() 2142 self.__markerMap.update()
2111 2143
2112 self.lastLine = line 2144 self.lastLine = line
2113 self.lastIndex = index 2145 self.lastIndex = index
2114 2146
2147 @pyqtSlot()
2115 def __modificationReadOnly(self): 2148 def __modificationReadOnly(self):
2116 """ 2149 """
2117 Private slot to handle the modificationAttempted signal. 2150 Private slot to handle the modificationAttempted signal.
2118 """ 2151 """
2119 EricMessageBox.warning( 2152 EricMessageBox.warning(
2380 @param foldPrev previous fold level (integer) 2413 @param foldPrev previous fold level (integer)
2381 @param token ??? 2414 @param token ???
2382 @param annotationLinesAdded number of added/deleted annotation lines 2415 @param annotationLinesAdded number of added/deleted annotation lines
2383 (integer) 2416 (integer)
2384 """ 2417 """
2385 if ( 2418 if mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT):
2386 mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) 2419 # 1. set/reset the autosave timer
2387 and linesAdded != 0 2420 if self.__autosaveInterval > 0:
2388 and self.breaks 2421 self.__autosaveTimer.start(self.__autosaveInterval * 1000)
2389 ): 2422
2390 bps = [] # list of breakpoints 2423 # 2. move breakpoints if a line was inserted or deleted
2391 for handle, (ln, cond, temp, enabled, ignorecount) in self.breaks.items(): 2424 if linesAdded != 0 and self.breaks:
2392 line = self.markerLine(handle) + 1 2425 bps = [] # list of breakpoints
2393 if ln != line: 2426 for handle, (
2394 bps.append((ln, line)) 2427 ln,
2395 self.breaks[handle] = (line, cond, temp, enabled, ignorecount) 2428 cond,
2396 self.inLinesChanged = True 2429 temp,
2397 for ln, line in sorted(bps, reverse=linesAdded > 0): 2430 enabled,
2398 index1 = self.breakpointModel.getBreakPointIndex(self.fileName, ln) 2431 ignorecount,
2399 index2 = self.breakpointModel.index(index1.row(), 1) 2432 ) in self.breaks.items():
2400 self.breakpointModel.setData(index2, line) 2433 line = self.markerLine(handle) + 1
2401 self.inLinesChanged = False 2434 if ln != line:
2435 bps.append((ln, line))
2436 self.breaks[handle] = (line, cond, temp, enabled, ignorecount)
2437 self.inLinesChanged = True
2438 for ln, line in sorted(bps, reverse=linesAdded > 0):
2439 index1 = self.breakpointModel.getBreakPointIndex(self.fileName, ln)
2440 index2 = self.breakpointModel.index(index1.row(), 1)
2441 self.breakpointModel.setData(index2, line)
2442 self.inLinesChanged = False
2402 2443
2403 def __restoreBreakpoints(self): 2444 def __restoreBreakpoints(self):
2404 """ 2445 """
2405 Private method to restore the breakpoints. 2446 Private method to restore the breakpoints.
2406 """ 2447 """
2407 for handle in list(self.breaks.keys()): 2448 for handle in self.breaks:
2408 self.markerDeleteHandle(handle) 2449 self.markerDeleteHandle(handle)
2409 self.__addBreakPoints(QModelIndex(), 0, self.breakpointModel.rowCount() - 1) 2450 self.__addBreakPoints(QModelIndex(), 0, self.breakpointModel.rowCount() - 1)
2410 self.__markerMap.update() 2451 self.__markerMap.update()
2411 2452
2453 @pyqtSlot(QModelIndex, int, int)
2412 def __deleteBreakPoints(self, parentIndex, start, end): 2454 def __deleteBreakPoints(self, parentIndex, start, end):
2413 """ 2455 """
2414 Private slot to delete breakpoints. 2456 Private slot to delete breakpoints.
2415 2457
2416 @param parentIndex index of parent item (QModelIndex) 2458 @param parentIndex index of parent item
2417 @param start start row (integer) 2459 @type QModelIndex
2418 @param end end row (integer) 2460 @param start start row
2461 @type int
2462 @param end end row
2463 @type int
2419 """ 2464 """
2420 for row in range(start, end + 1): 2465 for row in range(start, end + 1):
2421 index = self.breakpointModel.index(row, 0, parentIndex) 2466 index = self.breakpointModel.index(row, 0, parentIndex)
2422 fn, lineno = self.breakpointModel.getBreakPointByIndex(index)[0:2] 2467 fn, lineno = self.breakpointModel.getBreakPointByIndex(index)[0:2]
2423 if fn == self.fileName: 2468 if fn == self.fileName:
2424 self.clearBreakpoint(lineno) 2469 self.clearBreakpoint(lineno)
2425 2470
2471 @pyqtSlot(QModelIndex, QModelIndex)
2426 def __changeBreakPoints(self, startIndex, endIndex): 2472 def __changeBreakPoints(self, startIndex, endIndex):
2427 """ 2473 """
2428 Private slot to set changed breakpoints. 2474 Private slot to set changed breakpoints.
2429 2475
2430 @param startIndex start index of the breakpoints being changed 2476 @param startIndex start index of the breakpoints being changed
2431 (QModelIndex) 2477 @type QModelIndex
2432 @param endIndex end index of the breakpoints being changed 2478 @param endIndex end index of the breakpoints being changed
2433 (QModelIndex) 2479 @type QModelIndex
2434 """ 2480 """
2435 if not self.inLinesChanged: 2481 if not self.inLinesChanged:
2436 self.__addBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) 2482 self.__addBreakPoints(QModelIndex(), startIndex.row(), endIndex.row())
2437 2483
2484 @pyqtSlot(QModelIndex, QModelIndex)
2438 def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): 2485 def __breakPointDataAboutToBeChanged(self, startIndex, endIndex):
2439 """ 2486 """
2440 Private slot to handle the dataAboutToBeChanged signal of the 2487 Private slot to handle the dataAboutToBeChanged signal of the
2441 breakpoint model. 2488 breakpoint model.
2442 2489
2443 @param startIndex start index of the rows to be changed (QModelIndex) 2490 @param startIndex start index of the rows to be changed
2444 @param endIndex end index of the rows to be changed (QModelIndex) 2491 @type QModelIndex
2492 @param endIndex end index of the rows to be changed
2493 @type QModelIndex
2445 """ 2494 """
2446 self.__deleteBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) 2495 self.__deleteBreakPoints(QModelIndex(), startIndex.row(), endIndex.row())
2447 2496
2497 @pyqtSlot(QModelIndex, int, int)
2448 def __addBreakPoints(self, parentIndex, start, end): 2498 def __addBreakPoints(self, parentIndex, start, end):
2449 """ 2499 """
2450 Private slot to add breakpoints. 2500 Private slot to add breakpoints.
2451 2501
2452 @param parentIndex index of parent item (QModelIndex) 2502 @param parentIndex index of parent item
2453 @param start start row (integer) 2503 @type QModelIndex
2454 @param end end row (integer) 2504 @param start start row
2505 @type int
2506 @param end end row
2507 @type int
2455 """ 2508 """
2456 for row in range(start, end + 1): 2509 for row in range(start, end + 1):
2457 index = self.breakpointModel.index(row, 0, parentIndex) 2510 index = self.breakpointModel.index(row, 0, parentIndex)
2458 ( 2511 (
2459 fn, 2512 fn,
2480 if self.inLinesChanged: 2533 if self.inLinesChanged:
2481 return 2534 return
2482 2535
2483 for handle in self.breaks: 2536 for handle in self.breaks:
2484 if self.markerLine(handle) == line - 1: 2537 if self.markerLine(handle) == line - 1:
2485 break 2538 del self.breaks[handle]
2486 else: 2539 self.markerDeleteHandle(handle)
2487 # not found, simply ignore it 2540 self.__markerMap.update()
2488 return 2541 return
2489
2490 del self.breaks[handle]
2491 self.markerDeleteHandle(handle)
2492 self.__markerMap.update()
2493 2542
2494 def newBreakpointWithProperties(self, line, properties): 2543 def newBreakpointWithProperties(self, line, properties):
2495 """ 2544 """
2496 Public method to set a new breakpoint and its properties. 2545 Public method to set a new breakpoint and its properties.
2497 2546
2613 2662
2614 @return flag indicating the presence of breakpoints (boolean) 2663 @return flag indicating the presence of breakpoints (boolean)
2615 """ 2664 """
2616 return len(self.breaks) > 0 2665 return len(self.breaks) > 0
2617 2666
2667 @pyqtSlot()
2618 def __menuToggleTemporaryBreakpoint(self): 2668 def __menuToggleTemporaryBreakpoint(self):
2619 """ 2669 """
2620 Private slot to handle the 'Toggle temporary breakpoint' context menu 2670 Private slot to handle the 'Toggle temporary breakpoint' context menu
2621 action. 2671 action.
2622 """ 2672 """
2624 self.line, index = self.getCursorPosition() 2674 self.line, index = self.getCursorPosition()
2625 self.line += 1 2675 self.line += 1
2626 self.__toggleBreakpoint(self.line, 1) 2676 self.__toggleBreakpoint(self.line, 1)
2627 self.line = -1 2677 self.line = -1
2628 2678
2679 @pyqtSlot()
2629 def menuToggleBreakpoint(self): 2680 def menuToggleBreakpoint(self):
2630 """ 2681 """
2631 Public slot to handle the 'Toggle breakpoint' context menu action. 2682 Public slot to handle the 'Toggle breakpoint' context menu action.
2632 """ 2683 """
2633 if self.line < 0: 2684 if self.line < 0:
2634 self.line, index = self.getCursorPosition() 2685 self.line, index = self.getCursorPosition()
2635 self.line += 1 2686 self.line += 1
2636 self.__toggleBreakpoint(self.line) 2687 self.__toggleBreakpoint(self.line)
2637 self.line = -1 2688 self.line = -1
2638 2689
2690 @pyqtSlot()
2639 def __menuToggleBreakpointEnabled(self): 2691 def __menuToggleBreakpointEnabled(self):
2640 """ 2692 """
2641 Private slot to handle the 'Enable/Disable breakpoint' context menu 2693 Private slot to handle the 'Enable/Disable breakpoint' context menu
2642 action. 2694 action.
2643 """ 2695 """
2645 self.line, index = self.getCursorPosition() 2697 self.line, index = self.getCursorPosition()
2646 self.line += 1 2698 self.line += 1
2647 self.__toggleBreakpointEnabled(self.line) 2699 self.__toggleBreakpointEnabled(self.line)
2648 self.line = -1 2700 self.line = -1
2649 2701
2702 @pyqtSlot()
2650 def menuEditBreakpoint(self, line=None): 2703 def menuEditBreakpoint(self, line=None):
2651 """ 2704 """
2652 Public slot to handle the 'Edit breakpoint' context menu action. 2705 Public slot to handle the 'Edit breakpoint' context menu action.
2653 2706
2654 @param line linenumber of the breakpoint to edit 2707 @param line line number of the breakpoint to edit
2708 @type int
2655 """ 2709 """
2656 from eric7.Debugger.EditBreakpointDialog import EditBreakpointDialog 2710 from eric7.Debugger.EditBreakpointDialog import EditBreakpointDialog
2657 2711
2658 if line is not None: 2712 if line is not None:
2659 self.line = line - 1 2713 self.line = line - 1
2700 2754
2701 break 2755 break
2702 2756
2703 self.line = -1 2757 self.line = -1
2704 2758
2759 @pyqtSlot()
2705 def menuNextBreakpoint(self): 2760 def menuNextBreakpoint(self):
2706 """ 2761 """
2707 Public slot to handle the 'Next breakpoint' context menu action. 2762 Public slot to handle the 'Next breakpoint' context menu action.
2708 """ 2763 """
2709 line, index = self.getCursorPosition() 2764 line, index = self.getCursorPosition()
2717 bpline = self.markerFindNext(0, self.breakpointMask) 2772 bpline = self.markerFindNext(0, self.breakpointMask)
2718 if bpline >= 0: 2773 if bpline >= 0:
2719 self.setCursorPosition(bpline, 0) 2774 self.setCursorPosition(bpline, 0)
2720 self.ensureLineVisible(bpline) 2775 self.ensureLineVisible(bpline)
2721 2776
2777 @pyqtSlot()
2722 def menuPreviousBreakpoint(self): 2778 def menuPreviousBreakpoint(self):
2723 """ 2779 """
2724 Public slot to handle the 'Previous breakpoint' context menu action. 2780 Public slot to handle the 'Previous breakpoint' context menu action.
2725 """ 2781 """
2726 line, index = self.getCursorPosition() 2782 line, index = self.getCursorPosition()
2734 bpline = self.markerFindPrevious(self.lines() - 1, self.breakpointMask) 2790 bpline = self.markerFindPrevious(self.lines() - 1, self.breakpointMask)
2735 if bpline >= 0: 2791 if bpline >= 0:
2736 self.setCursorPosition(bpline, 0) 2792 self.setCursorPosition(bpline, 0)
2737 self.ensureLineVisible(bpline) 2793 self.ensureLineVisible(bpline)
2738 2794
2795 @pyqtSlot()
2739 def __menuClearBreakpoints(self): 2796 def __menuClearBreakpoints(self):
2740 """ 2797 """
2741 Private slot to handle the 'Clear all breakpoints' context menu action. 2798 Private slot to handle the 'Clear all breakpoints' context menu action.
2742 """ 2799 """
2743 self.__clearBreakpoints(self.fileName) 2800 self.__clearBreakpoints(self.fileName)
2744 2801
2745 def __clearBreakpoints(self, fileName): 2802 def __clearBreakpoints(self, fileName):
2746 """ 2803 """
2747 Private slot to clear all breakpoints. 2804 Private method to clear all breakpoints.
2748 2805
2749 @param fileName name of the file (string) 2806 @param fileName name of the file
2807 @type str
2750 """ 2808 """
2751 idxList = [] 2809 idxList = []
2752 for ln, _, _, _, _ in self.breaks.values(): 2810 for ln, _, _, _, _ in self.breaks.values():
2753 index = self.breakpointModel.getBreakPointIndex(fileName, ln) 2811 index = self.breakpointModel.getBreakPointIndex(fileName, ln)
2754 if index.isValid(): 2812 if index.isValid():
2814 2872
2815 @return flag indicating the presence of bookmarks (boolean) 2873 @return flag indicating the presence of bookmarks (boolean)
2816 """ 2874 """
2817 return len(self.bookmarks) > 0 2875 return len(self.bookmarks) > 0
2818 2876
2877 @pyqtSlot()
2819 def menuToggleBookmark(self): 2878 def menuToggleBookmark(self):
2820 """ 2879 """
2821 Public slot to handle the 'Toggle bookmark' context menu action. 2880 Public slot to handle the 'Toggle bookmark' context menu action.
2822 """ 2881 """
2823 if self.line < 0: 2882 if self.line < 0:
2824 self.line, index = self.getCursorPosition() 2883 self.line, index = self.getCursorPosition()
2825 self.line += 1 2884 self.line += 1
2826 self.toggleBookmark(self.line) 2885 self.toggleBookmark(self.line)
2827 self.line = -1 2886 self.line = -1
2828 2887
2888 @pyqtSlot()
2829 def nextBookmark(self): 2889 def nextBookmark(self):
2830 """ 2890 """
2831 Public slot to handle the 'Next bookmark' context menu action. 2891 Public slot to handle the 'Next bookmark' context menu action.
2832 """ 2892 """
2833 line, index = self.getCursorPosition() 2893 line, index = self.getCursorPosition()
2841 bmline = self.markerFindNext(0, 1 << self.bookmark) 2901 bmline = self.markerFindNext(0, 1 << self.bookmark)
2842 if bmline >= 0: 2902 if bmline >= 0:
2843 self.setCursorPosition(bmline, 0) 2903 self.setCursorPosition(bmline, 0)
2844 self.ensureLineVisible(bmline) 2904 self.ensureLineVisible(bmline)
2845 2905
2906 @pyqtSlot()
2846 def previousBookmark(self): 2907 def previousBookmark(self):
2847 """ 2908 """
2848 Public slot to handle the 'Previous bookmark' context menu action. 2909 Public slot to handle the 'Previous bookmark' context menu action.
2849 """ 2910 """
2850 line, index = self.getCursorPosition() 2911 line, index = self.getCursorPosition()
2858 bmline = self.markerFindPrevious(self.lines() - 1, 1 << self.bookmark) 2919 bmline = self.markerFindPrevious(self.lines() - 1, 1 << self.bookmark)
2859 if bmline >= 0: 2920 if bmline >= 0:
2860 self.setCursorPosition(bmline, 0) 2921 self.setCursorPosition(bmline, 0)
2861 self.ensureLineVisible(bmline) 2922 self.ensureLineVisible(bmline)
2862 2923
2924 @pyqtSlot()
2863 def clearBookmarks(self): 2925 def clearBookmarks(self):
2864 """ 2926 """
2865 Public slot to handle the 'Clear all bookmarks' context menu action. 2927 Public slot to handle the 'Clear all bookmarks' context menu action.
2866 """ 2928 """
2867 for handle in self.bookmarks: 2929 for handle in self.bookmarks:
2872 2934
2873 ########################################################################### 2935 ###########################################################################
2874 ## Printing methods below 2936 ## Printing methods below
2875 ########################################################################### 2937 ###########################################################################
2876 2938
2939 @pyqtSlot()
2877 def printFile(self): 2940 def printFile(self):
2878 """ 2941 """
2879 Public slot to print the text. 2942 Public slot to print the text.
2880 """ 2943 """
2881 from .Printer import Printer 2944 from .Printer import Printer
2911 QApplication.processEvents() 2974 QApplication.processEvents()
2912 else: 2975 else:
2913 sb.showMessage(self.tr("Printing aborted"), 2000) 2976 sb.showMessage(self.tr("Printing aborted"), 2000)
2914 QApplication.processEvents() 2977 QApplication.processEvents()
2915 2978
2979 @pyqtSlot()
2916 def printPreviewFile(self): 2980 def printPreviewFile(self):
2917 """ 2981 """
2918 Public slot to show a print preview of the text. 2982 Public slot to show a print preview of the text.
2919 """ 2983 """
2920 from .Printer import Printer 2984 from .Printer import Printer
2964 3028
2965 @return flag indicating the presence of task markers (boolean) 3029 @return flag indicating the presence of task markers (boolean)
2966 """ 3030 """
2967 return self.__hasTaskMarkers 3031 return self.__hasTaskMarkers
2968 3032
3033 @pyqtSlot()
2969 def nextTask(self): 3034 def nextTask(self):
2970 """ 3035 """
2971 Public slot to handle the 'Next task' context menu action. 3036 Public slot to handle the 'Next task' context menu action.
2972 """ 3037 """
2973 line, index = self.getCursorPosition() 3038 line, index = self.getCursorPosition()
2981 taskline = self.markerFindNext(0, 1 << self.taskmarker) 3046 taskline = self.markerFindNext(0, 1 << self.taskmarker)
2982 if taskline >= 0: 3047 if taskline >= 0:
2983 self.setCursorPosition(taskline, 0) 3048 self.setCursorPosition(taskline, 0)
2984 self.ensureLineVisible(taskline) 3049 self.ensureLineVisible(taskline)
2985 3050
3051 @pyqtSlot()
2986 def previousTask(self): 3052 def previousTask(self):
2987 """ 3053 """
2988 Public slot to handle the 'Previous task' context menu action. 3054 Public slot to handle the 'Previous task' context menu action.
2989 """ 3055 """
2990 line, index = self.getCursorPosition() 3056 line, index = self.getCursorPosition()
2998 taskline = self.markerFindPrevious(self.lines() - 1, 1 << self.taskmarker) 3064 taskline = self.markerFindPrevious(self.lines() - 1, 1 << self.taskmarker)
2999 if taskline >= 0: 3065 if taskline >= 0:
3000 self.setCursorPosition(taskline, 0) 3066 self.setCursorPosition(taskline, 0)
3001 self.ensureLineVisible(taskline) 3067 self.ensureLineVisible(taskline)
3002 3068
3069 @pyqtSlot()
3003 def extractTasks(self): 3070 def extractTasks(self):
3004 """ 3071 """
3005 Public slot to extract all tasks. 3072 Public slot to extract all tasks.
3006 """ 3073 """
3007 from eric7.Tasks.Task import Task 3074 from eric7.Tasks.Task import Task
3059 painter = QPainter(pixmap) 3126 painter = QPainter(pixmap)
3060 painter.fillRect(size - 4, 0, 4, size, Preferences.getEditorColour(key)) 3127 painter.fillRect(size - 4, 0, 4, size, Preferences.getEditorColour(key))
3061 painter.end() 3128 painter.end()
3062 return pixmap 3129 return pixmap
3063 3130
3131 @pyqtSlot()
3064 def __initOnlineChangeTrace(self): 3132 def __initOnlineChangeTrace(self):
3065 """ 3133 """
3066 Private slot to initialize the online change trace. 3134 Private slot to initialize the online change trace.
3067 """ 3135 """
3068 self.__hasChangeMarkers = False 3136 self.__hasChangeMarkers = False
3076 self.__onlineChangeTraceTimer.timeout.connect( 3144 self.__onlineChangeTraceTimer.timeout.connect(
3077 self.__onlineChangeTraceTimerTimeout 3145 self.__onlineChangeTraceTimerTimeout
3078 ) 3146 )
3079 self.textChanged.connect(self.__resetOnlineChangeTraceTimer) 3147 self.textChanged.connect(self.__resetOnlineChangeTraceTimer)
3080 3148
3149 @pyqtSlot()
3081 def __reinitOnlineChangeTrace(self): 3150 def __reinitOnlineChangeTrace(self):
3082 """ 3151 """
3083 Private slot to re-initialize the online change trace. 3152 Private slot to re-initialize the online change trace.
3084 """ 3153 """
3085 self.__oldText = self.text() 3154 self.__oldText = self.text()
3092 """ 3161 """
3093 if Preferences.getEditor("OnlineChangeTrace"): 3162 if Preferences.getEditor("OnlineChangeTrace"):
3094 self.__onlineChangeTraceTimer.stop() 3163 self.__onlineChangeTraceTimer.stop()
3095 self.__onlineChangeTraceTimer.start() 3164 self.__onlineChangeTraceTimer.start()
3096 3165
3166 @pyqtSlot()
3097 def __onlineChangeTraceTimerTimeout(self): 3167 def __onlineChangeTraceTimerTimeout(self):
3098 """ 3168 """
3099 Private slot to mark added and changed lines. 3169 Private slot to mark added and changed lines.
3100 """ 3170 """
3101 self.__deleteAllChangeMarkers() 3171 self.__deleteAllChangeMarkers()
3124 3194
3125 if self.__hasChangeMarkers: 3195 if self.__hasChangeMarkers:
3126 self.changeMarkersUpdated.emit(self) 3196 self.changeMarkersUpdated.emit(self)
3127 self.__markerMap.update() 3197 self.__markerMap.update()
3128 3198
3199 @pyqtSlot()
3129 def resetOnlineChangeTraceInfo(self): 3200 def resetOnlineChangeTraceInfo(self):
3130 """ 3201 """
3131 Public slot to reset the online change trace info. 3202 Public slot to reset the online change trace info.
3132 """ 3203 """
3133 self.__lastSavedText = self.text() 3204 self.__lastSavedText = self.text()
3146 3217
3147 if self.__hasChangeMarkers: 3218 if self.__hasChangeMarkers:
3148 self.changeMarkersUpdated.emit(self) 3219 self.changeMarkersUpdated.emit(self)
3149 self.__markerMap.update() 3220 self.__markerMap.update()
3150 3221
3222 @pyqtSlot()
3151 def __deleteAllChangeMarkers(self): 3223 def __deleteAllChangeMarkers(self):
3152 """ 3224 """
3153 Private slot to delete all change markers. 3225 Private slot to delete all change markers.
3154 """ 3226 """
3155 self.markerDeleteAll(self.__changeMarkerUnsaved) 3227 self.markerDeleteAll(self.__changeMarkerUnsaved)
3186 3258
3187 @return flag indicating the presence of change markers (boolean) 3259 @return flag indicating the presence of change markers (boolean)
3188 """ 3260 """
3189 return self.__hasChangeMarkers 3261 return self.__hasChangeMarkers
3190 3262
3263 @pyqtSlot()
3191 def nextChange(self): 3264 def nextChange(self):
3192 """ 3265 """
3193 Public slot to handle the 'Next change' context menu action. 3266 Public slot to handle the 'Next change' context menu action.
3194 """ 3267 """
3195 line, index = self.getCursorPosition() 3268 line, index = self.getCursorPosition()
3203 changeline = self.markerFindNext(0, self.changeMarkersMask) 3276 changeline = self.markerFindNext(0, self.changeMarkersMask)
3204 if changeline >= 0: 3277 if changeline >= 0:
3205 self.setCursorPosition(changeline, 0) 3278 self.setCursorPosition(changeline, 0)
3206 self.ensureLineVisible(changeline) 3279 self.ensureLineVisible(changeline)
3207 3280
3281 @pyqtSlot()
3208 def previousChange(self): 3282 def previousChange(self):
3209 """ 3283 """
3210 Public slot to handle the 'Previous change' context menu action. 3284 Public slot to handle the 'Previous change' context menu action.
3211 """ 3285 """
3212 line, index = self.getCursorPosition() 3286 line, index = self.getCursorPosition()
3302 break 3376 break
3303 # Couldn't find the unmodified state 3377 # Couldn't find the unmodified state
3304 3378
3305 def readFile(self, fn, createIt=False, encoding=""): 3379 def readFile(self, fn, createIt=False, encoding=""):
3306 """ 3380 """
3307 Public slot to read the text from a file. 3381 Public method to read the text from a file.
3308 3382
3309 @param fn filename to read from (string) 3383 @param fn filename to read from (string)
3310 @param createIt flag indicating the creation of a new file, if the 3384 @param createIt flag indicating the creation of a new file, if the
3311 given one doesn't exist (boolean) 3385 given one doesn't exist (boolean)
3312 @param encoding encoding to be used to read the file (string) 3386 @param encoding encoding to be used to read the file (string)
3358 self.extractTasks() 3432 self.extractTasks()
3359 3433
3360 self.setModified(modified) 3434 self.setModified(modified)
3361 self.lastModified = pathlib.Path(fn).stat().st_mtime 3435 self.lastModified = pathlib.Path(fn).stat().st_mtime
3362 3436
3437 @pyqtSlot()
3363 def __convertTabs(self): 3438 def __convertTabs(self):
3364 """ 3439 """
3365 Private slot to convert tabulators to spaces. 3440 Private slot to convert tabulators to spaces.
3366 """ 3441 """
3367 if ( 3442 if (
3391 ok = self.findNextTarget() 3466 ok = self.findNextTarget()
3392 self.endUndoAction() 3467 self.endUndoAction()
3393 3468
3394 def writeFile(self, fn, backup=True): 3469 def writeFile(self, fn, backup=True):
3395 """ 3470 """
3396 Public slot to write the text to a file. 3471 Public method to write the text to a file.
3397 3472
3398 @param fn filename to write to (string) 3473 @param fn filename to write to
3399 @param backup flag indicating to save a backup (boolean) 3474 @type str
3400 @return flag indicating success (boolean) 3475 @param backup flag indicating to save a backup
3476 @type bool
3477 @return flag indicating success
3478 @rtype bool
3401 """ 3479 """
3402 config = self.__loadEditorConfigObject(fn) 3480 config = self.__loadEditorConfigObject(fn)
3403 3481
3404 eol = self.__getEditorConfig("EOLMode", nodefault=True, config=config) 3482 eol = self.__getEditorConfig("EOLMode", nodefault=True, config=config)
3405 if eol is not None: 3483 if eol is not None:
3576 else: 3654 else:
3577 fn = self.fileName 3655 fn = self.fileName
3578 3656
3579 self.__loadEditorConfig(fn) 3657 self.__loadEditorConfig(fn)
3580 self.editorAboutToBeSaved.emit(self.fileName) 3658 self.editorAboutToBeSaved.emit(self.fileName)
3659 if self.__autosaveTimer.isActive():
3660 self.__autosaveTimer.stop()
3581 if self.writeFile(fn): 3661 if self.writeFile(fn):
3582 if saveas: 3662 if saveas:
3583 self.__clearBreakpoints(self.fileName) 3663 self.__clearBreakpoints(self.fileName)
3584 self.setFileName(fn) 3664 self.setFileName(fn)
3585 self.setModified(False) 3665 self.setModified(False)
3617 ) 3697 )
3618 return False 3698 return False
3619 3699
3620 def saveFileAs(self, path=None): 3700 def saveFileAs(self, path=None):
3621 """ 3701 """
3622 Public slot to save a file with a new name. 3702 Public method to save a file with a new name.
3623 3703
3624 @param path directory to save the file in (string) 3704 @param path directory to save the file in
3625 @return tuple of two values (boolean, string) giving a success 3705 @type str
3626 indicator and the name of the saved file 3706 @return tuple containing a success indicator and the name of the saved file
3707 @rtype tuple of (bool, str)
3627 """ 3708 """
3628 return self.saveFile(True, path) 3709 return self.saveFile(True, path)
3629 3710
3630 def __saveDeviceFile(self, saveas=False): 3711 def __saveDeviceFile(self, saveas=False):
3631 """ 3712 """
3667 3748
3668 return False 3749 return False
3669 3750
3670 def handleRenamed(self, fn): 3751 def handleRenamed(self, fn):
3671 """ 3752 """
3672 Public slot to handle the editorRenamed signal. 3753 Public method to handle the editorRenamed signal.
3673 3754
3674 @param fn filename to be set for the editor (string). 3755 @param fn filename to be set for the editor (string).
3675 """ 3756 """
3676 self.__clearBreakpoints(fn) 3757 self.__clearBreakpoints(fn)
3677 3758
3685 3766
3686 self.lastModified = pathlib.Path(fn).stat().st_mtime 3767 self.lastModified = pathlib.Path(fn).stat().st_mtime
3687 self.vm.setEditorName(self, self.fileName) 3768 self.vm.setEditorName(self, self.fileName)
3688 self.__updateReadOnly(True) 3769 self.__updateReadOnly(True)
3689 3770
3771 @pyqtSlot(str)
3690 def fileRenamed(self, fn): 3772 def fileRenamed(self, fn):
3691 """ 3773 """
3692 Public slot to handle the editorRenamed signal. 3774 Public slot to handle the editorRenamed signal.
3693 3775
3694 @param fn filename to be set for the editor (string). 3776 @param fn filename to be set for the editor
3777 @type str.
3695 """ 3778 """
3696 self.handleRenamed(fn) 3779 self.handleRenamed(fn)
3697 if not self.inFileRenamed: 3780 if not self.inFileRenamed:
3698 self.inFileRenamed = True 3781 self.inFileRenamed = True
3699 self.editorRenamed.emit(self.fileName) 3782 self.editorRenamed.emit(self.fileName)
3703 ## Utility methods below 3786 ## Utility methods below
3704 ########################################################################### 3787 ###########################################################################
3705 3788
3706 def ensureVisible(self, line, expand=False): 3789 def ensureVisible(self, line, expand=False):
3707 """ 3790 """
3708 Public slot to ensure, that the specified line is visible. 3791 Public method to ensure, that the specified line is visible.
3709 3792
3710 @param line line number to make visible 3793 @param line line number to make visible
3711 @type int 3794 @type int
3712 @param expand flag indicating to expand all folds 3795 @param expand flag indicating to expand all folds
3713 @type bool 3796 @type bool
3720 QsciScintilla.SC_FOLDACTION_EXPAND, 3803 QsciScintilla.SC_FOLDACTION_EXPAND,
3721 ) 3804 )
3722 3805
3723 def ensureVisibleTop(self, line, expand=False): 3806 def ensureVisibleTop(self, line, expand=False):
3724 """ 3807 """
3725 Public slot to ensure, that the specified line is visible at the top 3808 Public method to ensure, that the specified line is visible at the top
3726 of the editor. 3809 of the editor.
3727 3810
3728 @param line line number to make visible 3811 @param line line number to make visible
3729 @type int 3812 @type int
3730 @param expand flag indicating to expand all folds 3813 @param expand flag indicating to expand all folds
3742 3825
3743 def __marginClicked(self, margin, line, modifiers): # noqa: U100 3826 def __marginClicked(self, margin, line, modifiers): # noqa: U100
3744 """ 3827 """
3745 Private slot to handle the marginClicked signal. 3828 Private slot to handle the marginClicked signal.
3746 3829
3747 @param margin id of the clicked margin (integer) 3830 @param margin id of the clicked margin
3748 @param line line number of the click (integer) 3831 @type int
3749 @param modifiers keyboard modifiers (Qt.KeyboardModifiers) 3832 @param line line number of the click
3833 @type int
3834 @param modifiers keyboard modifiers
3835 @type Qt.KeyboardModifiers
3750 """ 3836 """
3751 if margin == self.__bmMargin: 3837 if margin == self.__bmMargin:
3752 self.toggleBookmark(line + 1) 3838 self.toggleBookmark(line + 1)
3753 elif margin == self.__bpMargin: 3839 elif margin == self.__bpMargin:
3754 self.__toggleBreakpoint(line + 1) 3840 self.__toggleBreakpoint(line + 1)
3756 if self.markersAtLine(line) & (1 << self.syntaxerror): 3842 if self.markersAtLine(line) & (1 << self.syntaxerror):
3757 self.__showSyntaxError(line) 3843 self.__showSyntaxError(line)
3758 elif self.markersAtLine(line) & (1 << self.warning): 3844 elif self.markersAtLine(line) & (1 << self.warning):
3759 self.__showWarning(line) 3845 self.__showWarning(line)
3760 3846
3847 @pyqtSlot()
3761 def handleMonospacedEnable(self): 3848 def handleMonospacedEnable(self):
3762 """ 3849 """
3763 Public slot to handle the Use Monospaced Font context menu entry. 3850 Public slot to handle the Use Monospaced Font context menu entry.
3764 """ 3851 """
3765 if self.menuActs["MonospacedFont"].isChecked(): 3852 if self.menuActs["MonospacedFont"].isChecked():
3772 self.lexer_.readSubstyles(self) 3859 self.lexer_.readSubstyles(self)
3773 self.lexer_.initProperties() 3860 self.lexer_.initProperties()
3774 self.setMonospaced(False) 3861 self.setMonospaced(False)
3775 self.__setMarginsDisplay() 3862 self.__setMarginsDisplay()
3776 3863
3777 def getWordBoundaries(self, line, index, useWordChars=True): 3864 def getWordBoundaries(self, line, index, useWordChars=True, forCompletion=False):
3778 """ 3865 """
3779 Public method to get the word boundaries at a position. 3866 Public method to get the word boundaries at a position.
3780 3867
3781 @param line number of line to look at (int) 3868 @param line number of line to look at
3782 @param index position to look at (int) 3869 @type int
3870 @param index position to look at
3871 @type int
3783 @param useWordChars flag indicating to use the wordCharacters 3872 @param useWordChars flag indicating to use the wordCharacters
3784 method (boolean) 3873 method (defaults to True)
3874 @type bool (optional)
3875 @param forCompletion flag indicating a modification for completions (defaults
3876 to False)
3877 @type bool (optional)
3785 @return tuple with start and end indexes of the word at the position 3878 @return tuple with start and end indexes of the word at the position
3786 (integer, integer) 3879 @rtype tuple of (int, int)
3787 """ 3880 """
3788 wc = self.wordCharacters() 3881 wc = self.wordCharacters()
3789 if wc is None or not useWordChars: 3882 if wc is None or not useWordChars:
3790 pattern = r"\b[\w_]+\b" 3883 pattern = r"\b[\w_]+\b"
3791 else: 3884 else:
3792 wc = re.sub(r"\w", "", wc) 3885 wc = re.sub(r"\w", "", wc)
3793 pattern = r"\b[\w{0}]+\b".format(re.escape(wc)) 3886 pattern = r"\b[\w{0}]+\b".format(re.escape(wc))
3887 if forCompletion:
3888 pattern += "=?"
3794 rx = ( 3889 rx = (
3795 re.compile(pattern) 3890 re.compile(pattern)
3796 if self.caseSensitive() 3891 if self.caseSensitive()
3797 else re.compile(pattern, re.IGNORECASE) 3892 else re.compile(pattern, re.IGNORECASE)
3798 ) 3893 )
3803 if start <= index <= end: 3898 if start <= index <= end:
3804 return (start, end) 3899 return (start, end)
3805 3900
3806 return (index, index) 3901 return (index, index)
3807 3902
3808 def getWord(self, line, index, direction=0, useWordChars=True): 3903 def getWord(self, line, index, direction=0, useWordChars=True, forCompletion=False):
3809 """ 3904 """
3810 Public method to get the word at a position. 3905 Public method to get the word at a position.
3811 3906
3812 @param line number of line to look at (int) 3907 @param line number of line to look at
3813 @param index position to look at (int) 3908 @type int
3909 @param index position to look at
3910 @type int
3814 @param direction direction to look in (0 = whole word, 1 = left, 3911 @param direction direction to look in (0 = whole word, 1 = left,
3815 2 = right) 3912 2 = right)
3913 @type int
3816 @param useWordChars flag indicating to use the wordCharacters 3914 @param useWordChars flag indicating to use the wordCharacters
3817 method (boolean) 3915 method (defaults to True)
3818 @return the word at that position (string) 3916 @type bool (optional)
3819 """ 3917 @param forCompletion flag indicating a modification for completions (defaults
3820 start, end = self.getWordBoundaries(line, index, useWordChars) 3918 to False)
3919 @type bool (optional)
3920 @return the word at that position
3921 @rtype str
3922 """
3923 start, end = self.getWordBoundaries(
3924 line, index, useWordChars=useWordChars, forCompletion=forCompletion
3925 )
3821 if direction == 1: 3926 if direction == 1:
3822 end = index 3927 end = index
3823 elif direction == 2: 3928 elif direction == 2:
3824 start = index 3929 start = index
3825 if end > start: 3930 if end > start:
4078 if Preferences.getEditor("CommentColumn0"): 4183 if Preferences.getEditor("CommentColumn0"):
4079 return line.startswith(commentStr) 4184 return line.startswith(commentStr)
4080 else: 4185 else:
4081 return line.strip().startswith(commentStr) 4186 return line.strip().startswith(commentStr)
4082 4187
4188 @pyqtSlot()
4083 def toggleCommentBlock(self): 4189 def toggleCommentBlock(self):
4084 """ 4190 """
4085 Public slot to toggle the comment of a block. 4191 Public slot to toggle the comment of a block.
4086 4192
4087 If the editor contains selected text and the start line is not commented, it 4193 If the editor contains selected text and the start line is not commented, it
4125 # 3. uncomment the determined block and reset the cursor position 4231 # 3. uncomment the determined block and reset the cursor position
4126 self.setSelection(begline, 0, endline, self.lineLength(endline)) 4232 self.setSelection(begline, 0, endline, self.lineLength(endline))
4127 self.uncommentLineOrSelection() 4233 self.uncommentLineOrSelection()
4128 self.setCursorPosition(line, index - len(commentStr)) 4234 self.setCursorPosition(line, index - len(commentStr))
4129 4235
4236 @pyqtSlot()
4130 def commentLine(self): 4237 def commentLine(self):
4131 """ 4238 """
4132 Public slot to comment the current line. 4239 Public slot to comment the current line.
4133 """ 4240 """
4134 if self.lexer_ is None or not self.lexer_.canBlockComment(): 4241 if self.lexer_ is None or not self.lexer_.canBlockComment():
4142 lineText = self.text(line) 4249 lineText = self.text(line)
4143 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) 4250 pos = len(lineText.replace(lineText.lstrip(" \t"), ""))
4144 self.insertAt(self.lexer_.commentStr(), line, pos) 4251 self.insertAt(self.lexer_.commentStr(), line, pos)
4145 self.endUndoAction() 4252 self.endUndoAction()
4146 4253
4254 @pyqtSlot()
4147 def uncommentLine(self): 4255 def uncommentLine(self):
4148 """ 4256 """
4149 Public slot to uncomment the current line. 4257 Public slot to uncomment the current line.
4150 """ 4258 """
4151 if self.lexer_ is None or not self.lexer_.canBlockComment(): 4259 if self.lexer_ is None or not self.lexer_.canBlockComment():
4168 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) 4276 pos = len(lineText.replace(lineText.lstrip(" \t"), ""))
4169 self.setSelection(line, pos, line, pos + len(commentStr)) 4277 self.setSelection(line, pos, line, pos + len(commentStr))
4170 self.removeSelectedText() 4278 self.removeSelectedText()
4171 self.endUndoAction() 4279 self.endUndoAction()
4172 4280
4281 @pyqtSlot()
4173 def commentSelection(self): 4282 def commentSelection(self):
4174 """ 4283 """
4175 Public slot to comment the current selection. 4284 Public slot to comment the current selection.
4176 """ 4285 """
4177 if self.lexer_ is None or not self.lexer_.canBlockComment(): 4286 if self.lexer_ is None or not self.lexer_.canBlockComment():
4198 4307
4199 # change the selection accordingly 4308 # change the selection accordingly
4200 self.setSelection(lineFrom, 0, endLine + 1, 0) 4309 self.setSelection(lineFrom, 0, endLine + 1, 0)
4201 self.endUndoAction() 4310 self.endUndoAction()
4202 4311
4312 @pyqtSlot()
4203 def uncommentSelection(self): 4313 def uncommentSelection(self):
4204 """ 4314 """
4205 Public slot to uncomment the current selection. 4315 Public slot to uncomment the current selection.
4206 """ 4316 """
4207 if self.lexer_ is None or not self.lexer_.canBlockComment(): 4317 if self.lexer_ is None or not self.lexer_.canBlockComment():
4246 4356
4247 # change the selection accordingly 4357 # change the selection accordingly
4248 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) 4358 self.setSelection(lineFrom, indexFrom, lineTo, indexTo)
4249 self.endUndoAction() 4359 self.endUndoAction()
4250 4360
4361 @pyqtSlot()
4251 def commentLineOrSelection(self): 4362 def commentLineOrSelection(self):
4252 """ 4363 """
4253 Public slot to comment the current line or current selection. 4364 Public slot to comment the current line or current selection.
4254 """ 4365 """
4255 if self.hasSelectedText(): 4366 if self.hasSelectedText():
4256 self.commentSelection() 4367 self.commentSelection()
4257 else: 4368 else:
4258 self.commentLine() 4369 self.commentLine()
4259 4370
4371 @pyqtSlot()
4260 def uncommentLineOrSelection(self): 4372 def uncommentLineOrSelection(self):
4261 """ 4373 """
4262 Public slot to uncomment the current line or current selection. 4374 Public slot to uncomment the current line or current selection.
4263 """ 4375 """
4264 if self.hasSelectedText(): 4376 if self.hasSelectedText():
4265 self.uncommentSelection() 4377 self.uncommentSelection()
4266 else: 4378 else:
4267 self.uncommentLine() 4379 self.uncommentLine()
4268 4380
4381 @pyqtSlot()
4269 def streamCommentLine(self): 4382 def streamCommentLine(self):
4270 """ 4383 """
4271 Public slot to stream comment the current line. 4384 Public slot to stream comment the current line.
4272 """ 4385 """
4273 if self.lexer_ is None or not self.lexer_.canStreamComment(): 4386 if self.lexer_ is None or not self.lexer_.canStreamComment():
4279 self.beginUndoAction() 4392 self.beginUndoAction()
4280 self.insertAt(commentStr["end"], line, self.lineLength(line)) 4393 self.insertAt(commentStr["end"], line, self.lineLength(line))
4281 self.insertAt(commentStr["start"], line, 0) 4394 self.insertAt(commentStr["start"], line, 0)
4282 self.endUndoAction() 4395 self.endUndoAction()
4283 4396
4397 @pyqtSlot()
4284 def streamCommentSelection(self): 4398 def streamCommentSelection(self):
4285 """ 4399 """
4286 Public slot to comment the current selection. 4400 Public slot to comment the current selection.
4287 """ 4401 """
4288 if self.lexer_ is None or not self.lexer_.canStreamComment(): 4402 if self.lexer_ is None or not self.lexer_.canStreamComment():
4312 if lineFrom == endLine: 4426 if lineFrom == endLine:
4313 indexTo += len(commentStr["start"]) 4427 indexTo += len(commentStr["start"])
4314 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) 4428 self.setSelection(lineFrom, indexFrom, lineTo, indexTo)
4315 self.endUndoAction() 4429 self.endUndoAction()
4316 4430
4431 @pyqtSlot()
4317 def streamCommentLineOrSelection(self): 4432 def streamCommentLineOrSelection(self):
4318 """ 4433 """
4319 Public slot to stream comment the current line or current selection. 4434 Public slot to stream comment the current line or current selection.
4320 """ 4435 """
4321 if self.hasSelectedText(): 4436 if self.hasSelectedText():
4322 self.streamCommentSelection() 4437 self.streamCommentSelection()
4323 else: 4438 else:
4324 self.streamCommentLine() 4439 self.streamCommentLine()
4325 4440
4441 @pyqtSlot()
4326 def boxCommentLine(self): 4442 def boxCommentLine(self):
4327 """ 4443 """
4328 Public slot to box comment the current line. 4444 Public slot to box comment the current line.
4329 """ 4445 """
4330 if self.lexer_ is None or not self.lexer_.canBoxComment(): 4446 if self.lexer_ is None or not self.lexer_.canBoxComment():
4340 self.insertAt(commentStr["middle"], line, 0) 4456 self.insertAt(commentStr["middle"], line, 0)
4341 self.insertAt(eol, line, 0) 4457 self.insertAt(eol, line, 0)
4342 self.insertAt(commentStr["start"], line, 0) 4458 self.insertAt(commentStr["start"], line, 0)
4343 self.endUndoAction() 4459 self.endUndoAction()
4344 4460
4461 @pyqtSlot()
4345 def boxCommentSelection(self): 4462 def boxCommentSelection(self):
4346 """ 4463 """
4347 Public slot to box comment the current selection. 4464 Public slot to box comment the current selection.
4348 """ 4465 """
4349 if self.lexer_ is None or not self.lexer_.canBoxComment(): 4466 if self.lexer_ is None or not self.lexer_.canBoxComment():
4372 4489
4373 # change the selection accordingly 4490 # change the selection accordingly
4374 self.setSelection(lineFrom, 0, endLine + 3, 0) 4491 self.setSelection(lineFrom, 0, endLine + 3, 0)
4375 self.endUndoAction() 4492 self.endUndoAction()
4376 4493
4494 @pyqtSlot()
4377 def boxCommentLineOrSelection(self): 4495 def boxCommentLineOrSelection(self):
4378 """ 4496 """
4379 Public slot to box comment the current line or current selection. 4497 Public slot to box comment the current line or current selection.
4380 """ 4498 """
4381 if self.hasSelectedText(): 4499 if self.hasSelectedText():
4449 indexEnd = indexTo - self.indentationWidth() 4567 indexEnd = indexTo - self.indentationWidth()
4450 if indexEnd < 0: 4568 if indexEnd < 0:
4451 indexEnd = 0 4569 indexEnd = 0
4452 self.setSelection(lineFrom, indexStart, lineTo, indexEnd) 4570 self.setSelection(lineFrom, indexStart, lineTo, indexEnd)
4453 4571
4572 @pyqtSlot()
4454 def indentLineOrSelection(self): 4573 def indentLineOrSelection(self):
4455 """ 4574 """
4456 Public slot to indent the current line or current selection. 4575 Public slot to indent the current line or current selection.
4457 """ 4576 """
4458 if self.hasSelectedText(): 4577 if self.hasSelectedText():
4459 self.__indentSelection(True) 4578 self.__indentSelection(True)
4460 else: 4579 else:
4461 self.__indentLine(True) 4580 self.__indentLine(True)
4462 4581
4582 @pyqtSlot()
4463 def unindentLineOrSelection(self): 4583 def unindentLineOrSelection(self):
4464 """ 4584 """
4465 Public slot to unindent the current line or current selection. 4585 Public slot to unindent the current line or current selection.
4466 """ 4586 """
4467 if self.hasSelectedText(): 4587 if self.hasSelectedText():
4468 self.__indentSelection(False) 4588 self.__indentSelection(False)
4469 else: 4589 else:
4470 self.__indentLine(False) 4590 self.__indentLine(False)
4471 4591
4592 @pyqtSlot()
4472 def smartIndentLineOrSelection(self): 4593 def smartIndentLineOrSelection(self):
4473 """ 4594 """
4474 Public slot to indent current line smartly. 4595 Public slot to indent current line smartly.
4475 """ 4596 """
4476 if self.hasSelectedText(): 4597 if self.hasSelectedText():
4484 else: 4605 else:
4485 self.__indentLine(True) 4606 self.__indentLine(True)
4486 4607
4487 def gotoLine(self, line, pos=1, firstVisible=False, expand=False): 4608 def gotoLine(self, line, pos=1, firstVisible=False, expand=False):
4488 """ 4609 """
4489 Public slot to jump to the beginning of a line. 4610 Public method to jump to the beginning of a line.
4490 4611
4491 @param line line number to go to 4612 @param line line number to go to
4492 @type int 4613 @type int
4493 @param pos position in line to go to 4614 @param pos position in line to go to
4494 @type int 4615 @type int
4502 if firstVisible: 4623 if firstVisible:
4503 self.ensureVisibleTop(line, expand) 4624 self.ensureVisibleTop(line, expand)
4504 else: 4625 else:
4505 self.ensureVisible(line, expand) 4626 self.ensureVisible(line, expand)
4506 4627
4628 @pyqtSlot()
4507 def __textChanged(self): 4629 def __textChanged(self):
4508 """ 4630 """
4509 Private slot to handle a change of the editor text. 4631 Private slot to handle a change of the editor text.
4510 4632
4511 This slot defers the handling to the next time the event loop 4633 This slot defers the handling to the next time the event loop
4512 is run in order to ensure, that cursor position has been updated 4634 is run in order to ensure, that cursor position has been updated
4513 by the underlying Scintilla editor. 4635 by the underlying Scintilla editor.
4514 """ 4636 """
4515 QTimer.singleShot(0, self.__saveLastEditPosition) 4637 QTimer.singleShot(0, self.__saveLastEditPosition)
4516 4638
4639 @pyqtSlot()
4517 def __saveLastEditPosition(self): 4640 def __saveLastEditPosition(self):
4518 """ 4641 """
4519 Private slot to record the last edit position. 4642 Private slot to record the last edit position.
4520 """ 4643 """
4521 self.__lastEditPosition = self.getCursorPosition() 4644 self.__lastEditPosition = self.getCursorPosition()
4589 4712
4590 ########################################################################### 4713 ###########################################################################
4591 ## Setup methods below 4714 ## Setup methods below
4592 ########################################################################### 4715 ###########################################################################
4593 4716
4717 @pyqtSlot()
4594 def readSettings(self): 4718 def readSettings(self):
4595 """ 4719 """
4596 Public slot to read the settings into our lexer. 4720 Public slot to read the settings into our lexer.
4597 """ 4721 """
4598 # read the lexer settings and reinit the properties 4722 # read the lexer settings and reinit the properties
4644 4768
4645 # set the calltips function 4769 # set the calltips function
4646 self.__setCallTips() 4770 self.__setCallTips()
4647 4771
4648 # set the autosave flags 4772 # set the autosave flags
4649 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0 4773 self.__autosaveInterval = Preferences.getEditor("AutosaveIntervalSeconds")
4774 if self.__autosaveInterval == 0:
4775 self.__autosaveTimer.stop()
4776 else:
4777 if self.isModified():
4778 self.__autosaveTimer.start(self.__autosaveInterval * 1000)
4650 4779
4651 if Preferences.getEditor("MiniContextMenu") != self.miniMenu: 4780 if Preferences.getEditor("MiniContextMenu") != self.miniMenu:
4652 # regenerate context menu 4781 # regenerate context menu
4653 self.__initContextMenu() 4782 self.__initContextMenu()
4654 else: 4783 else:
4656 self.menuActs["AutoCompletionEnable"].setChecked( 4785 self.menuActs["AutoCompletionEnable"].setChecked(
4657 self.autoCompletionThreshold() != -1 4786 self.autoCompletionThreshold() != -1
4658 ) 4787 )
4659 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) 4788 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced)
4660 self.menuActs["AutosaveEnable"].setChecked( 4789 self.menuActs["AutosaveEnable"].setChecked(
4661 self.autosaveEnabled and not self.autosaveManuallyDisabled 4790 self.__autosaveInterval > 0 and not self.__autosaveManuallyDisabled
4662 ) 4791 )
4663 4792
4664 # regenerate the margins context menu(s) 4793 # regenerate the margins context menu(s)
4665 self.__initContextMenuMargins() 4794 self.__initContextMenuMargins()
4666 4795
4800 self.setMarginWidth(self.__foldMargin, 0) 4929 self.setMarginWidth(self.__foldMargin, 0)
4801 self.setFolding( 4930 self.setFolding(
4802 QsciScintilla.FoldStyle.NoFoldStyle.value, self.__foldMargin 4931 QsciScintilla.FoldStyle.NoFoldStyle.value, self.__foldMargin
4803 ) 4932 )
4804 4933
4934 @pyqtSlot()
4805 def __resizeLinenoMargin(self): 4935 def __resizeLinenoMargin(self):
4806 """ 4936 """
4807 Private slot to resize the line numbers margin. 4937 Private slot to resize the line numbers margin.
4808 """ 4938 """
4809 linenoMargin = Preferences.getEditor("LinenoMargin") 4939 linenoMargin = Preferences.getEditor("LinenoMargin")
5128 elif autoCompletionSource == QsciScintilla.AutoCompletionSource.AcsAPIs: 5258 elif autoCompletionSource == QsciScintilla.AutoCompletionSource.AcsAPIs:
5129 self.setAutoCompletionSource(QsciScintilla.AutoCompletionSource.AcsAPIs) 5259 self.setAutoCompletionSource(QsciScintilla.AutoCompletionSource.AcsAPIs)
5130 else: 5260 else:
5131 self.setAutoCompletionSource(QsciScintilla.AutoCompletionSource.AcsAll) 5261 self.setAutoCompletionSource(QsciScintilla.AutoCompletionSource.AcsAll)
5132 5262
5263 @pyqtSlot()
5133 def __toggleAutoCompletionEnable(self): 5264 def __toggleAutoCompletionEnable(self):
5134 """ 5265 """
5135 Private slot to handle the Enable Autocompletion context menu entry. 5266 Private slot to handle the Enable Autocompletion context menu entry.
5136 """ 5267 """
5137 if self.menuActs["AutoCompletionEnable"].isChecked(): 5268 if self.menuActs["AutoCompletionEnable"].isChecked():
5141 5272
5142 ################################################################# 5273 #################################################################
5143 ## Support for autocompletion hook methods 5274 ## Support for autocompletion hook methods
5144 ################################################################# 5275 #################################################################
5145 5276
5277 @pyqtSlot(int)
5146 def __charAdded(self, charNumber): 5278 def __charAdded(self, charNumber):
5147 """ 5279 """
5148 Private slot called to handle the user entering a character. 5280 Private slot called to handle the user entering a character.
5149 5281
5150 @param charNumber value of the character entered (integer) 5282 @param charNumber value of the character entered
5283 @type int
5151 """ 5284 """
5152 char = chr(charNumber) 5285 char = chr(charNumber)
5153 # update code documentation viewer 5286 # update code documentation viewer
5154 if char == "(" and Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"): 5287 if char == "(" and Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"):
5155 self.vm.showEditorInfo(self) 5288 self.vm.showEditorInfo(self)
5197 return False 5330 return False
5198 5331
5199 wseps = self.lexer_.autoCompletionWordSeparators() 5332 wseps = self.lexer_.autoCompletionWordSeparators()
5200 return any(wsep.endswith(ch) for wsep in wseps) 5333 return any(wsep.endswith(ch) for wsep in wseps)
5201 5334
5335 @pyqtSlot()
5202 def __autocompletionCancelled(self): 5336 def __autocompletionCancelled(self):
5203 """ 5337 """
5204 Private slot to handle the cancellation of an auto-completion list. 5338 Private slot to handle the cancellation of an auto-completion list.
5205 """ 5339 """
5206 self.__acWatchdog.stop() 5340 self.__acWatchdog.stop()
5445 """ 5579 """
5446 Private method to clear the auto-completions cache. 5580 Private method to clear the auto-completions cache.
5447 """ 5581 """
5448 self.__acCache.clear() 5582 self.__acCache.clear()
5449 5583
5584 @pyqtSlot(int, str)
5450 def __completionListSelected(self, listId, txt): 5585 def __completionListSelected(self, listId, txt):
5451 """ 5586 """
5452 Private slot to handle the selection from the completion list. 5587 Private slot to handle the selection from the completion list.
5453 5588
5454 @param listId the ID of the user list (should be 1 or 2) (integer) 5589 @param listId the ID of the user list (should be 1 or 2)
5455 @param txt the selected text (string) 5590 @type int
5591 @param txt the selected text
5592 @type str
5456 """ 5593 """
5457 # custom completions via plug-ins 5594 # custom completions via plug-ins
5458 if listId == EditorAutoCompletionListID: 5595 if listId == EditorAutoCompletionListID:
5459 lst = txt.split() 5596 lst = txt.split()
5460 if len(lst) > 1: 5597 if len(lst) > 1:
5465 self.selectCurrentWord() 5602 self.selectCurrentWord()
5466 self.removeSelectedText() 5603 self.removeSelectedText()
5467 line, col = self.getCursorPosition() 5604 line, col = self.getCursorPosition()
5468 else: 5605 else:
5469 line, col = self.getCursorPosition() 5606 line, col = self.getCursorPosition()
5470 wLeft = self.getWordLeft(line, col) 5607 wLeft = self.getWord(line, col, 1, forCompletion=True) # word left
5471 if not txt.startswith(wLeft): 5608 if not txt.startswith(wLeft):
5472 self.selectCurrentWord() 5609 self.selectCurrentWord()
5473 self.removeSelectedText() 5610 self.removeSelectedText()
5474 line, col = self.getCursorPosition() 5611 line, col = self.getCursorPosition()
5475 elif wLeft: 5612 elif wLeft:
5709 5846
5710 ################################################################# 5847 #################################################################
5711 ## Methods needed by the code documentation viewer 5848 ## Methods needed by the code documentation viewer
5712 ################################################################# 5849 #################################################################
5713 5850
5851 @pyqtSlot()
5714 def __showCodeInfo(self): 5852 def __showCodeInfo(self):
5715 """ 5853 """
5716 Private slot to handle the context menu action to show code info. 5854 Private slot to handle the context menu action to show code info.
5717 """ 5855 """
5718 self.vm.showEditorInfo(self) 5856 self.vm.showEditorInfo(self)
5762 elif self.__marginNumber(pos.x()) == self.__indicMargin: 5900 elif self.__marginNumber(pos.x()) == self.__indicMargin:
5763 self.indicMarginMenu.popup(self.mapToGlobal(pos)) 5901 self.indicMarginMenu.popup(self.mapToGlobal(pos))
5764 elif self.__marginNumber(pos.x()) == self.__foldMargin: 5902 elif self.__marginNumber(pos.x()) == self.__foldMargin:
5765 self.foldMarginMenu.popup(self.mapToGlobal(pos)) 5903 self.foldMarginMenu.popup(self.mapToGlobal(pos))
5766 5904
5905 @pyqtSlot()
5767 def __aboutToShowContextMenu(self): 5906 def __aboutToShowContextMenu(self):
5768 """ 5907 """
5769 Private slot handling the aboutToShow signal of the context menu. 5908 Private slot handling the aboutToShow signal of the context menu.
5770 """ 5909 """
5771 self.menuActs["Reopen"].setEnabled( 5910 self.menuActs["Reopen"].setEnabled(
5826 5965
5827 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty()) 5966 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty())
5828 5967
5829 self.showMenu.emit("Main", self.menu, self) 5968 self.showMenu.emit("Main", self.menu, self)
5830 5969
5970 @pyqtSlot()
5831 def __showContextMenuAutocompletion(self): 5971 def __showContextMenuAutocompletion(self):
5832 """ 5972 """
5833 Private slot called before the autocompletion menu is shown. 5973 Private slot called before the autocompletion menu is shown.
5834 """ 5974 """
5835 self.menuActs["acDynamic"].setEnabled(self.canProvideDynamicAutoCompletion()) 5975 self.menuActs["acDynamic"].setEnabled(self.canProvideDynamicAutoCompletion())
5837 self.menuActs["acAPI"].setEnabled(self.acAPI) 5977 self.menuActs["acAPI"].setEnabled(self.acAPI)
5838 self.menuActs["acAPIDocument"].setEnabled(self.acAPI) 5978 self.menuActs["acAPIDocument"].setEnabled(self.acAPI)
5839 5979
5840 self.showMenu.emit("Autocompletion", self.autocompletionMenu, self) 5980 self.showMenu.emit("Autocompletion", self.autocompletionMenu, self)
5841 5981
5982 @pyqtSlot()
5842 def __showContextMenuShow(self): 5983 def __showContextMenuShow(self):
5843 """ 5984 """
5844 Private slot called before the show menu is shown. 5985 Private slot called before the show menu is shown.
5845 """ 5986 """
5846 prEnable = False 5987 prEnable = False
5882 ) 6023 )
5883 self.coverageHideAnnotationMenuAct.setEnabled(len(self.notcoveredMarkers) > 0) 6024 self.coverageHideAnnotationMenuAct.setEnabled(len(self.notcoveredMarkers) > 0)
5884 6025
5885 self.showMenu.emit("Show", self.menuShow, self) 6026 self.showMenu.emit("Show", self.menuShow, self)
5886 6027
6028 @pyqtSlot()
5887 def __showContextMenuGraphics(self): 6029 def __showContextMenuGraphics(self):
5888 """ 6030 """
5889 Private slot handling the aboutToShow signal of the diagrams context 6031 Private slot handling the aboutToShow signal of the diagrams context
5890 menu. 6032 menu.
5891 """ 6033 """
5896 else: 6038 else:
5897 self.applicationDiagramMenuAct.setEnabled(False) 6039 self.applicationDiagramMenuAct.setEnabled(False)
5898 6040
5899 self.showMenu.emit("Graphics", self.graphicsMenu, self) 6041 self.showMenu.emit("Graphics", self.graphicsMenu, self)
5900 6042
6043 @pyqtSlot(QMenu)
5901 def __showContextMenuMargin(self, menu): 6044 def __showContextMenuMargin(self, menu):
5902 """ 6045 """
5903 Private slot handling the aboutToShow signal of the margins context 6046 Private slot handling the aboutToShow signal of the margins context
5904 menu. 6047 menu.
5905 6048
5954 self.marginMenuActs["ExpandChildren"].setEnabled(isFoldHeader) 6097 self.marginMenuActs["ExpandChildren"].setEnabled(isFoldHeader)
5955 self.marginMenuActs["CollapseChildren"].setEnabled(isFoldHeader) 6098 self.marginMenuActs["CollapseChildren"].setEnabled(isFoldHeader)
5956 6099
5957 if menu is self.indicMarginMenu: 6100 if menu is self.indicMarginMenu:
5958 hasSyntaxErrors = bool(self.syntaxerrors) 6101 hasSyntaxErrors = bool(self.syntaxerrors)
5959 hasWarnings = bool(self.warnings) 6102 hasWarnings = bool(self._warnings)
5960 hasNotCoveredMarkers = bool(self.notcoveredMarkers) 6103 hasNotCoveredMarkers = bool(self.notcoveredMarkers)
5961 6104
5962 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors) 6105 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors)
5963 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors) 6106 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors)
5964 if hasSyntaxErrors and self.markersAtLine(self.line) & ( 6107 if hasSyntaxErrors and self.markersAtLine(self.line) & (
5992 self.__hasChangeMarkers 6135 self.__hasChangeMarkers
5993 ) 6136 )
5994 6137
5995 self.showMenu.emit("Margin", menu, self) 6138 self.showMenu.emit("Margin", menu, self)
5996 6139
6140 @pyqtSlot()
5997 def __showContextMenuChecks(self): 6141 def __showContextMenuChecks(self):
5998 """ 6142 """
5999 Private slot handling the aboutToShow signal of the checks context 6143 Private slot handling the aboutToShow signal of the checks context
6000 menu. 6144 menu.
6001 """ 6145 """
6002 self.showMenu.emit("Checks", self.checksMenu, self) 6146 self.showMenu.emit("Checks", self.checksMenu, self)
6003 6147
6148 @pyqtSlot()
6004 def __showContextMenuTools(self): 6149 def __showContextMenuTools(self):
6005 """ 6150 """
6006 Private slot handling the aboutToShow signal of the tools context 6151 Private slot handling the aboutToShow signal of the tools context
6007 menu. 6152 menu.
6008 """ 6153 """
6009 self.showMenu.emit("Tools", self.toolsMenu, self) 6154 self.showMenu.emit("Tools", self.toolsMenu, self)
6010 6155
6156 @pyqtSlot()
6011 def __showContextMenuFormatting(self): 6157 def __showContextMenuFormatting(self):
6012 """ 6158 """
6013 Private slot handling the aboutToShow signal of the code formatting context 6159 Private slot handling the aboutToShow signal of the code formatting context
6014 menu. 6160 menu.
6015 """ 6161 """
6025 encoding = act.data() 6171 encoding = act.data()
6026 self.readFile(self.fileName, encoding=encoding) 6172 self.readFile(self.fileName, encoding=encoding)
6027 self.__convertTabs() 6173 self.__convertTabs()
6028 self.__checkEncoding() 6174 self.__checkEncoding()
6029 6175
6176 @pyqtSlot()
6030 def __contextSave(self): 6177 def __contextSave(self):
6031 """ 6178 """
6032 Private slot handling the save context menu entry. 6179 Private slot handling the save context menu entry.
6033 """ 6180 """
6034 ok = self.saveFile() 6181 ok = self.saveFile()
6035 if ok: 6182 if ok:
6036 self.vm.setEditorName(self, self.fileName) 6183 self.vm.setEditorName(self, self.fileName)
6037 6184
6185 @pyqtSlot()
6038 def __contextSaveAs(self): 6186 def __contextSaveAs(self):
6039 """ 6187 """
6040 Private slot handling the save as context menu entry. 6188 Private slot handling the save as context menu entry.
6041 """ 6189 """
6042 ok = self.saveFileAs() 6190 ok = self.saveFileAs()
6043 if ok: 6191 if ok:
6044 self.vm.setEditorName(self, self.fileName) 6192 self.vm.setEditorName(self, self.fileName)
6045 6193
6194 @pyqtSlot()
6046 def __contextSaveCopy(self): 6195 def __contextSaveCopy(self):
6047 """ 6196 """
6048 Private slot handling the save copy context menu entry. 6197 Private slot handling the save copy context menu entry.
6049 """ 6198 """
6050 self.saveFileCopy() 6199 self.saveFileCopy()
6051 6200
6201 @pyqtSlot()
6052 def __contextClose(self): 6202 def __contextClose(self):
6053 """ 6203 """
6054 Private slot handling the close context menu entry. 6204 Private slot handling the close context menu entry.
6055 """ 6205 """
6056 self.vm.closeEditor(self) 6206 self.vm.closeEditor(self)
6057 6207
6208 @pyqtSlot()
6058 def __newView(self): 6209 def __newView(self):
6059 """ 6210 """
6060 Private slot to create a new view to an open document. 6211 Private slot to create a new view to an open document.
6061 """ 6212 """
6062 self.vm.newEditorView(self.fileName, self, self.filetype) 6213 self.vm.newEditorView(self.fileName, self, self.filetype)
6063 6214
6215 @pyqtSlot()
6064 def __newViewNewSplit(self): 6216 def __newViewNewSplit(self):
6065 """ 6217 """
6066 Private slot to create a new view to an open document. 6218 Private slot to create a new view to an open document.
6067 """ 6219 """
6068 self.vm.addSplit() 6220 self.vm.addSplit()
6069 self.vm.newEditorView(self.fileName, self, self.filetype) 6221 self.vm.newEditorView(self.fileName, self, self.filetype)
6070 6222
6223 @pyqtSlot()
6071 def __selectAll(self): 6224 def __selectAll(self):
6072 """ 6225 """
6073 Private slot handling the select all context menu action. 6226 Private slot handling the select all context menu action.
6074 """ 6227 """
6075 self.selectAll(True) 6228 self.selectAll(True)
6076 6229
6230 @pyqtSlot()
6077 def __deselectAll(self): 6231 def __deselectAll(self):
6078 """ 6232 """
6079 Private slot handling the deselect all context menu action. 6233 Private slot handling the deselect all context menu action.
6080 """ 6234 """
6081 self.selectAll(False) 6235 self.selectAll(False)
6082 6236
6237 @pyqtSlot()
6083 def joinLines(self): 6238 def joinLines(self):
6084 """ 6239 """
6085 Public slot to join the current line with the next one. 6240 Public slot to join the current line with the next one.
6086 """ 6241 """
6087 curLine = self.getCursorPosition()[0] 6242 curLine = self.getCursorPosition()[0]
6119 self.beginUndoAction() 6274 self.beginUndoAction()
6120 self.removeSelectedText() 6275 self.removeSelectedText()
6121 self.insertAt(" ", curLine, startIndex) 6276 self.insertAt(" ", curLine, startIndex)
6122 self.endUndoAction() 6277 self.endUndoAction()
6123 6278
6279 @pyqtSlot()
6124 def shortenEmptyLines(self): 6280 def shortenEmptyLines(self):
6125 """ 6281 """
6126 Public slot to compress lines consisting solely of whitespace 6282 Public slot to compress lines consisting solely of whitespace
6127 characters. 6283 characters.
6128 """ 6284 """
6133 while ok: 6289 while ok:
6134 self.replaceTarget("") 6290 self.replaceTarget("")
6135 ok = self.findNextTarget() 6291 ok = self.findNextTarget()
6136 self.endUndoAction() 6292 self.endUndoAction()
6137 6293
6294 @pyqtSlot()
6138 def __autosaveEnable(self): 6295 def __autosaveEnable(self):
6139 """ 6296 """
6140 Private slot handling the autosave enable context menu action. 6297 Private slot handling the autosave enable context menu action.
6141 """ 6298 """
6142 if self.menuActs["AutosaveEnable"].isChecked(): 6299 if self.menuActs["AutosaveEnable"].isChecked():
6143 self.autosaveManuallyDisabled = False 6300 self.__autosaveManuallyDisabled = False
6144 else: 6301 else:
6145 self.autosaveManuallyDisabled = True 6302 self.__autosaveManuallyDisabled = True
6146 6303
6147 def shouldAutosave(self): 6304 def __shouldAutosave(self):
6148 """ 6305 """
6149 Public slot to check the autosave flags. 6306 Private method to check the autosave flags.
6150 6307
6151 @return flag indicating this editor should be saved (boolean) 6308 @return flag indicating this editor should be saved (boolean)
6152 """ 6309 """
6153 return ( 6310 return (
6154 bool(self.fileName) 6311 bool(self.fileName)
6155 and not self.autosaveManuallyDisabled 6312 and not self.__autosaveManuallyDisabled
6156 and not self.isReadOnly() 6313 and not self.isReadOnly()
6157 ) 6314 and self.isModified()
6315 )
6316
6317 def __autosave(self):
6318 """
6319 Private slot to save the contents of the editor automatically.
6320
6321 It is only saved by the autosave timer after an initial save (i.e. it already
6322 has a name).
6323 """
6324 if self.__shouldAutosave():
6325 self.saveFile()
6158 6326
6159 def checkSyntax(self): 6327 def checkSyntax(self):
6160 """ 6328 """
6161 Public method to perform an automatic syntax check of the file. 6329 Public method to perform an automatic syntax check of the file.
6162 """ 6330 """
6195 fileType, 6363 fileType,
6196 self.fileName or "(Unnamed)", 6364 self.fileName or "(Unnamed)",
6197 self.text(), 6365 self.text(),
6198 ) 6366 )
6199 6367
6368 @pyqtSlot(str, str)
6200 def __processSyntaxCheckError(self, fn, msg): 6369 def __processSyntaxCheckError(self, fn, msg):
6201 """ 6370 """
6202 Private slot to report an error message of a syntax check. 6371 Private slot to report an error message of a syntax check.
6203 6372
6204 @param fn filename of the file 6373 @param fn filename of the file
6214 6383
6215 self.toggleWarning(0, 0, True, msg) 6384 self.toggleWarning(0, 0, True, msg)
6216 6385
6217 self.updateVerticalScrollBar() 6386 self.updateVerticalScrollBar()
6218 6387
6388 @pyqtSlot(str, dict)
6219 def __processSyntaxCheckResult(self, fn, problems): 6389 def __processSyntaxCheckResult(self, fn, problems):
6220 """ 6390 """
6221 Private slot to report the resulting messages of a syntax check. 6391 Private slot to report the resulting messages of a syntax check.
6222 6392
6223 @param fn filename of the checked file (str) 6393 @param fn filename of the checked file
6394 @type str
6224 @param problems dictionary with the keys 'error' and 'warnings' which 6395 @param problems dictionary with the keys 'error' and 'warnings' which
6225 hold a list containing details about the error/ warnings 6396 hold a list containing details about the error/ warnings
6226 (file name, line number, column, codestring (only at syntax 6397 (file name, line number, column, codestring (only at syntax
6227 errors), the message) (dict) 6398 errors), the message)
6399 @type dict
6228 """ 6400 """
6229 # Check if it's the requested file, otherwise ignore signal 6401 # Check if it's the requested file, otherwise ignore signal
6230 if fn != self.fileName and (bool(self.fileName) or fn != "(Unnamed)"): 6402 if fn != self.fileName and (bool(self.fileName) or fn != "(Unnamed)"):
6231 return 6403 return
6232 6404
6236 error = problems.get("error") 6408 error = problems.get("error")
6237 if error: 6409 if error:
6238 _fn, lineno, col, code, msg = error 6410 _fn, lineno, col, code, msg = error
6239 self.toggleSyntaxError(lineno, col, True, msg) 6411 self.toggleSyntaxError(lineno, col, True, msg)
6240 6412
6241 warnings = problems.get("py_warnings", []) 6413 for _fn, lineno, col, _code, msg in problems.get("py_warnings", []):
6242 for _fn, lineno, col, _code, msg in warnings:
6243 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningPython) 6414 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningPython)
6244 6415
6245 warnings = problems.get("warnings", []) 6416 for _fn, lineno, col, _code, msg in problems.get("warnings", []):
6246 for _fn, lineno, col, _code, msg in warnings:
6247 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningCode) 6417 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningCode)
6248 6418
6249 self.updateVerticalScrollBar() 6419 self.updateVerticalScrollBar()
6250 6420
6421 @pyqtSlot()
6251 def __initOnlineSyntaxCheck(self): 6422 def __initOnlineSyntaxCheck(self):
6252 """ 6423 """
6253 Private slot to initialize the online syntax check. 6424 Private slot to initialize the online syntax check.
6254 """ 6425 """
6255 self.__onlineSyntaxCheckTimer = QTimer(self) 6426 self.__onlineSyntaxCheckTimer = QTimer(self)
6432 6603
6433 @return flag indicating the presence of coverage markers (boolean) 6604 @return flag indicating the presence of coverage markers (boolean)
6434 """ 6605 """
6435 return len(self.notcoveredMarkers) > 0 6606 return len(self.notcoveredMarkers) > 0
6436 6607
6608 @pyqtSlot()
6437 def nextUncovered(self): 6609 def nextUncovered(self):
6438 """ 6610 """
6439 Public slot to handle the 'Next uncovered' context menu action. 6611 Public slot to handle the 'Next uncovered' context menu action.
6440 """ 6612 """
6441 line, index = self.getCursorPosition() 6613 line, index = self.getCursorPosition()
6449 ucline = self.markerFindNext(0, 1 << self.notcovered) 6621 ucline = self.markerFindNext(0, 1 << self.notcovered)
6450 if ucline >= 0: 6622 if ucline >= 0:
6451 self.setCursorPosition(ucline, 0) 6623 self.setCursorPosition(ucline, 0)
6452 self.ensureLineVisible(ucline) 6624 self.ensureLineVisible(ucline)
6453 6625
6626 @pyqtSlot()
6454 def previousUncovered(self): 6627 def previousUncovered(self):
6455 """ 6628 """
6456 Public slot to handle the 'Previous uncovered' context menu action. 6629 Public slot to handle the 'Previous uncovered' context menu action.
6457 """ 6630 """
6458 line, index = self.getCursorPosition() 6631 line, index = self.getCursorPosition()
6534 6707
6535 ########################################################################### 6708 ###########################################################################
6536 ## Syntax error handling methods below 6709 ## Syntax error handling methods below
6537 ########################################################################### 6710 ###########################################################################
6538 6711
6539 def toggleSyntaxError(self, line, index, error, msg="", show=False): 6712 def toggleSyntaxError(self, line, index, setError, msg="", show=False):
6540 """ 6713 """
6541 Public method to toggle a syntax error indicator. 6714 Public method to toggle a syntax error indicator.
6542 6715
6543 @param line line number of the syntax error (integer) 6716 @param line line number of the syntax error
6544 @param index index number of the syntax error (integer) 6717 @type int
6545 @param error flag indicating if the error marker should be 6718 @param index index number of the syntax error
6546 set or deleted (boolean) 6719 @type int
6547 @param msg error message (string) 6720 @param setError flag indicating if the error marker should be
6721 set or deleted
6722 @type bool
6723 @param msg error message
6724 @type str
6548 @param show flag indicating to set the cursor to the error position 6725 @param show flag indicating to set the cursor to the error position
6549 (boolean) 6726 @type bool
6550 """ 6727 """
6551 if line == 0: 6728 if line == 0:
6552 line = 1 6729 line = 1
6553 # hack to show a syntax error marker, if line is reported to be 0 6730 # hack to show a syntax error marker, if line is reported to be 0
6554 if error: 6731
6732 line = min(line, self.lines())
6733 # Limit the line number to the ones we really have to ensure proper display
6734 # of the error annotation.
6735
6736 if setError:
6555 # set a new syntax error marker 6737 # set a new syntax error marker
6556 markers = self.markersAtLine(line - 1) 6738 markers = self.markersAtLine(line - 1)
6557 index += self.indentation(line - 1) 6739 index += self.indentation(line - 1)
6558 if not (markers & (1 << self.syntaxerror)): 6740 if not (markers & (1 << self.syntaxerror)):
6559 handle = self.markerAdd(line - 1, self.syntaxerror) 6741 handle = self.markerAdd(line - 1, self.syntaxerror)
6560 self.syntaxerrors[handle] = [(msg, index)] 6742 self.syntaxerrors[handle] = [(msg, index)]
6561 self.syntaxerrorToggled.emit(self) 6743 self.syntaxerrorToggled.emit(self)
6562 else: 6744 else:
6563 for handle in list(self.syntaxerrors.keys()): 6745 for handle in self.syntaxerrors:
6564 if ( 6746 if (
6565 self.markerLine(handle) == line - 1 6747 self.markerLine(handle) == line - 1
6566 and (msg, index) not in self.syntaxerrors[handle] 6748 and (msg, index) not in self.syntaxerrors[handle]
6567 ): 6749 ):
6568 self.syntaxerrors[handle].append((msg, index)) 6750 self.syntaxerrors[handle].append((msg, index))
6576 self.markerDeleteHandle(handle) 6758 self.markerDeleteHandle(handle)
6577 self.syntaxerrorToggled.emit(self) 6759 self.syntaxerrorToggled.emit(self)
6578 6760
6579 self.__setAnnotation(line - 1) 6761 self.__setAnnotation(line - 1)
6580 self.__markerMap.update() 6762 self.__markerMap.update()
6581
6582 def getSyntaxErrors(self):
6583 """
6584 Public method to retrieve the syntax error markers.
6585
6586 @return sorted list of all lines containing a syntax error
6587 (list of integer)
6588 """
6589 selist = []
6590 for handle in list(self.syntaxerrors.keys()):
6591 selist.append(self.markerLine(handle) + 1)
6592
6593 selist.sort()
6594 return selist
6595 6763
6596 def getSyntaxErrorLines(self): 6764 def getSyntaxErrorLines(self):
6597 """ 6765 """
6598 Public method to get the lines containing a syntax error. 6766 Public method to get the lines containing a syntax error.
6599 6767
6615 6783
6616 @return flag indicating the presence of syntax errors (boolean) 6784 @return flag indicating the presence of syntax errors (boolean)
6617 """ 6785 """
6618 return len(self.syntaxerrors) > 0 6786 return len(self.syntaxerrors) > 0
6619 6787
6788 @pyqtSlot()
6620 def gotoSyntaxError(self): 6789 def gotoSyntaxError(self):
6621 """ 6790 """
6622 Public slot to handle the 'Goto syntax error' context menu action. 6791 Public slot to handle the 'Goto syntax error' context menu action.
6623 """ 6792 """
6624 seline = self.markerFindNext(0, 1 << self.syntaxerror) 6793 seline = self.markerFindNext(0, 1 << self.syntaxerror)
6628 if self.markerLine(handle) == seline: 6797 if self.markerLine(handle) == seline:
6629 index = self.syntaxerrors[handle][0][1] 6798 index = self.syntaxerrors[handle][0][1]
6630 self.setCursorPosition(seline, index) 6799 self.setCursorPosition(seline, index)
6631 self.ensureLineVisible(seline) 6800 self.ensureLineVisible(seline)
6632 6801
6802 @pyqtSlot()
6633 def clearSyntaxError(self): 6803 def clearSyntaxError(self):
6634 """ 6804 """
6635 Public slot to handle the 'Clear all syntax error' context menu action. 6805 Public slot to handle the 'Clear all syntax error' context menu action.
6636 """ 6806 """
6637 for handle in list(self.syntaxerrors.keys()): 6807 for handle in list(self.syntaxerrors.keys()):
6639 self.toggleSyntaxError(line, 0, False) 6809 self.toggleSyntaxError(line, 0, False)
6640 6810
6641 self.syntaxerrors.clear() 6811 self.syntaxerrors.clear()
6642 self.syntaxerrorToggled.emit(self) 6812 self.syntaxerrorToggled.emit(self)
6643 6813
6814 @pyqtSlot()
6644 def __showSyntaxError(self, line=-1): 6815 def __showSyntaxError(self, line=-1):
6645 """ 6816 """
6646 Private slot to handle the 'Show syntax error message' 6817 Private slot to handle the 'Show syntax error message'
6647 context menu action. 6818 context menu action.
6648 6819
6649 @param line line number to show the syntax error for (integer) 6820 @param line line number to show the syntax error for
6821 @type int
6650 """ 6822 """
6651 if line == -1: 6823 if line == -1:
6652 line = self.line 6824 line = self.line
6653 6825
6654 for handle in list(self.syntaxerrors.keys()): 6826 for handle in self.syntaxerrors:
6655 if self.markerLine(handle) == line: 6827 if self.markerLine(handle) == line:
6656 errors = [e[0] for e in self.syntaxerrors[handle]] 6828 errors = [e[0] for e in self.syntaxerrors[handle]]
6657 EricMessageBox.critical( 6829 EricMessageBox.critical(
6658 self, self.tr("Syntax Error"), "\n".join(errors) 6830 self, self.tr("Syntax Error"), "\n".join(errors)
6659 ) 6831 )
6691 ########################################################################### 6863 ###########################################################################
6692 ## Warning handling methods below 6864 ## Warning handling methods below
6693 ########################################################################### 6865 ###########################################################################
6694 6866
6695 def toggleWarning( 6867 def toggleWarning(
6696 self, line, col, warning, msg="", warningType=WarningCode # noqa: U100 6868 self, line, col, setWarning, msg="", warningType=WarningCode # noqa: U100
6697 ): 6869 ):
6698 """ 6870 """
6699 Public method to toggle a warning indicator. 6871 Public method to toggle a warning indicator.
6700 6872
6701 Note: This method is used to set pyflakes and code style warnings. 6873 Note: This method is used to set pyflakes and code style warnings.
6702 6874
6703 @param line line number of the warning 6875 @param line line number of the warning
6876 @type int
6704 @param col column of the warning 6877 @param col column of the warning
6705 @param warning flag indicating if the warning marker should be 6878 @type int
6706 set or deleted (boolean) 6879 @param setWarning flag indicating if the warning marker should be
6707 @param msg warning message (string) 6880 set or deleted
6708 @param warningType type of warning message (integer) 6881 @type bool
6882 @param msg warning message
6883 @type str
6884 @param warningType type of warning message
6885 @type int
6709 """ 6886 """
6710 if line == 0: 6887 if line == 0:
6711 line = 1 6888 line = 1
6712 # hack to show a warning marker, if line is reported to be 0 6889 # hack to show a warning marker, if line is reported to be 0
6713 if warning: 6890
6891 line = min(line, self.lines())
6892 # Limit the line number to the ones we really have to ensure proper display
6893 # of the warning annotation.
6894
6895 if setWarning:
6714 # set/amend a new warning marker 6896 # set/amend a new warning marker
6715 warn = (msg, warningType) 6897 warn = (msg, warningType)
6716 markers = self.markersAtLine(line - 1) 6898 markers = self.markersAtLine(line - 1)
6717 if not (markers & (1 << self.warning)): 6899 if not (markers & (1 << self.warning)):
6718 handle = self.markerAdd(line - 1, self.warning) 6900 handle = self.markerAdd(line - 1, self.warning)
6719 self.warnings[handle] = [warn] 6901 self._warnings[handle] = [warn]
6720 self.syntaxerrorToggled.emit(self) 6902 self.syntaxerrorToggled.emit(self)
6903 # signal is also used for warnings
6721 else: 6904 else:
6722 for handle in list(self.warnings.keys()): 6905 for handle in self._warnings:
6723 if ( 6906 if (
6724 self.markerLine(handle) == line - 1 6907 self.markerLine(handle) == line - 1
6725 and warn not in self.warnings[handle] 6908 and warn not in self._warnings[handle]
6726 ): 6909 ):
6727 self.warnings[handle].append(warn) 6910 self._warnings[handle].append(warn)
6728 else: 6911 else:
6729 for handle in list(self.warnings.keys()): 6912 for handle in list(self._warnings.keys()):
6730 if self.markerLine(handle) == line - 1: 6913 if self.markerLine(handle) == line - 1:
6731 del self.warnings[handle] 6914 del self._warnings[handle]
6732 self.markerDeleteHandle(handle) 6915 self.markerDeleteHandle(handle)
6733 self.syntaxerrorToggled.emit(self) 6916 self.syntaxerrorToggled.emit(self)
6917 # signal is also used for warnings
6734 6918
6735 self.__setAnnotation(line - 1) 6919 self.__setAnnotation(line - 1)
6736 self.__markerMap.update() 6920 self.__markerMap.update()
6737
6738 def getWarnings(self):
6739 """
6740 Public method to retrieve the warning markers.
6741
6742 @return sorted list of all lines containing a warning
6743 (list of integer)
6744 """
6745 fwlist = []
6746 for handle in list(self.warnings.keys()):
6747 fwlist.append(self.markerLine(handle) + 1)
6748
6749 fwlist.sort()
6750 return fwlist
6751 6921
6752 def getWarningLines(self): 6922 def getWarningLines(self):
6753 """ 6923 """
6754 Public method to get the lines containing a warning. 6924 Public method to get the lines containing a warning.
6755 6925
6769 """ 6939 """
6770 Public method to check for the presence of warnings. 6940 Public method to check for the presence of warnings.
6771 6941
6772 @return flag indicating the presence of warnings (boolean) 6942 @return flag indicating the presence of warnings (boolean)
6773 """ 6943 """
6774 return len(self.warnings) > 0 6944 return len(self._warnings) > 0
6775 6945
6946 @pyqtSlot()
6776 def nextWarning(self): 6947 def nextWarning(self):
6777 """ 6948 """
6778 Public slot to handle the 'Next warning' context menu action. 6949 Public slot to handle the 'Next warning' context menu action.
6779 """ 6950 """
6780 line, index = self.getCursorPosition() 6951 line, index = self.getCursorPosition()
6788 fwline = self.markerFindNext(0, 1 << self.warning) 6959 fwline = self.markerFindNext(0, 1 << self.warning)
6789 if fwline >= 0: 6960 if fwline >= 0:
6790 self.setCursorPosition(fwline, 0) 6961 self.setCursorPosition(fwline, 0)
6791 self.ensureLineVisible(fwline) 6962 self.ensureLineVisible(fwline)
6792 6963
6964 @pyqtSlot()
6793 def previousWarning(self): 6965 def previousWarning(self):
6794 """ 6966 """
6795 Public slot to handle the 'Previous warning' context menu action. 6967 Public slot to handle the 'Previous warning' context menu action.
6796 """ 6968 """
6797 line, index = self.getCursorPosition() 6969 line, index = self.getCursorPosition()
6805 fwline = self.markerFindPrevious(self.lines() - 1, 1 << self.warning) 6977 fwline = self.markerFindPrevious(self.lines() - 1, 1 << self.warning)
6806 if fwline >= 0: 6978 if fwline >= 0:
6807 self.setCursorPosition(fwline, 0) 6979 self.setCursorPosition(fwline, 0)
6808 self.ensureLineVisible(fwline) 6980 self.ensureLineVisible(fwline)
6809 6981
6982 @pyqtSlot()
6810 def clearFlakesWarnings(self): 6983 def clearFlakesWarnings(self):
6811 """ 6984 """
6812 Public slot to clear all pyflakes warnings. 6985 Public slot to clear all pyflakes warnings.
6813 """ 6986 """
6814 self.__clearTypedWarning(Editor.WarningCode) 6987 self.__clearTypedWarning(Editor.WarningCode)
6815 self.__clearTypedWarning(Editor.WarningPython) 6988 self.__clearTypedWarning(Editor.WarningPython)
6816 6989
6990 @pyqtSlot()
6817 def clearStyleWarnings(self): 6991 def clearStyleWarnings(self):
6818 """ 6992 """
6819 Public slot to clear all style warnings. 6993 Public slot to clear all style warnings.
6820 """ 6994 """
6821 self.__clearTypedWarning(Editor.WarningStyle) 6995 self.__clearTypedWarning(Editor.WarningStyle)
6996
6997 @pyqtSlot()
6998 def clearInfoWarnings(self):
6999 """
7000 Public slot to clear all info warnings.
7001 """
7002 self.__clearTypedWarning(Editor.WarningInfo)
7003
7004 @pyqtSlot()
7005 def clearErrorWarnings(self):
7006 """
7007 Public slot to clear all error warnings.
7008 """
7009 self.__clearTypedWarning(Editor.WarningError)
7010
7011 @pyqtSlot()
7012 def clearCodeWarnings(self):
7013 """
7014 Public slot to clear all code warnings.
7015 """
7016 self.__clearTypedWarning(Editor.WarningCode)
6822 7017
6823 def __clearTypedWarning(self, warningKind): 7018 def __clearTypedWarning(self, warningKind):
6824 """ 7019 """
6825 Private method to clear warnings of a specific kind. 7020 Private method to clear warnings of a specific kind.
6826 7021
6827 @param warningKind kind of warning to clear (Editor.WarningCode, 7022 @param warningKind kind of warning to clear (Editor.WarningCode,
6828 Editor.WarningPython, Editor.WarningStyle) 7023 Editor.WarningPython, Editor.WarningStyle)
6829 """ 7024 """
6830 for handle in list(self.warnings.keys()): 7025 for handle in list(self._warnings.keys()):
6831 warnings = [] 7026 issues = []
6832 for msg, warningType in self.warnings[handle]: 7027 for msg, warningType in self._warnings[handle]:
6833 if warningType == warningKind: 7028 if warningType == warningKind:
6834 continue 7029 continue
6835 7030
6836 warnings.append((msg, warningType)) 7031 issues.append((msg, warningType))
6837 7032
6838 if warnings: 7033 if issues:
6839 self.warnings[handle] = warnings 7034 self._warnings[handle] = issues
6840 self.__setAnnotation(self.markerLine(handle)) 7035 self.__setAnnotation(self.markerLine(handle))
6841 else: 7036 else:
6842 del self.warnings[handle] 7037 del self._warnings[handle]
6843 self.__setAnnotation(self.markerLine(handle)) 7038 self.__setAnnotation(self.markerLine(handle))
6844 self.markerDeleteHandle(handle) 7039 self.markerDeleteHandle(handle)
6845 self.syntaxerrorToggled.emit(self) 7040 self.syntaxerrorToggled.emit(self)
6846 self.__markerMap.update() 7041 self.__markerMap.update()
6847 7042
7043 @pyqtSlot()
6848 def clearWarnings(self): 7044 def clearWarnings(self):
6849 """ 7045 """
6850 Public slot to clear all warnings. 7046 Public slot to clear all warnings.
6851 """ 7047 """
6852 for handle in self.warnings: 7048 for handle in self._warnings:
6853 self.warnings[handle] = [] 7049 self._warnings[handle] = []
6854 self.__setAnnotation(self.markerLine(handle)) 7050 self.__setAnnotation(self.markerLine(handle))
6855 self.markerDeleteHandle(handle) 7051 self.markerDeleteHandle(handle)
6856 self.warnings.clear() 7052 self._warnings.clear()
6857 self.syntaxerrorToggled.emit(self) 7053 self.syntaxerrorToggled.emit(self)
6858 self.__markerMap.update() 7054 self.__markerMap.update()
6859 7055
7056 @pyqtSlot()
6860 def __showWarning(self, line=-1): 7057 def __showWarning(self, line=-1):
6861 """ 7058 """
6862 Private slot to handle the 'Show warning' context menu action. 7059 Private slot to handle the 'Show warning' context menu action.
6863 7060
6864 @param line line number to show the warning for (integer) 7061 @param line line number to show the warning for
7062 @type int
6865 """ 7063 """
6866 if line == -1: 7064 if line == -1:
6867 line = self.line 7065 line = self.line
6868 7066
6869 for handle in list(self.warnings.keys()): 7067 for handle in self._warnings:
6870 if self.markerLine(handle) == line: 7068 if self.markerLine(handle) == line:
6871 EricMessageBox.warning( 7069 EricMessageBox.warning(
6872 self, 7070 self,
6873 self.tr("Warning"), 7071 self.tr("Warning"),
6874 "\n".join([w[0] for w in self.warnings[handle]]), 7072 "\n".join([w[0] for w in self._warnings[handle]]),
6875 ) 7073 )
6876 break 7074 break
6877 else: 7075 else:
6878 EricMessageBox.warning( 7076 EricMessageBox.warning(
6879 self, self.tr("Warning"), self.tr("No warning messages available.") 7077 self, self.tr("Warning"), self.tr("No warning messages available.")
6881 7079
6882 ########################################################################### 7080 ###########################################################################
6883 ## Annotation handling methods below 7081 ## Annotation handling methods below
6884 ########################################################################### 7082 ###########################################################################
6885 7083
7084 @pyqtSlot()
6886 def __setAnnotationStyles(self): 7085 def __setAnnotationStyles(self):
6887 """ 7086 """
6888 Private slot to define the style used by inline annotations. 7087 Private slot to define the style used by inline annotations.
6889 """ 7088 """
6890 if hasattr(QsciScintilla, "annotate"): 7089 if hasattr(QsciScintilla, "annotate"):
6922 QsciScintilla.SCI_STYLESETBACK, 7121 QsciScintilla.SCI_STYLESETBACK,
6923 self.annotationStyleStyle, 7122 self.annotationStyleStyle,
6924 Preferences.getEditorColour("AnnotationsStyleBackground"), 7123 Preferences.getEditorColour("AnnotationsStyleBackground"),
6925 ) 7124 )
6926 7125
7126 self.annotationInfoStyle = self.annotationStyleStyle + 1
7127 self.SendScintilla(
7128 QsciScintilla.SCI_STYLESETFORE,
7129 self.annotationInfoStyle,
7130 Preferences.getEditorColour("AnnotationsInfoForeground"),
7131 )
7132 self.SendScintilla(
7133 QsciScintilla.SCI_STYLESETBACK,
7134 self.annotationInfoStyle,
7135 Preferences.getEditorColour("AnnotationsInfoBackground"),
7136 )
7137
6927 def __setAnnotation(self, line): 7138 def __setAnnotation(self, line):
6928 """ 7139 """
6929 Private method to set the annotations for the given line. 7140 Private method to set the annotations for the given line.
6930 7141
6931 @param line number of the line that needs annotation (integer) 7142 @param line number of the line that needs annotation (integer)
6932 """ 7143 """
6933 if hasattr(QsciScintilla, "annotate"): 7144 if hasattr(QsciScintilla, "annotate"):
6934 warningAnnotations = [] 7145 warningAnnotations = []
6935 errorAnnotations = [] 7146 errorAnnotations = []
6936 styleAnnotations = [] 7147 styleAnnotations = []
7148 infoAnnotations = []
6937 7149
6938 # step 1: do warnings 7150 # step 1: do warnings
6939 for handle in self.warnings: 7151 for handle in self._warnings:
6940 if self.markerLine(handle) == line: 7152 if self.markerLine(handle) == line:
6941 for msg, warningType in self.warnings[handle]: 7153 for msg, warningType in self._warnings[handle]:
6942 if warningType == Editor.WarningStyle: 7154 if warningType == Editor.WarningInfo:
7155 infoAnnotations.append(self.tr("Info: {0}").format(msg))
7156 elif warningType == Editor.WarningError:
7157 errorAnnotations.append(self.tr("Error: {0}").format(msg))
7158 elif warningType == Editor.WarningStyle:
6943 styleAnnotations.append(self.tr("Style: {0}").format(msg)) 7159 styleAnnotations.append(self.tr("Style: {0}").format(msg))
6944 elif warningType == Editor.WarningPython: 7160 elif warningType == Editor.WarningPython:
6945 warningAnnotations.append(msg) 7161 warningAnnotations.append(msg)
6946 else: 7162 else:
6947 warningAnnotations.append( 7163 warningAnnotations.append(
6952 for handle in self.syntaxerrors: 7168 for handle in self.syntaxerrors:
6953 if self.markerLine(handle) == line: 7169 if self.markerLine(handle) == line:
6954 for msg, _ in self.syntaxerrors[handle]: 7170 for msg, _ in self.syntaxerrors[handle]:
6955 errorAnnotations.append(self.tr("Error: {0}").format(msg)) 7171 errorAnnotations.append(self.tr("Error: {0}").format(msg))
6956 7172
7173 # step 3: assemble the annotation
6957 annotations = [] 7174 annotations = []
7175 if infoAnnotations:
7176 annotationInfoTxt = "\n".join(infoAnnotations)
7177 if styleAnnotations or warningAnnotations or errorAnnotations:
7178 annotationInfoTxt += "\n"
7179 annotations.append(
7180 QsciStyledText(annotationInfoTxt, self.annotationInfoStyle)
7181 )
7182
6958 if styleAnnotations: 7183 if styleAnnotations:
6959 annotationStyleTxt = "\n".join(styleAnnotations) 7184 annotationStyleTxt = "\n".join(styleAnnotations)
6960 if warningAnnotations or errorAnnotations: 7185 if warningAnnotations or errorAnnotations:
6961 annotationStyleTxt += "\n" 7186 annotationStyleTxt += "\n"
6962 annotations.append( 7187 annotations.append(
6986 """ 7211 """
6987 Private method to refresh the annotations. 7212 Private method to refresh the annotations.
6988 """ 7213 """
6989 if hasattr(QsciScintilla, "annotate"): 7214 if hasattr(QsciScintilla, "annotate"):
6990 self.clearAnnotations() 7215 self.clearAnnotations()
6991 for handle in list(self.warnings.keys()) + list(self.syntaxerrors.keys()): 7216 for handle in self._warnings:
7217 line = self.markerLine(handle)
7218 self.__setAnnotation(line)
7219 for handle in self.syntaxerrors:
6992 line = self.markerLine(handle) 7220 line = self.markerLine(handle)
6993 self.__setAnnotation(line) 7221 self.__setAnnotation(line)
6994 7222
6995 ################################################################# 7223 #################################################################
6996 ## Fold handling methods 7224 ## Fold handling methods
6997 ################################################################# 7225 #################################################################
6998 7226
7227 @pyqtSlot()
6999 def toggleCurrentFold(self): 7228 def toggleCurrentFold(self):
7000 """ 7229 """
7001 Public slot to toggle the fold containing the current line. 7230 Public slot to toggle the fold containing the current line.
7002 """ 7231 """
7003 line, index = self.getCursorPosition() 7232 line, index = self.getCursorPosition()
7004 self.foldLine(line) 7233 self.foldLine(line)
7005 7234
7006 def expandFoldWithChildren(self, line=-1): 7235 def expandFoldWithChildren(self, line=-1):
7007 """ 7236 """
7008 Public slot to expand the current fold including its children. 7237 Public method to expand the current fold including its children.
7009 7238
7010 @param line number of line to be expanded 7239 @param line number of line to be expanded
7011 @type int 7240 @type int
7012 """ 7241 """
7013 if line == -1: 7242 if line == -1:
7017 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_EXPAND 7246 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_EXPAND
7018 ) 7247 )
7019 7248
7020 def collapseFoldWithChildren(self, line=-1): 7249 def collapseFoldWithChildren(self, line=-1):
7021 """ 7250 """
7022 Public slot to collapse the current fold including its children. 7251 Public method to collapse the current fold including its children.
7023 7252
7024 @param line number of line to be expanded 7253 @param line number of line to be expanded
7025 @type int 7254 @type int
7026 """ 7255 """
7027 if line == -1: 7256 if line == -1:
7029 7258
7030 self.SendScintilla( 7259 self.SendScintilla(
7031 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_CONTRACT 7260 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_CONTRACT
7032 ) 7261 )
7033 7262
7263 @pyqtSlot()
7034 def __contextMenuExpandFoldWithChildren(self): 7264 def __contextMenuExpandFoldWithChildren(self):
7035 """ 7265 """
7036 Private slot to handle the context menu expand with children action. 7266 Private slot to handle the context menu expand with children action.
7037 """ 7267 """
7038 self.expandFoldWithChildren(self.line) 7268 self.expandFoldWithChildren(self.line)
7039 7269
7270 @pyqtSlot()
7040 def __contextMenuCollapseFoldWithChildren(self): 7271 def __contextMenuCollapseFoldWithChildren(self):
7041 """ 7272 """
7042 Private slot to handle the context menu collapse with children action. 7273 Private slot to handle the context menu collapse with children action.
7043 """ 7274 """
7044 self.collapseFoldWithChildren(self.line) 7275 self.collapseFoldWithChildren(self.line)
7053 7284
7054 @return Tuple of macro name and a flag, indicating, if the user 7285 @return Tuple of macro name and a flag, indicating, if the user
7055 pressed ok or canceled the operation. (string, boolean) 7286 pressed ok or canceled the operation. (string, boolean)
7056 """ 7287 """
7057 qs = [] 7288 qs = []
7058 for s in list(self.macros.keys()): 7289 for s in self.macros:
7059 qs.append(s) 7290 qs.append(s)
7060 qs.sort() 7291 qs.sort()
7061 return QInputDialog.getItem( 7292 return QInputDialog.getItem(
7062 self, self.tr("Macro Name"), self.tr("Select a macro name:"), qs, 0, False 7293 self, self.tr("Macro Name"), self.tr("Select a macro name:"), qs, 0, False
7063 ) 7294 )
7389 Protected method called when the editor loses focus. 7620 Protected method called when the editor loses focus.
7390 7621
7391 @param event the event object 7622 @param event the event object
7392 @type QFocusEvent 7623 @type QFocusEvent
7393 """ 7624 """
7625 if Preferences.getEditor("AutosaveOnFocusLost") and self.__shouldAutosave():
7626 self.saveFile()
7627
7394 self.vm.editorActGrp.setEnabled(False) 7628 self.vm.editorActGrp.setEnabled(False)
7395 self.setCaretWidth(0) 7629 self.setCaretWidth(0)
7396 7630
7397 self.cancelCallTips() 7631 self.cancelCallTips()
7398 7632
7583 """ 7817 """
7584 return ( 7818 return (
7585 self.isLocalFile() and not os.access(self.fileName, os.W_OK) 7819 self.isLocalFile() and not os.access(self.fileName, os.W_OK)
7586 ) or self.isReadOnly() 7820 ) or self.isReadOnly()
7587 7821
7822 @pyqtSlot()
7588 def refresh(self): 7823 def refresh(self):
7589 """ 7824 """
7590 Public slot to refresh the editor contents. 7825 Public slot to refresh the editor contents.
7591 """ 7826 """
7592 # save cursor position 7827 # save cursor position
7601 7836
7602 # clear flakes warning markers 7837 # clear flakes warning markers
7603 self.clearWarnings() 7838 self.clearWarnings()
7604 7839
7605 # clear breakpoint markers 7840 # clear breakpoint markers
7606 for handle in list(self.breaks.keys()): 7841 for handle in self.breaks:
7607 self.markerDeleteHandle(handle) 7842 self.markerDeleteHandle(handle)
7608 self.breaks.clear() 7843 self.breaks.clear()
7609 7844
7610 if not os.path.exists(self.fileName): 7845 if not os.path.exists(self.fileName):
7611 # close the file, if it was deleted in the background 7846 # close the file, if it was deleted in the background
7757 7992
7758 menu.aboutToShow.connect(self.__showContextMenuResources) 7993 menu.aboutToShow.connect(self.__showContextMenuResources)
7759 7994
7760 return menu 7995 return menu
7761 7996
7997 @pyqtSlot()
7762 def __showContextMenuResources(self): 7998 def __showContextMenuResources(self):
7763 """ 7999 """
7764 Private slot handling the aboutToShow signal of the resources context 8000 Private slot handling the aboutToShow signal of the resources context
7765 menu. 8001 menu.
7766 """ 8002 """
7934 self.applicationDiagram = UMLDialog( 8170 self.applicationDiagram = UMLDialog(
7935 UMLDialogType.APPLICATION_DIAGRAM, self.project, self, noModules=not res 8171 UMLDialogType.APPLICATION_DIAGRAM, self.project, self, noModules=not res
7936 ) 8172 )
7937 self.applicationDiagram.show() 8173 self.applicationDiagram.show()
7938 8174
8175 @pyqtSlot()
7939 def __loadDiagram(self): 8176 def __loadDiagram(self):
7940 """ 8177 """
7941 Private slot to load a diagram from file. 8178 Private slot to load a diagram from file.
7942 """ 8179 """
7943 from eric7.Graphics.UMLDialog import UMLDialog, UMLDialogType 8180 from eric7.Graphics.UMLDialog import UMLDialog, UMLDialogType
7952 8189
7953 ####################################################################### 8190 #######################################################################
7954 ## Typing aids related methods below 8191 ## Typing aids related methods below
7955 ####################################################################### 8192 #######################################################################
7956 8193
8194 @pyqtSlot()
7957 def __toggleTypingAids(self): 8195 def __toggleTypingAids(self):
7958 """ 8196 """
7959 Private slot to toggle the typing aids. 8197 Private slot to toggle the typing aids.
7960 """ 8198 """
7961 if self.menuActs["TypingAidsEnabled"].isChecked(): 8199 if self.menuActs["TypingAidsEnabled"].isChecked():
8049 8287
8050 ####################################################################### 8288 #######################################################################
8051 ## Project related methods 8289 ## Project related methods
8052 ####################################################################### 8290 #######################################################################
8053 8291
8292 @pyqtSlot()
8054 def __projectPropertiesChanged(self): 8293 def __projectPropertiesChanged(self):
8055 """ 8294 """
8056 Private slot to handle changes of the project properties. 8295 Private slot to handle changes of the project properties.
8057 """ 8296 """
8058 if self.spell: 8297 if self.spell:
8078 self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel 8317 self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel
8079 ) 8318 )
8080 8319
8081 self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged) 8320 self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged)
8082 8321
8322 @pyqtSlot()
8083 def projectOpened(self): 8323 def projectOpened(self):
8084 """ 8324 """
8085 Public slot to handle the opening of a project. 8325 Public slot to handle the opening of a project.
8086 """ 8326 """
8087 if self.fileName and self.project.isProjectCategory(self.fileName, "SOURCES"): 8327 if self.fileName and self.project.isProjectCategory(self.fileName, "SOURCES"):
8088 self.project.projectPropertiesChanged.connect( 8328 self.project.projectPropertiesChanged.connect(
8089 self.__projectPropertiesChanged 8329 self.__projectPropertiesChanged
8090 ) 8330 )
8091 self.setSpellingForProject() 8331 self.setSpellingForProject()
8092 8332
8333 @pyqtSlot()
8093 def projectClosed(self): 8334 def projectClosed(self):
8094 """ 8335 """
8095 Public slot to handle the closing of a project. 8336 Public slot to handle the closing of a project.
8096 """ 8337 """
8097 with contextlib.suppress(TypeError): 8338 with contextlib.suppress(TypeError):
8115 8356
8116 return "" 8357 return ""
8117 8358
8118 def __setSpellingLanguage(self, language, pwl="", pel=""): 8359 def __setSpellingLanguage(self, language, pwl="", pel=""):
8119 """ 8360 """
8120 Private slot to set the spell checking language. 8361 Private method to set the spell checking language.
8121 8362
8122 @param language spell checking language to be set (string) 8363 @param language spell checking language to be set (string)
8123 @param pwl name of the personal/project word list (string) 8364 @param pwl name of the personal/project word list (string)
8124 @param pel name of the personal/project exclude list (string) 8365 @param pel name of the personal/project exclude list (string)
8125 """ 8366 """
8215 @pyqtSlot(int) 8456 @pyqtSlot(int)
8216 def __spellCharAdded(self, charNumber): 8457 def __spellCharAdded(self, charNumber):
8217 """ 8458 """
8218 Private slot called to handle the user entering a character. 8459 Private slot called to handle the user entering a character.
8219 8460
8220 @param charNumber value of the character entered (integer) 8461 @param charNumber value of the character entered
8462 @type int
8221 """ 8463 """
8222 if self.spell: 8464 if self.spell:
8223 if not chr(charNumber).isalnum(): 8465 if not chr(charNumber).isalnum():
8224 self.spell.checkWord(self.positionBefore(self.currentPosition()), True) 8466 self.spell.checkWord(self.positionBefore(self.currentPosition()), True)
8225 elif self.hasIndicator(self.spellingIndicator, self.currentPosition()): 8467 elif self.hasIndicator(self.spellingIndicator, self.currentPosition()):
8226 self.spell.checkWord(self.currentPosition()) 8468 self.spell.checkWord(self.currentPosition())
8227 8469
8470 @pyqtSlot()
8228 def checkSpelling(self): 8471 def checkSpelling(self):
8229 """ 8472 """
8230 Public slot to perform an interactive spell check of the document. 8473 Public slot to perform an interactive spell check of the document.
8231 """ 8474 """
8232 from .SpellCheckingDialog import SpellCheckingDialog 8475 from .SpellCheckingDialog import SpellCheckingDialog
8237 dlg.exec() 8480 dlg.exec()
8238 self.setCursorPosition(cline, cindex) 8481 self.setCursorPosition(cline, cindex)
8239 if Preferences.getEditor("AutoSpellCheckingEnabled"): 8482 if Preferences.getEditor("AutoSpellCheckingEnabled"):
8240 self.spell.checkDocumentIncrementally() 8483 self.spell.checkDocumentIncrementally()
8241 8484
8485 @pyqtSlot()
8242 def __checkSpellingSelection(self): 8486 def __checkSpellingSelection(self):
8243 """ 8487 """
8244 Private slot to spell check the current selection. 8488 Private slot to spell check the current selection.
8245 """ 8489 """
8246 from .SpellCheckingDialog import SpellCheckingDialog 8490 from .SpellCheckingDialog import SpellCheckingDialog
8249 startPos = self.positionFromLineIndex(sline, sindex) 8493 startPos = self.positionFromLineIndex(sline, sindex)
8250 endPos = self.positionFromLineIndex(eline, eindex) 8494 endPos = self.positionFromLineIndex(eline, eindex)
8251 dlg = SpellCheckingDialog(self.spell, startPos, endPos, self) 8495 dlg = SpellCheckingDialog(self.spell, startPos, endPos, self)
8252 dlg.exec() 8496 dlg.exec()
8253 8497
8498 @pyqtSlot()
8254 def __checkSpellingWord(self): 8499 def __checkSpellingWord(self):
8255 """ 8500 """
8256 Private slot to check the word below the spelling context menu. 8501 Private slot to check the word below the spelling context menu.
8257 """ 8502 """
8258 from .SpellCheckingDialog import SpellCheckingDialog 8503 from .SpellCheckingDialog import SpellCheckingDialog
8262 wordStartPos = self.positionFromLineIndex(line, wordStart) 8507 wordStartPos = self.positionFromLineIndex(line, wordStart)
8263 wordEndPos = self.positionFromLineIndex(line, wordEnd) 8508 wordEndPos = self.positionFromLineIndex(line, wordEnd)
8264 dlg = SpellCheckingDialog(self.spell, wordStartPos, wordEndPos, self) 8509 dlg = SpellCheckingDialog(self.spell, wordStartPos, wordEndPos, self)
8265 dlg.exec() 8510 dlg.exec()
8266 8511
8512 @pyqtSlot()
8267 def __showContextMenuSpelling(self): 8513 def __showContextMenuSpelling(self):
8268 """ 8514 """
8269 Private slot to set up the spelling menu before it is shown. 8515 Private slot to set up the spelling menu before it is shown.
8270 """ 8516 """
8271 self.spellingMenu.clear() 8517 self.spellingMenu.clear()
8287 ) 8533 )
8288 self.spellingMenu.addAction(self.tr("Ignore All"), self.__ignoreSpellingAlways) 8534 self.spellingMenu.addAction(self.tr("Ignore All"), self.__ignoreSpellingAlways)
8289 8535
8290 self.showMenu.emit("Spelling", self.spellingMenu, self) 8536 self.showMenu.emit("Spelling", self.spellingMenu, self)
8291 8537
8538 @pyqtSlot(QAction)
8292 def __contextMenuSpellingTriggered(self, action): 8539 def __contextMenuSpellingTriggered(self, action):
8293 """ 8540 """
8294 Private slot to handle the selection of a suggestion of the spelling 8541 Private slot to handle the selection of a suggestion of the spelling
8295 context menu. 8542 context menu.
8296 8543
8297 @param action reference to the action that was selected (QAction) 8544 @param action reference to the action that was selected
8545 @type QAction
8298 """ 8546 """
8299 if action in self.spellingSuggActs: 8547 if action in self.spellingSuggActs:
8300 replacement = action.text() 8548 replacement = action.text()
8301 line, index = self.lineIndexFromPosition(self.spellingMenuPos) 8549 line, index = self.lineIndexFromPosition(self.spellingMenuPos)
8302 wordStart, wordEnd = self.getWordBoundaries(line, index) 8550 wordStart, wordEnd = self.getWordBoundaries(line, index)
8304 self.beginUndoAction() 8552 self.beginUndoAction()
8305 self.removeSelectedText() 8553 self.removeSelectedText()
8306 self.insert(replacement) 8554 self.insert(replacement)
8307 self.endUndoAction() 8555 self.endUndoAction()
8308 8556
8557 @pyqtSlot()
8309 def __addToSpellingDictionary(self): 8558 def __addToSpellingDictionary(self):
8310 """ 8559 """
8311 Private slot to add the word below the spelling context menu to the 8560 Private slot to add the word below the spelling context menu to the
8312 dictionary. 8561 dictionary.
8313 """ 8562 """
8318 wordStart, wordEnd = self.getWordBoundaries(line, index) 8567 wordStart, wordEnd = self.getWordBoundaries(line, index)
8319 self.clearIndicator(self.spellingIndicator, line, wordStart, line, wordEnd) 8568 self.clearIndicator(self.spellingIndicator, line, wordStart, line, wordEnd)
8320 if Preferences.getEditor("AutoSpellCheckingEnabled"): 8569 if Preferences.getEditor("AutoSpellCheckingEnabled"):
8321 self.spell.checkDocumentIncrementally() 8570 self.spell.checkDocumentIncrementally()
8322 8571
8572 @pyqtSlot()
8323 def __removeFromSpellingDictionary(self): 8573 def __removeFromSpellingDictionary(self):
8324 """ 8574 """
8325 Private slot to remove the word below the context menu to the 8575 Private slot to remove the word below the context menu to the
8326 dictionary. 8576 dictionary.
8327 """ 8577 """
8366 self.__inRemoteSharedEdit, 8616 self.__inRemoteSharedEdit,
8367 ) 8617 )
8368 8618
8369 def shareConnected(self, connected): 8619 def shareConnected(self, connected):
8370 """ 8620 """
8371 Public slot to handle a change of the connected state. 8621 Public method to handle a change of the connected state.
8372 8622
8373 @param connected flag indicating the connected state (boolean) 8623 @param connected flag indicating the connected state (boolean)
8374 """ 8624 """
8375 if not connected: 8625 if not connected:
8376 self.__inRemoteSharedEdit = False 8626 self.__inRemoteSharedEdit = False
8380 self.__isSyncing = False 8630 self.__isSyncing = False
8381 self.__receivedWhileSyncing = [] 8631 self.__receivedWhileSyncing = []
8382 8632
8383 def shareEditor(self, share): 8633 def shareEditor(self, share):
8384 """ 8634 """
8385 Public slot to set the shared status of the editor. 8635 Public method to set the shared status of the editor.
8386 8636
8387 @param share flag indicating the share status (boolean) 8637 @param share flag indicating the share status (boolean)
8388 """ 8638 """
8389 self.__isShared = share 8639 self.__isShared = share
8390 if not share: 8640 if not share:
8391 self.shareConnected(False) 8641 self.shareConnected(False)
8392 8642
8643 @pyqtSlot()
8393 def startSharedEdit(self): 8644 def startSharedEdit(self):
8394 """ 8645 """
8395 Public slot to start a shared edit session for the editor. 8646 Public slot to start a shared edit session for the editor.
8396 """ 8647 """
8397 self.__inSharedEdit = True 8648 self.__inSharedEdit = True
8403 ).toHex(), 8654 ).toHex(),
8404 encoding="utf-8", 8655 encoding="utf-8",
8405 ) 8656 )
8406 self.__send(Editor.StartEditToken, hashStr) 8657 self.__send(Editor.StartEditToken, hashStr)
8407 8658
8659 @pyqtSlot()
8408 def sendSharedEdit(self): 8660 def sendSharedEdit(self):
8409 """ 8661 """
8410 Public slot to end a shared edit session for the editor and 8662 Public slot to end a shared edit session for the editor and
8411 send the changes. 8663 send the changes.
8412 """ 8664 """
8415 self.__inSharedEdit = False 8667 self.__inSharedEdit = False
8416 self.__savedText = "" 8668 self.__savedText = ""
8417 8669
8418 def cancelSharedEdit(self, send=True): 8670 def cancelSharedEdit(self, send=True):
8419 """ 8671 """
8420 Public slot to cancel a shared edit session for the editor. 8672 Public method to cancel a shared edit session for the editor.
8421 8673
8422 @param send flag indicating to send the CancelEdit command (boolean) 8674 @param send flag indicating to send the CancelEdit command (boolean)
8423 """ 8675 """
8424 self.__inSharedEdit = False 8676 self.__inSharedEdit = False
8425 self.__savedText = "" 8677 self.__savedText = ""
8445 elif token == Editor.CancelEditToken: 8697 elif token == Editor.CancelEditToken:
8446 msg = "{0}{1}c".format(token, Editor.Separator) 8698 msg = "{0}{1}c".format(token, Editor.Separator)
8447 8699
8448 self.vm.send(self.fileName, msg) 8700 self.vm.send(self.fileName, msg)
8449 8701
8702 @pyqtSlot(str)
8450 def receive(self, command): 8703 def receive(self, command):
8451 """ 8704 """
8452 Public slot to handle received editor commands. 8705 Public slot to handle received editor commands.
8453 8706
8454 @param command command string (string) 8707 @param command command string
8708 @type str
8455 """ 8709 """
8456 if self.__isShared: 8710 if self.__isShared:
8457 if self.__isSyncing and not command.startswith( 8711 if self.__isSyncing and not command.startswith(
8458 Editor.SyncToken + Editor.Separator 8712 Editor.SyncToken + Editor.Separator
8459 ): 8713 ):
8477 elif token == Editor.RequestSyncToken: 8731 elif token == Editor.RequestSyncToken:
8478 self.__processRequestSyncCommand(argsString) 8732 self.__processRequestSyncCommand(argsString)
8479 elif token == Editor.SyncToken: 8733 elif token == Editor.SyncToken:
8480 self.__processSyncCommand(argsString) 8734 self.__processSyncCommand(argsString)
8481 8735
8736 @pyqtSlot(str)
8482 def __processStartEditCommand(self, argsString): 8737 def __processStartEditCommand(self, argsString):
8483 """ 8738 """
8484 Private slot to process a remote StartEdit command. 8739 Private slot to process a remote StartEdit command.
8485 8740
8486 @param argsString string containing the command parameters (string) 8741 @param argsString string containing the command parameters
8742 @type str
8487 """ 8743 """
8488 if not self.__inSharedEdit and not self.__inRemoteSharedEdit: 8744 if not self.__inSharedEdit and not self.__inRemoteSharedEdit:
8489 self.__inRemoteSharedEdit = True 8745 self.__inRemoteSharedEdit = True
8490 self.setReadOnly(True) 8746 self.setReadOnly(True)
8491 self.__updateReadOnly() 8747 self.__updateReadOnly()
8526 commands.append(formatStr.format("r", j1, i2 - i1, j2 - j1)) 8782 commands.append(formatStr.format("r", j1, i2 - i1, j2 - j1))
8527 commands.extend(newL[j1:j2]) 8783 commands.extend(newL[j1:j2])
8528 8784
8529 return "\n".join(commands) + "\n" 8785 return "\n".join(commands) + "\n"
8530 8786
8787 @pyqtSlot(str)
8531 def __processEndEditCommand(self, argsString): 8788 def __processEndEditCommand(self, argsString):
8532 """ 8789 """
8533 Private slot to process a remote EndEdit command. 8790 Private slot to process a remote EndEdit command.
8534 8791
8535 @param argsString string containing the command parameters (string) 8792 @param argsString string containing the command parameters
8793 @type str
8536 """ 8794 """
8537 commands = argsString.splitlines() 8795 commands = argsString.splitlines()
8538 sep = self.getLineSeparator() 8796 sep = self.getLineSeparator()
8539 cur = self.getCursorPosition() 8797 cur = self.getCursorPosition()
8540 8798
8565 self.__updateReadOnly() 8823 self.__updateReadOnly()
8566 self.__inRemoteSharedEdit = False 8824 self.__inRemoteSharedEdit = False
8567 8825
8568 self.setCursorPosition(*cur) 8826 self.setCursorPosition(*cur)
8569 8827
8828 @pyqtSlot(str)
8570 def __processRequestSyncCommand(self, argsString): 8829 def __processRequestSyncCommand(self, argsString):
8571 """ 8830 """
8572 Private slot to process a remote RequestSync command. 8831 Private slot to process a remote RequestSync command.
8573 8832
8574 @param argsString string containing the command parameters (string) 8833 @param argsString string containing the command parameters
8834 @type str
8575 """ 8835 """
8576 if self.__inSharedEdit: 8836 if self.__inSharedEdit:
8577 hashStr = str( 8837 hashStr = str(
8578 QCryptographicHash.hash( 8838 QCryptographicHash.hash(
8579 Utilities.encode(self.__savedText, self.encoding)[0], 8839 Utilities.encode(self.__savedText, self.encoding)[0],
8583 ) 8843 )
8584 8844
8585 if hashStr == argsString: 8845 if hashStr == argsString:
8586 self.__send(Editor.SyncToken, self.__savedText) 8846 self.__send(Editor.SyncToken, self.__savedText)
8587 8847
8848 @pyqtSlot(str)
8588 def __processSyncCommand(self, argsString): 8849 def __processSyncCommand(self, argsString):
8589 """ 8850 """
8590 Private slot to process a remote Sync command. 8851 Private slot to process a remote Sync command.
8591 8852
8592 @param argsString string containing the command parameters (string) 8853 @param argsString string containing the command parameters
8854 @type str
8593 """ 8855 """
8594 if self.__isSyncing: 8856 if self.__isSyncing:
8595 cur = self.getCursorPosition() 8857 cur = self.getCursorPosition()
8596 8858
8597 self.setReadOnly(False) 8859 self.setReadOnly(False)
8612 8874
8613 ####################################################################### 8875 #######################################################################
8614 ## Special search related methods 8876 ## Special search related methods
8615 ####################################################################### 8877 #######################################################################
8616 8878
8879 @pyqtSlot()
8617 def searchCurrentWordForward(self): 8880 def searchCurrentWordForward(self):
8618 """ 8881 """
8619 Public slot to search the current word forward. 8882 Public slot to search the current word forward.
8620 """ 8883 """
8621 self.__searchCurrentWord(forward=True) 8884 self.__searchCurrentWord(forward=True)
8622 8885
8886 @pyqtSlot()
8623 def searchCurrentWordBackward(self): 8887 def searchCurrentWordBackward(self):
8624 """ 8888 """
8625 Public slot to search the current word backward. 8889 Public slot to search the current word backward.
8626 """ 8890 """
8627 self.__searchCurrentWord(forward=False) 8891 self.__searchCurrentWord(forward=False)
8664 8928
8665 ####################################################################### 8929 #######################################################################
8666 ## Sort related methods 8930 ## Sort related methods
8667 ####################################################################### 8931 #######################################################################
8668 8932
8933 @pyqtSlot()
8669 def sortLines(self): 8934 def sortLines(self):
8670 """ 8935 """
8671 Public slot to sort the lines spanned by a rectangular selection. 8936 Public slot to sort the lines spanned by a rectangular selection.
8672 """ 8937 """
8673 from .SortOptionsDialog import SortOptionsDialog 8938 from .SortOptionsDialog import SortOptionsDialog
8868 a plug-in. 9133 a plug-in.
8869 9134
8870 @param name name of the plug-in 9135 @param name name of the plug-in
8871 @type str 9136 @type str
8872 """ 9137 """
8873 keys = [] 9138 for key in list(self.__mouseClickHandlers.keys()):
8874 for key in self.__mouseClickHandlers:
8875 if self.__mouseClickHandlers[key][0] == name: 9139 if self.__mouseClickHandlers[key][0] == name:
8876 keys.append(key) 9140 del self.__mouseClickHandlers[key]
8877 for key in keys:
8878 del self.__mouseClickHandlers[key]
8879 9141
8880 def gotoReferenceHandler(self, referencesList): 9142 def gotoReferenceHandler(self, referencesList):
8881 """ 9143 """
8882 Public method to handle a list of references to perform a goto. 9144 Public method to handle a list of references to perform a goto.
8883 9145
8922 9184
8923 ####################################################################### 9185 #######################################################################
8924 ## Methods implementing a Shell interface 9186 ## Methods implementing a Shell interface
8925 ####################################################################### 9187 #######################################################################
8926 9188
9189 @pyqtSlot()
8927 def __executeSelection(self): 9190 def __executeSelection(self):
8928 """ 9191 """
8929 Private slot to execute the selected text in the shell window. 9192 Private slot to execute the selected text in the shell window.
8930 """ 9193 """
8931 txt = self.selectedText() 9194 txt = self.selectedText()
9134 300, lambda: self.__popupDocstringMenu(lineText2Cursor, cursorPosition) 9397 300, lambda: self.__popupDocstringMenu(lineText2Cursor, cursorPosition)
9135 ) 9398 )
9136 9399
9137 def __popupDocstringMenu(self, lastLineText, lastCursorPosition): 9400 def __popupDocstringMenu(self, lastLineText, lastCursorPosition):
9138 """ 9401 """
9139 Private slot to pop up a menu asking the user, if a docstring should be 9402 Private method to pop up a menu asking the user, if a docstring should be
9140 inserted. 9403 inserted.
9141 9404
9142 @param lastLineText line contents when the delay timer was started 9405 @param lastLineText line contents when the delay timer was started
9143 @type str 9406 @type str
9144 @param lastCursorPosition position of the cursor when the delay timer 9407 @param lastCursorPosition position of the cursor when the delay timer
9145 was started (line and index) 9408 was started (line and index)
9146 @type tuple of (int, int) 9409 @type tuple of (int, int)
9147 """ 9410 """
9411 from .DocstringGenerator.BaseDocstringGenerator import DocstringMenuForEnterOnly
9412
9148 cursorPosition = self.getCursorPosition() 9413 cursorPosition = self.getCursorPosition()
9149 if lastCursorPosition != cursorPosition: 9414 if lastCursorPosition != cursorPosition:
9150 return 9415 return
9151 9416
9152 if self.text(cursorPosition[0])[: cursorPosition[1]] != lastLineText: 9417 if self.text(cursorPosition[0])[: cursorPosition[1]] != lastLineText:
9153 return 9418 return
9154 9419
9155 generator = self.getDocstringGenerator() 9420 generator = self.getDocstringGenerator()
9156 if generator.hasFunctionDefinition(cursorPosition): 9421 if generator.hasFunctionDefinition(cursorPosition):
9157 from .DocstringGenerator.BaseDocstringGenerator import ( # __IGNORE_WARNING__
9158 DocstringMenuForEnterOnly,
9159 )
9160
9161 docstringMenu = DocstringMenuForEnterOnly(self) 9422 docstringMenu = DocstringMenuForEnterOnly(self)
9162 act = docstringMenu.addAction( 9423 act = docstringMenu.addAction(
9163 EricPixmapCache.getIcon("fileText"), 9424 EricPixmapCache.getIcon("fileText"),
9164 self.tr("Generate Docstring"), 9425 self.tr("Generate Docstring"),
9165 lambda: generator.insertDocstring(cursorPosition, fromStart=False), 9426 lambda: generator.insertDocstring(cursorPosition, fromStart=False),
9197 else: 9458 else:
9198 self.__cancelMouseHoverHelp() 9459 self.__cancelMouseHoverHelp()
9199 else: 9460 else:
9200 self.__cancelMouseHoverHelp() 9461 self.__cancelMouseHoverHelp()
9201 9462
9463 @pyqtSlot()
9202 def __cancelMouseHoverHelp(self): 9464 def __cancelMouseHoverHelp(self):
9203 """ 9465 """
9204 Private slot cancelling the display of mouse hover help. 9466 Private slot cancelling the display of mouse hover help.
9205 """ 9467 """
9206 if self.__showingMouseHoverHelp: 9468 if self.__showingMouseHoverHelp:

eric ide

mercurial