eric6/QScintilla/Editor.py

branch
maintenance
changeset 8043
0acf98cd089a
parent 7924
8a96736d465e
parent 8004
38d359e2ded7
child 8142
43248bafe9b2
equal deleted inserted replaced
7991:866adc8c315b 8043:0acf98cd089a
2 2
3 # Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 3 # Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 # 4 #
5 5
6 """ 6 """
7 Module implementing the editor component of the eric6 IDE. 7 Module implementing the editor component of the eric IDE.
8 """ 8 """
9 9
10 import os 10 import os
11 import re 11 import re
12 import difflib 12 import difflib
44 TemplateCompletionListID = 2 44 TemplateCompletionListID = 2
45 45
46 46
47 class Editor(QsciScintillaCompat): 47 class Editor(QsciScintillaCompat):
48 """ 48 """
49 Class implementing the editor component of the eric6 IDE. 49 Class implementing the editor component of the eric IDE.
50 50
51 @signal modificationStatusChanged(bool, QsciScintillaCompat) emitted when 51 @signal modificationStatusChanged(bool, QsciScintillaCompat) emitted when
52 the modification status has changed 52 the modification status has changed
53 @signal undoAvailable(bool) emitted to signal the undo availability 53 @signal undoAvailable(bool) emitted to signal the undo availability
54 @signal redoAvailable(bool) emitted to signal the redo availability 54 @signal redoAvailable(bool) emitted to signal the redo availability
155 r"""^\|\|\|\|\|\|\| .*?$""", 155 r"""^\|\|\|\|\|\|\| .*?$""",
156 r"""^=======.*?$""", 156 r"""^=======.*?$""",
157 r"""^>>>>>>> .*?$""", 157 r"""^>>>>>>> .*?$""",
158 ) 158 )
159 159
160 EncloseChars = {
161 '"': '"',
162 "'": "'",
163 "(": "()",
164 ")": "()",
165 "{": "{}", # __IGNORE_WARNING_M613__
166 "}": "{}", # __IGNORE_WARNING_M613__
167 "[": "[]",
168 "]": "[]",
169 "<": "<>",
170 ">": "<>",
171 }
172
160 def __init__(self, dbs, fn="", vm=None, 173 def __init__(self, dbs, fn="", vm=None,
161 filetype="", editor=None, tv=None): 174 filetype="", editor=None, tv=None):
162 """ 175 """
163 Constructor 176 Constructor
164 177
240 253
241 self.acAPI = False 254 self.acAPI = False
242 255
243 self.__lastEditPosition = None 256 self.__lastEditPosition = None
244 self.__annotationLines = 0 257 self.__annotationLines = 0
258
259 self.__docstringGenerator = None
245 260
246 # list of clones 261 # list of clones
247 self.__clones = [] 262 self.__clones = []
248 263
249 # clear QScintilla defined keyboard commands 264 # clear QScintilla defined keyboard commands
807 self.tr('Stream Comment'), 822 self.tr('Stream Comment'),
808 self.streamCommentLineOrSelection) 823 self.streamCommentLineOrSelection)
809 self.menuActs["BoxComment"] = self.menu.addAction( 824 self.menuActs["BoxComment"] = self.menu.addAction(
810 self.tr('Box Comment'), 825 self.tr('Box Comment'),
811 self.boxCommentLineOrSelection) 826 self.boxCommentLineOrSelection)
827 self.menu.addSeparator()
828 self.menuActs["Docstring"] = self.menu.addAction(
829 self.tr("Generate Docstring"),
830 self.__insertDocstring)
812 self.menu.addSeparator() 831 self.menu.addSeparator()
813 self.menu.addAction( 832 self.menu.addAction(
814 self.tr('Select to brace'), self.selectToMatchingBrace) 833 self.tr('Select to brace'), self.selectToMatchingBrace)
815 self.menu.addAction(self.tr('Select all'), self.__selectAll) 834 self.menu.addAction(self.tr('Select all'), self.__selectAll)
816 self.menu.addAction( 835 self.menu.addAction(
1444 if language: 1463 if language:
1445 self.filetype = language 1464 self.filetype = language
1446 self.setLanguage(self.supportedLanguages[language][1]) 1465 self.setLanguage(self.supportedLanguages[language][1])
1447 self.checkSyntax() 1466 self.checkSyntax()
1448 1467
1468 self.__docstringGenerator = None
1469
1449 def __languageChanged(self, language, propagate=True): 1470 def __languageChanged(self, language, propagate=True):
1450 """ 1471 """
1451 Private slot handling a change of a connected editor's language. 1472 Private slot handling a change of a connected editor's language.
1452 1473
1453 @param language language to be set (string) 1474 @param language language to be set (string)
1454 @keyparam propagate flag indicating to propagate the change (boolean) 1475 @param propagate flag indicating to propagate the change (boolean)
1455 """ 1476 """
1456 if language == '': 1477 if language == '':
1457 self.__resetLanguage(propagate=propagate) 1478 self.__resetLanguage(propagate=propagate)
1458 elif language == "Guessed": 1479 elif language == "Guessed":
1459 self.setLanguage("dummy.pygments", 1480 self.setLanguage("dummy.pygments",
1466 self.filetype = language 1487 self.filetype = language
1467 self.setLanguage(self.supportedLanguages[language][1], 1488 self.setLanguage(self.supportedLanguages[language][1],
1468 propagate=propagate) 1489 propagate=propagate)
1469 self.checkSyntax() 1490 self.checkSyntax()
1470 1491
1492 self.__docstringGenerator = None
1493
1471 def __resetLanguage(self, propagate=True): 1494 def __resetLanguage(self, propagate=True):
1472 """ 1495 """
1473 Private method used to reset the language selection. 1496 Private method used to reset the language selection.
1474 1497
1475 @keyparam propagate flag indicating to propagate the change (boolean) 1498 @param propagate flag indicating to propagate the change (boolean)
1476 """ 1499 """
1477 if ( 1500 if (
1478 self.lexer_ is not None and 1501 self.lexer_ is not None and
1479 (self.lexer_.lexer() == "container" or 1502 (self.lexer_.lexer() == "container" or
1480 self.lexer_.lexer() is None) 1503 self.lexer_.lexer() is None)
1492 self.__setTextDisplay() 1515 self.__setTextDisplay()
1493 self.__setMarginsDisplay() 1516 self.__setMarginsDisplay()
1494 self.setMonospaced(useMonospaced) 1517 self.setMonospaced(useMonospaced)
1495 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) 1518 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced)
1496 1519
1520 self.__docstringGenerator = None
1521
1497 if not self.inLanguageChanged and propagate: 1522 if not self.inLanguageChanged and propagate:
1498 self.inLanguageChanged = True 1523 self.inLanguageChanged = True
1499 self.languageChanged.emit(self.apiLanguage) 1524 self.languageChanged.emit(self.apiLanguage)
1500 self.inLanguageChanged = False 1525 self.inLanguageChanged = False
1501 1526
1506 1531
1507 @param filename filename used to determine the associated lexer 1532 @param filename filename used to determine the associated lexer
1508 language (string) 1533 language (string)
1509 @param initTextDisplay flag indicating an initialization of the text 1534 @param initTextDisplay flag indicating an initialization of the text
1510 display is required as well (boolean) 1535 display is required as well (boolean)
1511 @keyparam propagate flag indicating to propagate the change (boolean) 1536 @param propagate flag indicating to propagate the change (boolean)
1512 @keyparam pyname name of the pygments lexer to use (string) 1537 @param pyname name of the pygments lexer to use (string)
1513 """ 1538 """
1514 # clear all warning and syntax error markers 1539 # clear all warning and syntax error markers
1515 self.clearSyntaxError() 1540 self.clearSyntaxError()
1516 self.clearWarnings() 1541 self.clearWarnings()
1517 1542
1520 self.__lexerReset = False 1545 self.__lexerReset = False
1521 self.__bindLexer(filename, pyname=pyname) 1546 self.__bindLexer(filename, pyname=pyname)
1522 self.__bindCompleter(filename) 1547 self.__bindCompleter(filename)
1523 self.recolor() 1548 self.recolor()
1524 self.__checkLanguage() 1549 self.__checkLanguage()
1550
1551 self.__docstringGenerator = None
1525 1552
1526 # set the text display 1553 # set the text display
1527 if initTextDisplay: 1554 if initTextDisplay:
1528 self.__setTextDisplay() 1555 self.__setTextDisplay()
1529 1556
1587 def __encodingChanged(self, encoding, propagate=True): 1614 def __encodingChanged(self, encoding, propagate=True):
1588 """ 1615 """
1589 Private slot to handle a change of the encoding. 1616 Private slot to handle a change of the encoding.
1590 1617
1591 @param encoding changed encoding (string) 1618 @param encoding changed encoding (string)
1592 @keyparam propagate flag indicating to propagate the change (boolean) 1619 @param propagate flag indicating to propagate the change (boolean)
1593 """ 1620 """
1594 self.encoding = encoding 1621 self.encoding = encoding
1595 self.__checkEncoding() 1622 self.__checkEncoding()
1596 1623
1597 if not self.inEncodingChanged and propagate: 1624 if not self.inEncodingChanged and propagate:
1701 """ 1728 """
1702 Private slot to set the correct lexer depending on language. 1729 Private slot to set the correct lexer depending on language.
1703 1730
1704 @param filename filename used to determine the associated lexer 1731 @param filename filename used to determine the associated lexer
1705 language (string) 1732 language (string)
1706 @keyparam pyname name of the pygments lexer to use (string) 1733 @param pyname name of the pygments lexer to use (string)
1707 """ 1734 """
1708 if ( 1735 if (
1709 self.lexer_ is not None and 1736 self.lexer_ is not None and
1710 (self.lexer_.lexer() == "container" or 1737 (self.lexer_.lexer() == "container" or
1711 self.lexer_.lexer() is None) 1738 self.lexer_.lexer() is None)
1823 1850
1824 def getLanguage(self, normalized=True, forPygments=False): 1851 def getLanguage(self, normalized=True, forPygments=False):
1825 """ 1852 """
1826 Public method to retrieve the language of the editor. 1853 Public method to retrieve the language of the editor.
1827 1854
1828 @keyparam normalized flag indicating to normalize some Pygments 1855 @param normalized flag indicating to normalize some Pygments
1829 lexer names (boolean) 1856 lexer names (boolean)
1830 @keyparam forPygments flag indicating to normalize some lexer 1857 @param forPygments flag indicating to normalize some lexer
1831 names for Pygments (boolean) 1858 names for Pygments (boolean)
1832 @return language of the editor (string) 1859 @return language of the editor (string)
1833 """ 1860 """
1834 if ( 1861 if (
1835 self.apiLanguage == "Guessed" or 1862 self.apiLanguage == "Guessed" or
3071 def readFile(self, fn, createIt=False, encoding=""): 3098 def readFile(self, fn, createIt=False, encoding=""):
3072 """ 3099 """
3073 Public slot to read the text from a file. 3100 Public slot to read the text from a file.
3074 3101
3075 @param fn filename to read from (string) 3102 @param fn filename to read from (string)
3076 @keyparam createIt flag indicating the creation of a new file, if the 3103 @param createIt flag indicating the creation of a new file, if the
3077 given one doesn't exist (boolean) 3104 given one doesn't exist (boolean)
3078 @keyparam encoding encoding to be used to read the file (string) 3105 @param encoding encoding to be used to read the file (string)
3079 (Note: this parameter overrides encoding detection) 3106 (Note: this parameter overrides encoding detection)
3080 """ 3107 """
3081 self.__loadEditorConfig(fileName=fn) 3108 self.__loadEditorConfig(fileName=fn)
3082 3109
3083 try: 3110 try:
3397 def saveFileAs(self, path=None, toProject=False): 3424 def saveFileAs(self, path=None, toProject=False):
3398 """ 3425 """
3399 Public slot to save a file with a new name. 3426 Public slot to save a file with a new name.
3400 3427
3401 @param path directory to save the file in (string) 3428 @param path directory to save the file in (string)
3402 @keyparam toProject flag indicating a save to project operation 3429 @param toProject flag indicating a save to project operation
3403 (boolean) 3430 (boolean)
3404 @return tuple of two values (boolean, string) giving a success 3431 @return tuple of two values (boolean, string) giving a success
3405 indicator and the name of the saved file 3432 indicator and the name of the saved file
3406 """ 3433 """
3407 return self.saveFile(True, path) 3434 return self.saveFile(True, path)
3446 """ 3473 """
3447 Public slot to ensure, that the specified line is visible. 3474 Public slot to ensure, that the specified line is visible.
3448 3475
3449 @param line line number to make visible 3476 @param line line number to make visible
3450 @type int 3477 @type int
3451 @keyparam expand flag indicating to expand all folds 3478 @param expand flag indicating to expand all folds
3452 @type bool 3479 @type bool
3453 """ 3480 """
3454 self.ensureLineVisible(line - 1) 3481 self.ensureLineVisible(line - 1)
3455 if expand: 3482 if expand:
3456 self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line - 1, 3483 self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line - 1,
3461 Public slot to ensure, that the specified line is visible at the top 3488 Public slot to ensure, that the specified line is visible at the top
3462 of the editor. 3489 of the editor.
3463 3490
3464 @param line line number to make visible 3491 @param line line number to make visible
3465 @type int 3492 @type int
3466 @keyparam expand flag indicating to expand all folds 3493 @param expand flag indicating to expand all folds
3467 @type bool 3494 @type bool
3468 """ 3495 """
3469 self.ensureVisible(line) 3496 self.ensureVisible(line)
3470 self.setFirstVisibleLine(line - 1) 3497 self.setFirstVisibleLine(line - 1)
3471 self.ensureCursorVisible() 3498 self.ensureCursorVisible()
3512 """ 3539 """
3513 Public method to get the word boundaries at a position. 3540 Public method to get the word boundaries at a position.
3514 3541
3515 @param line number of line to look at (int) 3542 @param line number of line to look at (int)
3516 @param index position to look at (int) 3543 @param index position to look at (int)
3517 @keyparam useWordChars flag indicating to use the wordCharacters 3544 @param useWordChars flag indicating to use the wordCharacters
3518 method (boolean) 3545 method (boolean)
3519 @return tuple with start and end indexes of the word at the position 3546 @return tuple with start and end indexes of the word at the position
3520 (integer, integer) 3547 (integer, integer)
3521 """ 3548 """
3522 wc = self.wordCharacters() 3549 wc = self.wordCharacters()
3544 3571
3545 @param line number of line to look at (int) 3572 @param line number of line to look at (int)
3546 @param index position to look at (int) 3573 @param index position to look at (int)
3547 @param direction direction to look in (0 = whole word, 1 = left, 3574 @param direction direction to look in (0 = whole word, 1 = left,
3548 2 = right) 3575 2 = right)
3549 @keyparam useWordChars flag indicating to use the wordCharacters 3576 @param useWordChars flag indicating to use the wordCharacters
3550 method (boolean) 3577 method (boolean)
3551 @return the word at that position (string) 3578 @return the word at that position (string)
3552 """ 3579 """
3553 start, end = self.getWordBoundaries(line, index, useWordChars) 3580 start, end = self.getWordBoundaries(line, index, useWordChars)
3554 if direction == 1: 3581 if direction == 1:
4196 """ 4223 """
4197 Public slot to jump to the beginning of a line. 4224 Public slot to jump to the beginning of a line.
4198 4225
4199 @param line line number to go to 4226 @param line line number to go to
4200 @type int 4227 @type int
4201 @keyparam pos position in line to go to 4228 @param pos position in line to go to
4202 @type int 4229 @type int
4203 @keyparam firstVisible flag indicating to make the line the first 4230 @param firstVisible flag indicating to make the line the first
4204 visible line 4231 visible line
4205 @type bool 4232 @type bool
4206 @keyparam expand flag indicating to expand all folds 4233 @param expand flag indicating to expand all folds
4207 @type bool 4234 @type bool
4208 """ 4235 """
4209 self.setCursorPosition(line - 1, pos - 1) 4236 self.setCursorPosition(line - 1, pos - 1)
4210 if firstVisible: 4237 if firstVisible:
4211 self.ensureVisibleTop(line, expand) 4238 self.ensureVisibleTop(line, expand)
4807 if ( 4834 if (
4808 char == "(" and 4835 char == "(" and
4809 Preferences.getDocuViewer("ShowInfoOnOpenParenthesis") 4836 Preferences.getDocuViewer("ShowInfoOnOpenParenthesis")
4810 ): 4837 ):
4811 self.vm.showEditorInfo(self) 4838 self.vm.showEditorInfo(self)
4812 4839
4840 self.__delayedDocstringMenuPopup(self.getCursorPosition())
4841
4813 if self.isListActive(): 4842 if self.isListActive():
4814 if self.__isStartChar(char): 4843 if self.__isStartChar(char):
4815 self.cancelList() 4844 self.cancelList()
4816 self.autoComplete(auto=True, context=True) 4845 self.autoComplete(auto=True, context=True)
4817 return 4846 return
4929 4958
4930 def autoComplete(self, auto=False, context=True): 4959 def autoComplete(self, auto=False, context=True):
4931 """ 4960 """
4932 Public method to start auto-completion. 4961 Public method to start auto-completion.
4933 4962
4934 @keyparam auto flag indicating a call from the __charAdded method 4963 @param auto flag indicating a call from the __charAdded method
4935 (boolean) 4964 (boolean)
4936 @keyparam context flag indicating to complete a context (boolean) 4965 @param context flag indicating to complete a context (boolean)
4937 """ 4966 """
4938 if auto and not Preferences.getEditor("AutoCompletionEnabled"): 4967 if auto and not Preferences.getEditor("AutoCompletionEnabled"):
4939 # auto-completion is disabled 4968 # auto-completion is disabled
4940 return 4969 return
4941 4970
4980 5009
4981 def __autoComplete(self, auto=True, context=None): 5010 def __autoComplete(self, auto=True, context=None):
4982 """ 5011 """
4983 Private method to start auto-completion via plug-ins. 5012 Private method to start auto-completion via plug-ins.
4984 5013
4985 @keyparam auto flag indicating a call from the __charAdded method 5014 @param auto flag indicating a call from the __charAdded method
4986 (boolean) 5015 (boolean)
4987 @keyparam context flag indicating to complete a context 5016 @param context flag indicating to complete a context
4988 @type bool or None 5017 @type bool or None
4989 """ 5018 """
4990 self.__acCompletions.clear() 5019 self.__acCompletions.clear()
4991 self.__acCompletionsFinished = 0 5020 self.__acCompletionsFinished = 0
4992 5021
5476 else: 5505 else:
5477 self.menuActs["NewSplit"].setIcon( 5506 self.menuActs["NewSplit"].setIcon(
5478 UI.PixmapCache.getIcon("splitVertical")) 5507 UI.PixmapCache.getIcon("splitVertical"))
5479 5508
5480 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty()) 5509 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty())
5510
5511 cline = self.getCursorPosition()[0]
5512 line = self.text(cline)
5513 self.menuActs["Docstring"].setEnabled(
5514 self.getDocstringGenerator().isFunctionStart(line))
5481 5515
5482 self.showMenu.emit("Main", self.menu, self) 5516 self.showMenu.emit("Main", self.menu, self)
5483 5517
5484 def __showContextMenuAutocompletion(self): 5518 def __showContextMenuAutocompletion(self):
5485 """ 5519 """
6200 @param line line number of the syntax error (integer) 6234 @param line line number of the syntax error (integer)
6201 @param index index number of the syntax error (integer) 6235 @param index index number of the syntax error (integer)
6202 @param error flag indicating if the error marker should be 6236 @param error flag indicating if the error marker should be
6203 set or deleted (boolean) 6237 set or deleted (boolean)
6204 @param msg error message (string) 6238 @param msg error message (string)
6205 @keyparam show flag indicating to set the cursor to the error position 6239 @param show flag indicating to set the cursor to the error position
6206 (boolean) 6240 (boolean)
6207 """ 6241 """
6208 if line == 0: 6242 if line == 0:
6209 line = 1 6243 line = 1
6210 # hack to show a syntax error marker, if line is reported to be 0 6244 # hack to show a syntax error marker, if line is reported to be 0
6358 @param line line number of the warning 6392 @param line line number of the warning
6359 @param col column of the warning 6393 @param col column of the warning
6360 @param warning flag indicating if the warning marker should be 6394 @param warning flag indicating if the warning marker should be
6361 set or deleted (boolean) 6395 set or deleted (boolean)
6362 @param msg warning message (string) 6396 @param msg warning message (string)
6363 @keyparam warningType type of warning message (integer) 6397 @param warningType type of warning message (integer)
6364 """ 6398 """
6365 if line == 0: 6399 if line == 0:
6366 line = 1 6400 line = 1
6367 # hack to show a warning marker, if line is reported to be 0 6401 # hack to show a warning marker, if line is reported to be 0
6368 if warning: 6402 if warning:
6933 6967
6934 def keyPressEvent(self, ev): 6968 def keyPressEvent(self, ev):
6935 """ 6969 """
6936 Protected method to handle the user input a key at a time. 6970 Protected method to handle the user input a key at a time.
6937 6971
6938 @param ev key event (QKeyEvent) 6972 @param ev key event
6939 """ 6973 @type QKeyEvent
6974 """
6975 def encloseSelectedText(encString):
6976 """
6977 Local function to enclose the current selection with some
6978 characters.
6979
6980 @param encString string to use to enclose the selection
6981 (one or two characters)
6982 @type str
6983 """
6984 startChar = encString[0]
6985 if len(encString) == 2:
6986 endChar = encString[1]
6987 else:
6988 endChar = startChar
6989
6990 sline, sindex, eline, eindex = self.getSelection()
6991 replaceText = startChar + self.selectedText() + endChar
6992 self.beginUndoAction()
6993 self.replaceSelectedText(replaceText)
6994 self.endUndoAction()
6995 self.setSelection(sline, sindex + 1, eline, eindex + 1)
6996
6940 txt = ev.text() 6997 txt = ev.text()
6941 6998
6942 # See it is text to insert. 6999 # See it is text to insert.
6943 if len(txt) and txt >= " ": 7000 if len(txt) and txt >= " ":
7001 if self.hasSelectedText():
7002 if txt in Editor.EncloseChars:
7003 encloseSelectedText(Editor.EncloseChars[txt])
7004 ev.accept()
7005 return
7006
6944 super(Editor, self).keyPressEvent(ev) 7007 super(Editor, self).keyPressEvent(ev)
6945 else: 7008 else:
6946 ev.ignore() 7009 ev.ignore()
6947 7010
6948 def focusInEvent(self, event): 7011 def focusInEvent(self, event):
6952 This method checks for modifications of the current file and 7015 This method checks for modifications of the current file and
6953 rereads it upon request. The cursor is placed at the current position 7016 rereads it upon request. The cursor is placed at the current position
6954 assuming, that it is in the vicinity of the old position after the 7017 assuming, that it is in the vicinity of the old position after the
6955 reread. 7018 reread.
6956 7019
6957 @param event the event object (QFocusEvent) 7020 @param event the event object
7021 @type QFocusEvent
6958 """ 7022 """
6959 self.recolor() 7023 self.recolor()
6960 self.vm.editActGrp.setEnabled(True) 7024 self.vm.editActGrp.setEnabled(True)
6961 self.vm.editorActGrp.setEnabled(True) 7025 self.vm.editorActGrp.setEnabled(True)
6962 self.vm.copyActGrp.setEnabled(True) 7026 self.vm.copyActGrp.setEnabled(True)
6977 if Preferences.getEditor("AutoReopen") and not self.isModified(): 7041 if Preferences.getEditor("AutoReopen") and not self.isModified():
6978 self.refresh() 7042 self.refresh()
6979 else: 7043 else:
6980 msg = self.tr( 7044 msg = self.tr(
6981 """<p>The file <b>{0}</b> has been changed while it""" 7045 """<p>The file <b>{0}</b> has been changed while it"""
6982 """ was opened in eric6. Reread it?</p>""" 7046 """ was opened in eric. Reread it?</p>"""
6983 ).format(self.fileName) 7047 ).format(self.fileName)
6984 yesDefault = True 7048 yesDefault = True
6985 if self.isModified(): 7049 if self.isModified():
6986 msg += self.tr( 7050 msg += self.tr(
6987 """<br><b>Warning:</b> You will lose""" 7051 """<br><b>Warning:</b> You will lose"""
7005 7069
7006 def focusOutEvent(self, event): 7070 def focusOutEvent(self, event):
7007 """ 7071 """
7008 Protected method called when the editor loses focus. 7072 Protected method called when the editor loses focus.
7009 7073
7010 @param event the event object (QFocusEvent) 7074 @param event the event object
7075 @type QFocusEvent
7011 """ 7076 """
7012 self.vm.editorActGrp.setEnabled(False) 7077 self.vm.editorActGrp.setEnabled(False)
7013 self.setCaretWidth(0) 7078 self.setCaretWidth(0)
7014 7079
7015 super(Editor, self).focusOutEvent(event) 7080 super(Editor, self).focusOutEvent(event)
7022 showMinimized and showNormal. The windows caption is shortened 7087 showMinimized and showNormal. The windows caption is shortened
7023 for the minimized mode and reset to the full filename for the 7088 for the minimized mode and reset to the full filename for the
7024 other modes. This is to make the editor windows work nicer 7089 other modes. This is to make the editor windows work nicer
7025 with the QWorkspace. 7090 with the QWorkspace.
7026 7091
7027 @param evt the event, that was generated (QEvent) 7092 @param evt the event, that was generated
7093 @type QEvent
7028 """ 7094 """
7029 if ( 7095 if (
7030 evt.type() == QEvent.WindowStateChange and 7096 evt.type() == QEvent.WindowStateChange and
7031 bool(self.fileName) 7097 bool(self.fileName)
7032 ): 7098 ):
7042 7108
7043 def mousePressEvent(self, event): 7109 def mousePressEvent(self, event):
7044 """ 7110 """
7045 Protected method to handle the mouse press event. 7111 Protected method to handle the mouse press event.
7046 7112
7047 @param event the mouse press event (QMouseEvent) 7113 @param event the mouse press event
7114 @type QMouseEvent
7048 """ 7115 """
7049 self.vm.eventFilter(self, event) 7116 self.vm.eventFilter(self, event)
7050 super(Editor, self).mousePressEvent(event) 7117 super(Editor, self).mousePressEvent(event)
7118
7119 def mouseDoubleClickEvent(self, evt):
7120 """
7121 Protected method to handle mouse double click events.
7122
7123 @param evt reference to the mouse event
7124 @type QMouseEvent
7125 """
7126 super(Editor, self).mouseDoubleClickEvent(evt)
7127
7128 self.mouseDoubleClick.emit(evt.pos(), evt.buttons())
7051 7129
7052 def wheelEvent(self, evt): 7130 def wheelEvent(self, evt):
7053 """ 7131 """
7054 Protected method to handle wheel events. 7132 Protected method to handle wheel events.
7055 7133
7056 @param evt reference to the wheel event (QWheelEvent) 7134 @param evt reference to the wheel event
7135 @type QWheelEvent
7057 """ 7136 """
7058 delta = evt.angleDelta().y() 7137 delta = evt.angleDelta().y()
7059 if evt.modifiers() & Qt.ControlModifier: 7138 if evt.modifiers() & Qt.ControlModifier:
7060 if delta < 0: 7139 if delta < 0:
7061 self.zoomOut() 7140 self.zoomOut()
7076 7155
7077 def event(self, evt): 7156 def event(self, evt):
7078 """ 7157 """
7079 Public method handling events. 7158 Public method handling events.
7080 7159
7081 @param evt reference to the event (QEvent) 7160 @param evt reference to the event
7082 @return flag indicating, if the event was handled (boolean) 7161 @type QEvent
7162 @return flag indicating, if the event was handled
7163 @rtype bool
7083 """ 7164 """
7084 if evt.type() == QEvent.Gesture: 7165 if evt.type() == QEvent.Gesture:
7085 self.gestureEvent(evt) 7166 self.gestureEvent(evt)
7086 return True 7167 return True
7087 7168
7089 7170
7090 def gestureEvent(self, evt): 7171 def gestureEvent(self, evt):
7091 """ 7172 """
7092 Protected method handling gesture events. 7173 Protected method handling gesture events.
7093 7174
7094 @param evt reference to the gesture event (QGestureEvent 7175 @param evt reference to the gesture event
7176 @type QGestureEvent
7095 """ 7177 """
7096 pinch = evt.gesture(Qt.PinchGesture) 7178 pinch = evt.gesture(Qt.PinchGesture)
7097 if pinch: 7179 if pinch:
7098 if pinch.state() == Qt.GestureStarted: 7180 if pinch.state() == Qt.GestureStarted:
7099 zoom = (self.getZoom() + 10) / 10.0 7181 zoom = (self.getZoom() + 10) / 10.0
7111 7193
7112 def resizeEvent(self, evt): 7194 def resizeEvent(self, evt):
7113 """ 7195 """
7114 Protected method handling resize events. 7196 Protected method handling resize events.
7115 7197
7116 @param evt reference to the resize event (QResizeEvent) 7198 @param evt reference to the resize event
7199 @type QResizeEvent
7117 """ 7200 """
7118 super(Editor, self).resizeEvent(evt) 7201 super(Editor, self).resizeEvent(evt)
7119 self.__markerMap.calculateGeometry() 7202 self.__markerMap.calculateGeometry()
7120 7203
7121 def viewportEvent(self, evt): 7204 def viewportEvent(self, evt):
7122 """ 7205 """
7123 Protected method handling event of the viewport. 7206 Protected method handling event of the viewport.
7124 7207
7125 @param evt reference to the event (QEvent) 7208 @param evt reference to the event
7126 @return flag indiating that the event was handled (boolean) 7209 @type QEvent
7210 @return flag indiating that the event was handled
7211 @rtype bool
7127 """ 7212 """
7128 try: 7213 try:
7129 self.__markerMap.calculateGeometry() 7214 self.__markerMap.calculateGeometry()
7130 except AttributeError: 7215 except AttributeError:
7131 # ignore this - there seems to be a runtime issue when the editor 7216 # ignore this - there seems to be a runtime issue when the editor
7664 def __setSpellingLanguage(self, language, pwl="", pel=""): 7749 def __setSpellingLanguage(self, language, pwl="", pel=""):
7665 """ 7750 """
7666 Private slot to set the spell checking language. 7751 Private slot to set the spell checking language.
7667 7752
7668 @param language spell checking language to be set (string) 7753 @param language spell checking language to be set (string)
7669 @keyparam pwl name of the personal/project word list (string) 7754 @param pwl name of the personal/project word list (string)
7670 @keyparam pel name of the personal/project exclude list (string) 7755 @param pel name of the personal/project exclude list (string)
7671 """ 7756 """
7672 if self.spell and self.spell.getLanguage() != language: 7757 if self.spell and self.spell.getLanguage() != language:
7673 self.spell.setLanguage(language, pwl=pwl, pel=pel) 7758 self.spell.setLanguage(language, pwl=pwl, pel=pel)
7674 self.spell.checkDocumentIncrementally() 7759 self.spell.checkDocumentIncrementally()
7675 7760
7960 8045
7961 def cancelSharedEdit(self, send=True): 8046 def cancelSharedEdit(self, send=True):
7962 """ 8047 """
7963 Public slot to cancel a shared edit session for the editor. 8048 Public slot to cancel a shared edit session for the editor.
7964 8049
7965 @keyparam send flag indicating to send the CancelEdit command (boolean) 8050 @param send flag indicating to send the CancelEdit command (boolean)
7966 """ 8051 """
7967 self.__inSharedEdit = False 8052 self.__inSharedEdit = False
7968 self.__savedText = "" 8053 self.__savedText = ""
7969 if send: 8054 if send:
7970 self.__send(Editor.CancelEditToken) 8055 self.__send(Editor.CancelEditToken)
8566 elif option == "IndentWidth": 8651 elif option == "IndentWidth":
8567 return overrides[language][1] 8652 return overrides[language][1]
8568 8653
8569 return None 8654 return None
8570 8655
8571 def mouseDoubleClickEvent(self, evt): 8656 #######################################################################
8572 """ 8657 ## Methods implementing the docstring generator interface
8573 Protected method to handle mouse double click events. 8658 #######################################################################
8574 8659
8575 @param evt reference to the mouse event 8660 def getDocstringGenerator(self):
8576 @type QMouseEvent 8661 """
8577 """ 8662 Public method to get a reference to the docstring generator.
8578 super(Editor, self).mouseDoubleClickEvent(evt) 8663
8579 8664 @return reference to the docstring generator
8580 self.mouseDoubleClick.emit(evt.pos(), evt.buttons()) 8665 @rtype BaseDocstringGenerator
8666 """
8667 if self.__docstringGenerator is None:
8668 from . import DocstringGenerator
8669 self.__docstringGenerator = (
8670 DocstringGenerator.getDocstringGenerator(self)
8671 )
8672
8673 return self.__docstringGenerator
8674
8675 def insertDocstring(self):
8676 """
8677 Public method to generate and insert a docstring for the function under
8678 the cursor.
8679
8680 Note: This method is called via a keyboard shortcut or through the
8681 global 'Edit' menu.
8682 """
8683 generator = self.getDocstringGenerator()
8684 generator.insertDocstringFromShortcut(self.getCursorPosition())
8685
8686 @pyqtSlot()
8687 def __insertDocstring(self):
8688 """
8689 Private slot to generate and insert a docstring for the function under
8690 the cursor.
8691 """
8692 generator = self.getDocstringGenerator()
8693 generator.insertDocstring(self.getCursorPosition(), fromStart=True)
8694
8695 def __delayedDocstringMenuPopup(self, cursorPosition):
8696 """
8697 Private method to test, if the user might want to insert a docstring.
8698
8699 @param cursorPosition current cursor position (line and column)
8700 @type tuple of (int, int)
8701 """
8702 if (
8703 Preferences.getEditor("DocstringAutoGenerate") and
8704 self.getDocstringGenerator().isDocstringIntro(cursorPosition)
8705 ):
8706 lineText2Cursor = self.text(cursorPosition[0])[:cursorPosition[1]]
8707
8708 QTimer.singleShot(
8709 300,
8710 lambda: self.__popupDocstringMenu(lineText2Cursor,
8711 cursorPosition)
8712 )
8713
8714 def __popupDocstringMenu(self, lastLineText, lastCursorPosition):
8715 """
8716 Private slot to pop up a menu asking the user, if a docstring should be
8717 inserted.
8718
8719 @param lastLineText line contents when the delay timer was started
8720 @type str
8721 @param lastCursorPosition position of the cursor when the delay timer
8722 was started (line and index)
8723 @type tuple of (int, int)
8724 """
8725 cursorPosition = self.getCursorPosition()
8726 if lastCursorPosition != cursorPosition:
8727 return
8728
8729 if self.text(cursorPosition[0])[:cursorPosition[1]] != lastLineText:
8730 return
8731
8732 generator = self.getDocstringGenerator()
8733 if generator.hasFunctionDefinition(cursorPosition):
8734 from .DocstringGenerator.BaseDocstringGenerator import (
8735 DocstringMenuForEnterOnly
8736 )
8737 docstringMenu = DocstringMenuForEnterOnly(self)
8738 act = docstringMenu.addAction(
8739 UI.PixmapCache.getIcon("fileText"),
8740 self.tr("Generate Docstring"),
8741 lambda: generator.insertDocstring(cursorPosition,
8742 fromStart=False)
8743 )
8744 docstringMenu.setActiveAction(act)
8745 docstringMenu.popup(
8746 self.mapToGlobal(self.getGlobalCursorPosition()))

eric ide

mercurial