eric6/QScintilla/Editor.py

branch
maintenance
changeset 7286
7eb04391adf7
parent 7214
f434af227a41
parent 7278
1820a0344b62
child 7322
cd8ee889589f
equal deleted inserted replaced
7226:babe80d84a3e 7286:7eb04391adf7
4 # 4 #
5 5
6 """ 6 """
7 Module implementing the editor component of the eric6 IDE. 7 Module implementing the editor component of the eric6 IDE.
8 """ 8 """
9 from __future__ import unicode_literals 9
10 try:
11 str = unicode
12 chr = unichr
13 except NameError:
14 pass
15 10
16 import os 11 import os
17 import re 12 import re
18 import difflib 13 import difflib
19 14
20 from PyQt5.QtCore import QDir, QTimer, QModelIndex, QFileInfo, pyqtSignal, \ 15 from PyQt5.QtCore import (
21 pyqtSlot, QCryptographicHash, QEvent, QDateTime, QRegExp, Qt, QPoint 16 QDir, QTimer, QModelIndex, QFileInfo, pyqtSignal, pyqtSlot,
17 QCryptographicHash, QEvent, QDateTime, QRegExp, Qt, QPoint
18 )
22 from PyQt5.QtGui import QCursor, QPalette, QFont, QPixmap, QPainter 19 from PyQt5.QtGui import QCursor, QPalette, QFont, QPixmap, QPainter
23 from PyQt5.QtWidgets import QLineEdit, QActionGroup, QDialog, QInputDialog, \ 20 from PyQt5.QtWidgets import (
24 QApplication, QMenu 21 QLineEdit, QActionGroup, QDialog, QInputDialog, QApplication, QMenu
22 )
25 from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QAbstractPrintDialog 23 from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QAbstractPrintDialog
26 from PyQt5.Qsci import QsciScintilla, QsciMacro, QsciStyledText 24 from PyQt5.Qsci import QsciScintilla, QsciMacro, QsciStyledText
27 25
28 from E5Gui.E5Application import e5App 26 from E5Gui.E5Application import e5App
29 from E5Gui import E5FileDialog, E5MessageBox 27 from E5Gui import E5FileDialog, E5MessageBox
33 from .EditorMarkerMap import EditorMarkerMap 31 from .EditorMarkerMap import EditorMarkerMap
34 32
35 import Preferences 33 import Preferences
36 import Utilities 34 import Utilities
37 from Utilities import MouseUtilities 35 from Utilities import MouseUtilities
38 from Globals import qVersionTuple
39 36
40 import UI.PixmapCache 37 import UI.PixmapCache
41 38
42 from ThirdParty.EditorConfig import editorconfig 39 from ThirdParty.EditorConfig import editorconfig
43 40
313 self.currentline = self.markerDefine( 310 self.currentline = self.markerDefine(
314 UI.PixmapCache.getPixmap("currentLineMarker.png")) 311 UI.PixmapCache.getPixmap("currentLineMarker.png"))
315 self.errorline = self.markerDefine( 312 self.errorline = self.markerDefine(
316 UI.PixmapCache.getPixmap("errorLineMarker.png")) 313 UI.PixmapCache.getPixmap("errorLineMarker.png"))
317 314
318 self.breakpointMask = (1 << self.breakpoint) | \ 315 self.breakpointMask = (
319 (1 << self.cbreakpoint) | \ 316 (1 << self.breakpoint) |
320 (1 << self.tbreakpoint) | \ 317 (1 << self.cbreakpoint) |
321 (1 << self.tcbreakpoint) | \ 318 (1 << self.tbreakpoint) |
322 (1 << self.dbreakpoint) 319 (1 << self.tcbreakpoint) |
323 320 (1 << self.dbreakpoint)
324 self.changeMarkersMask = (1 << self.__changeMarkerSaved) | \ 321 )
325 (1 << self.__changeMarkerUnsaved) 322
323 self.changeMarkersMask = (
324 (1 << self.__changeMarkerSaved) |
325 (1 << self.__changeMarkerUnsaved)
326 )
326 327
327 self.__markerMap = EditorMarkerMap(self) 328 self.__markerMap = EditorMarkerMap(self)
328 329
329 # configure the margins 330 # configure the margins
330 self.__setMarginsDisplay() 331 self.__setMarginsDisplay()
350 self.syntaxCheckService = None 351 self.syntaxCheckService = None
351 352
352 self.isResourcesFile = False 353 self.isResourcesFile = False
353 if editor is None: 354 if editor is None:
354 if self.fileName: 355 if self.fileName:
355 if (QFileInfo(self.fileName).size() // 1024) > \ 356 if (
356 Preferences.getEditor("WarnFilesize"): 357 (QFileInfo(self.fileName).size() // 1024) >
358 Preferences.getEditor("WarnFilesize")
359 ):
357 res = E5MessageBox.yesNo( 360 res = E5MessageBox.yesNo(
358 self, 361 self,
359 self.tr("Open File"), 362 self.tr("Open File"),
360 self.tr("""<p>The size of the file <b>{0}</b>""" 363 self.tr("""<p>The size of the file <b>{0}</b>"""
361 """ is <b>{1} KB</b>.""" 364 """ is <b>{1} KB</b>."""
369 self.__bindLexer(self.fileName) 372 self.__bindLexer(self.fileName)
370 self.__bindCompleter(self.fileName) 373 self.__bindCompleter(self.fileName)
371 self.checkSyntax() 374 self.checkSyntax()
372 self.isResourcesFile = self.fileName.endswith(".qrc") 375 self.isResourcesFile = self.fileName.endswith(".qrc")
373 376
377 self.__convertTabs()
378
374 self.recolor() 379 self.recolor()
375 else: 380 else:
376 # clone the given editor 381 # clone the given editor
377 self.setDocument(editor.document()) 382 self.setDocument(editor.document())
378 self.breaks = editor.breaks 383 self.breaks = editor.breaks
508 self.textChanged.connect(self.__textChanged) 513 self.textChanged.connect(self.__textChanged)
509 514
510 # initialize the online change trace timer 515 # initialize the online change trace timer
511 self.__initOnlineChangeTrace() 516 self.__initOnlineChangeTrace()
512 517
513 if self.fileName and \ 518 if (
514 self.project.isOpen() and \ 519 self.fileName and
515 self.project.isProjectSource(self.fileName): 520 self.project.isOpen() and
521 self.project.isProjectSource(self.fileName)
522 ):
516 self.project.projectPropertiesChanged.connect( 523 self.project.projectPropertiesChanged.connect(
517 self.__projectPropertiesChanged) 524 self.__projectPropertiesChanged)
518 525
519 self.grabGesture(Qt.PinchGesture) 526 self.grabGesture(Qt.PinchGesture)
520 527
1015 self.supportedLanguages = {} 1022 self.supportedLanguages = {}
1016 supportedLanguages = Lexers.getSupportedLanguages() 1023 supportedLanguages = Lexers.getSupportedLanguages()
1017 languages = sorted(list(supportedLanguages.keys())) 1024 languages = sorted(list(supportedLanguages.keys()))
1018 for language in languages: 1025 for language in languages:
1019 if language != "Guessed": 1026 if language != "Guessed":
1020 self.supportedLanguages[language] = \ 1027 self.supportedLanguages[language] = (
1021 supportedLanguages[language][:2] 1028 supportedLanguages[language][:2]
1029 )
1022 act = menu.addAction( 1030 act = menu.addAction(
1023 UI.PixmapCache.getIcon(supportedLanguages[language][2]), 1031 UI.PixmapCache.getIcon(supportedLanguages[language][2]),
1024 self.supportedLanguages[language][0]) 1032 self.supportedLanguages[language][0])
1025 act.setCheckable(True) 1033 act.setCheckable(True)
1026 act.setData(language) 1034 act.setData(language)
1172 self.marginMenuActs["EnableBreakpoint"] = self.bpMarginMenu.addAction( 1180 self.marginMenuActs["EnableBreakpoint"] = self.bpMarginMenu.addAction(
1173 self.tr('Enable breakpoint'), 1181 self.tr('Enable breakpoint'),
1174 self.__menuToggleBreakpointEnabled) 1182 self.__menuToggleBreakpointEnabled)
1175 self.marginMenuActs["NextBreakpoint"] = self.bpMarginMenu.addAction( 1183 self.marginMenuActs["NextBreakpoint"] = self.bpMarginMenu.addAction(
1176 self.tr('Next breakpoint'), self.menuNextBreakpoint) 1184 self.tr('Next breakpoint'), self.menuNextBreakpoint)
1177 self.marginMenuActs["PreviousBreakpoint"] = \ 1185 self.marginMenuActs["PreviousBreakpoint"] = (
1178 self.bpMarginMenu.addAction( 1186 self.bpMarginMenu.addAction(
1179 self.tr('Previous breakpoint'), 1187 self.tr('Previous breakpoint'),
1180 self.menuPreviousBreakpoint) 1188 self.menuPreviousBreakpoint)
1189 )
1181 self.marginMenuActs["ClearBreakpoint"] = self.bpMarginMenu.addAction( 1190 self.marginMenuActs["ClearBreakpoint"] = self.bpMarginMenu.addAction(
1182 self.tr('Clear all breakpoints'), self.__menuClearBreakpoints) 1191 self.tr('Clear all breakpoints'), self.__menuClearBreakpoints)
1183 1192
1184 self.bpMarginMenu.aboutToShow.connect( 1193 self.bpMarginMenu.aboutToShow.connect(
1185 lambda: self.__showContextMenuMargin(self.bpMarginMenu)) 1194 lambda: self.__showContextMenuMargin(self.bpMarginMenu))
1186 1195
1187 # fold margin 1196 # fold margin
1188 self.foldMarginMenu = QMenu() 1197 self.foldMarginMenu = QMenu()
1189 1198
1190 self.marginMenuActs["ToggleAllFolds"] = \ 1199 self.marginMenuActs["ToggleAllFolds"] = (
1191 self.foldMarginMenu.addAction( 1200 self.foldMarginMenu.addAction(
1192 self.tr("Toggle all folds"), 1201 self.tr("Toggle all folds"),
1193 self.foldAll) 1202 self.foldAll)
1194 self.marginMenuActs["ToggleAllFoldsAndChildren"] = \ 1203 )
1204 self.marginMenuActs["ToggleAllFoldsAndChildren"] = (
1195 self.foldMarginMenu.addAction( 1205 self.foldMarginMenu.addAction(
1196 self.tr("Toggle all folds (including children)"), 1206 self.tr("Toggle all folds (including children)"),
1197 lambda: self.foldAll(True)) 1207 lambda: self.foldAll(True))
1198 self.marginMenuActs["ToggleCurrentFold"] = \ 1208 )
1209 self.marginMenuActs["ToggleCurrentFold"] = (
1199 self.foldMarginMenu.addAction( 1210 self.foldMarginMenu.addAction(
1200 self.tr("Toggle current fold"), 1211 self.tr("Toggle current fold"),
1201 self.toggleCurrentFold) 1212 self.toggleCurrentFold)
1213 )
1202 self.foldMarginMenu.addSeparator() 1214 self.foldMarginMenu.addSeparator()
1203 self.marginMenuActs["ExpandChildren"] = \ 1215 self.marginMenuActs["ExpandChildren"] = (
1204 self.foldMarginMenu.addAction( 1216 self.foldMarginMenu.addAction(
1205 self.tr("Expand (including children)"), 1217 self.tr("Expand (including children)"),
1206 self.__contextMenuExpandFoldWithChildren) 1218 self.__contextMenuExpandFoldWithChildren)
1207 self.marginMenuActs["CollapseChildren"] = \ 1219 )
1220 self.marginMenuActs["CollapseChildren"] = (
1208 self.foldMarginMenu.addAction( 1221 self.foldMarginMenu.addAction(
1209 self.tr("Collapse (including children)"), 1222 self.tr("Collapse (including children)"),
1210 self.__contextMenuCollapseFoldWithChildren) 1223 self.__contextMenuCollapseFoldWithChildren)
1224 )
1211 self.foldMarginMenu.addSeparator() 1225 self.foldMarginMenu.addSeparator()
1212 self.marginMenuActs["ClearAllFolds"] = \ 1226 self.marginMenuActs["ClearAllFolds"] = (
1213 self.foldMarginMenu.addAction( 1227 self.foldMarginMenu.addAction(
1214 self.tr("Clear all folds"), 1228 self.tr("Clear all folds"),
1215 self.clearFolds) 1229 self.clearFolds)
1230 )
1216 1231
1217 self.foldMarginMenu.aboutToShow.connect( 1232 self.foldMarginMenu.aboutToShow.connect(
1218 lambda: self.__showContextMenuMargin(self.foldMarginMenu)) 1233 lambda: self.__showContextMenuMargin(self.foldMarginMenu))
1219 1234
1220 # indicator margin 1235 # indicator margin
1221 self.indicMarginMenu = QMenu() 1236 self.indicMarginMenu = QMenu()
1222 1237
1223 self.marginMenuActs["GotoSyntaxError"] = \ 1238 self.marginMenuActs["GotoSyntaxError"] = (
1224 self.indicMarginMenu.addAction( 1239 self.indicMarginMenu.addAction(
1225 self.tr('Goto syntax error'), self.gotoSyntaxError) 1240 self.tr('Goto syntax error'), self.gotoSyntaxError)
1226 self.marginMenuActs["ShowSyntaxError"] = \ 1241 )
1242 self.marginMenuActs["ShowSyntaxError"] = (
1227 self.indicMarginMenu.addAction( 1243 self.indicMarginMenu.addAction(
1228 self.tr('Show syntax error message'), 1244 self.tr('Show syntax error message'),
1229 self.__showSyntaxError) 1245 self.__showSyntaxError)
1230 self.marginMenuActs["ClearSyntaxError"] = \ 1246 )
1247 self.marginMenuActs["ClearSyntaxError"] = (
1231 self.indicMarginMenu.addAction( 1248 self.indicMarginMenu.addAction(
1232 self.tr('Clear syntax error'), self.clearSyntaxError) 1249 self.tr('Clear syntax error'), self.clearSyntaxError)
1250 )
1233 self.indicMarginMenu.addSeparator() 1251 self.indicMarginMenu.addSeparator()
1234 self.marginMenuActs["NextWarningMarker"] = \ 1252 self.marginMenuActs["NextWarningMarker"] = (
1235 self.indicMarginMenu.addAction( 1253 self.indicMarginMenu.addAction(
1236 self.tr("Next warning"), self.nextWarning) 1254 self.tr("Next warning"), self.nextWarning)
1237 self.marginMenuActs["PreviousWarningMarker"] = \ 1255 )
1256 self.marginMenuActs["PreviousWarningMarker"] = (
1238 self.indicMarginMenu.addAction( 1257 self.indicMarginMenu.addAction(
1239 self.tr("Previous warning"), self.previousWarning) 1258 self.tr("Previous warning"), self.previousWarning)
1240 self.marginMenuActs["ShowWarning"] = \ 1259 )
1260 self.marginMenuActs["ShowWarning"] = (
1241 self.indicMarginMenu.addAction( 1261 self.indicMarginMenu.addAction(
1242 self.tr('Show warning message'), self.__showWarning) 1262 self.tr('Show warning message'), self.__showWarning)
1243 self.marginMenuActs["ClearWarnings"] = \ 1263 )
1264 self.marginMenuActs["ClearWarnings"] = (
1244 self.indicMarginMenu.addAction( 1265 self.indicMarginMenu.addAction(
1245 self.tr('Clear warnings'), self.clearWarnings) 1266 self.tr('Clear warnings'), self.clearWarnings)
1267 )
1246 self.indicMarginMenu.addSeparator() 1268 self.indicMarginMenu.addSeparator()
1247 self.marginMenuActs["NextCoverageMarker"] = \ 1269 self.marginMenuActs["NextCoverageMarker"] = (
1248 self.indicMarginMenu.addAction( 1270 self.indicMarginMenu.addAction(
1249 self.tr('Next uncovered line'), self.nextUncovered) 1271 self.tr('Next uncovered line'), self.nextUncovered)
1250 self.marginMenuActs["PreviousCoverageMarker"] = \ 1272 )
1273 self.marginMenuActs["PreviousCoverageMarker"] = (
1251 self.indicMarginMenu.addAction( 1274 self.indicMarginMenu.addAction(
1252 self.tr('Previous uncovered line'), self.previousUncovered) 1275 self.tr('Previous uncovered line'), self.previousUncovered)
1276 )
1253 self.indicMarginMenu.addSeparator() 1277 self.indicMarginMenu.addSeparator()
1254 self.marginMenuActs["NextTaskMarker"] = \ 1278 self.marginMenuActs["NextTaskMarker"] = (
1255 self.indicMarginMenu.addAction( 1279 self.indicMarginMenu.addAction(
1256 self.tr('Next task'), self.nextTask) 1280 self.tr('Next task'), self.nextTask)
1257 self.marginMenuActs["PreviousTaskMarker"] = \ 1281 )
1282 self.marginMenuActs["PreviousTaskMarker"] = (
1258 self.indicMarginMenu.addAction( 1283 self.indicMarginMenu.addAction(
1259 self.tr('Previous task'), self.previousTask) 1284 self.tr('Previous task'), self.previousTask)
1285 )
1260 self.indicMarginMenu.addSeparator() 1286 self.indicMarginMenu.addSeparator()
1261 self.marginMenuActs["NextChangeMarker"] = \ 1287 self.marginMenuActs["NextChangeMarker"] = (
1262 self.indicMarginMenu.addAction( 1288 self.indicMarginMenu.addAction(
1263 self.tr('Next change'), self.nextChange) 1289 self.tr('Next change'), self.nextChange)
1264 self.marginMenuActs["PreviousChangeMarker"] = \ 1290 )
1291 self.marginMenuActs["PreviousChangeMarker"] = (
1265 self.indicMarginMenu.addAction( 1292 self.indicMarginMenu.addAction(
1266 self.tr('Previous change'), self.previousChange) 1293 self.tr('Previous change'), self.previousChange)
1267 self.marginMenuActs["ClearChangeMarkers"] = \ 1294 )
1295 self.marginMenuActs["ClearChangeMarkers"] = (
1268 self.indicMarginMenu.addAction( 1296 self.indicMarginMenu.addAction(
1269 self.tr('Clear changes'), self.__reinitOnlineChangeTrace) 1297 self.tr('Clear changes'), self.__reinitOnlineChangeTrace)
1298 )
1270 1299
1271 self.indicMarginMenu.aboutToShow.connect( 1300 self.indicMarginMenu.aboutToShow.connect(
1272 lambda: self.__showContextMenuMargin(self.indicMarginMenu)) 1301 lambda: self.__showContextMenuMargin(self.indicMarginMenu))
1273 1302
1274 def __exportMenuTriggered(self, act): 1303 def __exportMenuTriggered(self, act):
1390 """ 1419 """
1391 Private method used to reset the language selection. 1420 Private method used to reset the language selection.
1392 1421
1393 @keyparam propagate flag indicating to propagate the change (boolean) 1422 @keyparam propagate flag indicating to propagate the change (boolean)
1394 """ 1423 """
1395 if self.lexer_ is not None and \ 1424 if (
1396 (self.lexer_.lexer() == "container" or self.lexer_.lexer() is None): 1425 self.lexer_ is not None and
1426 (self.lexer_.lexer() == "container" or
1427 self.lexer_.lexer() is None)
1428 ):
1397 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded) 1429 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded)
1398 1430
1399 self.apiLanguage = "" 1431 self.apiLanguage = ""
1400 self.lexer_ = None 1432 self.lexer_ = None
1401 self.__lexerReset = True 1433 self.__lexerReset = True
1491 def __checkEncoding(self): 1523 def __checkEncoding(self):
1492 """ 1524 """
1493 Private method to check the selected encoding of the encodings submenu. 1525 Private method to check the selected encoding of the encodings submenu.
1494 """ 1526 """
1495 try: 1527 try:
1496 self.supportedEncodings[self.__normalizedEncoding()]\ 1528 (self.supportedEncodings[self.__normalizedEncoding()]
1497 .setChecked(True) 1529 .setChecked(True))
1498 except (AttributeError, KeyError): 1530 except (AttributeError, KeyError):
1499 pass 1531 pass
1500 1532
1501 def __encodingChanged(self, encoding, propagate=True): 1533 def __encodingChanged(self, encoding, propagate=True):
1502 """ 1534 """
1520 @param encoding encoding to be normalized (string) 1552 @param encoding encoding to be normalized (string)
1521 @return normalized encoding (string) 1553 @return normalized encoding (string)
1522 """ 1554 """
1523 if not encoding: 1555 if not encoding:
1524 encoding = self.encoding 1556 encoding = self.encoding
1525 return encoding.replace("-default", "")\ 1557 return (
1526 .replace("-guessed", "")\ 1558 encoding
1527 .replace("-selected", "") 1559 .replace("-default", "")
1560 .replace("-guessed", "")
1561 .replace("-selected", "")
1562 )
1528 1563
1529 def __showContextMenuEol(self): 1564 def __showContextMenuEol(self):
1530 """ 1565 """
1531 Private slot handling the aboutToShow signal of the eol context menu. 1566 Private slot handling the aboutToShow signal of the eol context menu.
1532 """ 1567 """
1569 1604
1570 @param filename filename used to determine the associated lexer 1605 @param filename filename used to determine the associated lexer
1571 language (string) 1606 language (string)
1572 @keyparam pyname name of the pygments lexer to use (string) 1607 @keyparam pyname name of the pygments lexer to use (string)
1573 """ 1608 """
1574 if self.lexer_ is not None and \ 1609 if (
1575 (self.lexer_.lexer() == "container" or self.lexer_.lexer() is None): 1610 self.lexer_ is not None and
1611 (self.lexer_.lexer() == "container" or
1612 self.lexer_.lexer() is None)
1613 ):
1576 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded) 1614 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded)
1577 1615
1578 language = "" 1616 language = ""
1579 if not self.filetype: 1617 if not self.filetype:
1580 if filename: 1618 if filename:
1581 basename = os.path.basename(filename) 1619 basename = os.path.basename(filename)
1582 if self.project.isOpen() and \ 1620 if (
1583 self.project.isProjectFile(filename): 1621 self.project.isOpen() and
1622 self.project.isProjectFile(filename)
1623 ):
1584 language = self.project.getEditorLexerAssoc(basename) 1624 language = self.project.getEditorLexerAssoc(basename)
1585 if not language: 1625 if not language:
1586 language = Preferences.getEditorLexerAssoc(basename) 1626 language = Preferences.getEditorLexerAssoc(basename)
1587 if not language: 1627 if not language:
1588 bindName = self.__bindName(self.text(0)) 1628 bindName = self.__bindName(self.text(0))
1686 lexer names (boolean) 1726 lexer names (boolean)
1687 @keyparam forPygments flag indicating to normalize some lexer 1727 @keyparam forPygments flag indicating to normalize some lexer
1688 names for Pygments (boolean) 1728 names for Pygments (boolean)
1689 @return language of the editor (string) 1729 @return language of the editor (string)
1690 """ 1730 """
1691 if self.apiLanguage == "Guessed" or \ 1731 if (
1692 self.apiLanguage.startswith("Pygments|"): 1732 self.apiLanguage == "Guessed" or
1733 self.apiLanguage.startswith("Pygments|")
1734 ):
1693 lang = self.lexer_.name() 1735 lang = self.lexer_.name()
1694 if normalized: 1736 if normalized:
1695 # adjust some Pygments lexer names 1737 # adjust some Pygments lexer names
1696 if lang == "Python": 1738 if lang == "Python":
1697 lang = "Python2" 1739 lang = "Python2"
1935 if self.filetype == "Ruby": 1977 if self.filetype == "Ruby":
1936 return True 1978 return True
1937 1979
1938 if self.filetype == "": 1980 if self.filetype == "":
1939 line0 = self.text(0) 1981 line0 = self.text(0)
1940 if line0.startswith("#!") and \ 1982 if (
1941 "ruby" in line0: 1983 line0.startswith("#!") and
1984 "ruby" in line0
1985 ):
1942 self.filetype = "Ruby" 1986 self.filetype = "Ruby"
1943 return True 1987 return True
1944 1988
1945 if bool(self.fileName) and \ 1989 if (
1946 os.path.splitext(self.fileName)[1] in \ 1990 bool(self.fileName) and
1947 self.dbs.getExtensions('Ruby'): 1991 os.path.splitext(self.fileName)[1] in
1992 self.dbs.getExtensions('Ruby')
1993 ):
1948 self.filetype = "Ruby" 1994 self.filetype = "Ruby"
1949 return True 1995 return True
1950 1996
1951 return False 1997 return False
1952 1998
1958 """ 2004 """
1959 if self.filetype == "JavaScript": 2005 if self.filetype == "JavaScript":
1960 return True 2006 return True
1961 2007
1962 if self.filetype == "": 2008 if self.filetype == "":
1963 if self.fileName and \ 2009 if (
1964 os.path.splitext(self.fileName)[1] == ".js": 2010 self.fileName and
2011 os.path.splitext(self.fileName)[1] == ".js"
2012 ):
1965 self.filetype = "JavaScript" 2013 self.filetype = "JavaScript"
1966 return True 2014 return True
1967 2015
1968 return False 2016 return False
1969 2017
2036 @param foldPrev previous fold level (integer) 2084 @param foldPrev previous fold level (integer)
2037 @param token ??? 2085 @param token ???
2038 @param annotationLinesAdded number of added/deleted annotation lines 2086 @param annotationLinesAdded number of added/deleted annotation lines
2039 (integer) 2087 (integer)
2040 """ 2088 """
2041 if mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) and \ 2089 if (
2042 linesAdded != 0: 2090 mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) and
2091 linesAdded != 0
2092 ):
2043 if self.breaks: 2093 if self.breaks:
2044 bps = [] # list of breakpoints 2094 bps = [] # list of breakpoints
2045 for handle, (ln, cond, temp, enabled, ignorecount) in \ 2095 for handle, (ln, cond, temp, enabled, ignorecount) in (
2046 self.breaks.items(): 2096 self.breaks.items()
2097 ):
2047 line = self.markerLine(handle) + 1 2098 line = self.markerLine(handle) + 1
2048 if ln != line: 2099 if ln != line:
2049 bps.append((ln, line)) 2100 bps.append((ln, line))
2050 self.breaks[handle] = (line, cond, temp, enabled, 2101 self.breaks[handle] = (line, cond, temp, enabled,
2051 ignorecount) 2102 ignorecount)
2113 @param start start row (integer) 2164 @param start start row (integer)
2114 @param end end row (integer) 2165 @param end end row (integer)
2115 """ 2166 """
2116 for row in range(start, end + 1): 2167 for row in range(start, end + 1):
2117 index = self.breakpointModel.index(row, 0, parentIndex) 2168 index = self.breakpointModel.index(row, 0, parentIndex)
2118 fn, line, cond, temp, enabled, ignorecount = \ 2169 fn, line, cond, temp, enabled, ignorecount = (
2119 self.breakpointModel.getBreakPointByIndex(index)[:6] 2170 self.breakpointModel.getBreakPointByIndex(index)[:6]
2171 )
2120 if fn == self.fileName: 2172 if fn == self.fileName:
2121 self.newBreakpointWithProperties( 2173 self.newBreakpointWithProperties(
2122 line, (cond, temp, enabled, ignorecount)) 2174 line, (cond, temp, enabled, ignorecount))
2123 2175
2124 def clearBreakpoint(self, line): 2176 def clearBreakpoint(self, line):
2175 for handle in self.breaks: 2227 for handle in self.breaks:
2176 if self.markerLine(handle) == line - 1: 2228 if self.markerLine(handle) == line - 1:
2177 # delete breakpoint or toggle it to the next state 2229 # delete breakpoint or toggle it to the next state
2178 index = self.breakpointModel.getBreakPointIndex( 2230 index = self.breakpointModel.getBreakPointIndex(
2179 self.fileName, line) 2231 self.fileName, line)
2180 if Preferences.getDebugger("ThreeStateBreakPoints") and \ 2232 if (
2181 not self.breakpointModel.isBreakPointTemporaryByIndex( 2233 Preferences.getDebugger("ThreeStateBreakPoints") and
2182 index): 2234 not self.breakpointModel.isBreakPointTemporaryByIndex(
2235 index)
2236 ):
2183 self.breakpointModel.deleteBreakPointByIndex(index) 2237 self.breakpointModel.deleteBreakPointByIndex(index)
2184 self.__addBreakPoint(line, True) 2238 self.__addBreakPoint(line, True)
2185 else: 2239 else:
2186 self.breakpointModel.deleteBreakPointByIndex(index) 2240 self.breakpointModel.deleteBreakPointByIndex(index)
2187 self.breakpointToggled.emit(self) 2241 self.breakpointToggled.emit(self)
2951 QApplication.restoreOverrideCursor() 3005 QApplication.restoreOverrideCursor()
2952 raise 3006 raise
2953 3007
2954 modified = False 3008 modified = False
2955 3009
2956 if (not self.__getEditorConfig("TabForIndentation")) and \ 3010 self.setText(txt)
2957 Preferences.getEditor("ConvertTabsOnLoad") and \ 3011
2958 not (self.lexer_ and 3012 # get eric specific flags
2959 self.lexer_.alwaysKeepTabs()): 3013 self.__processFlags()
3014
3015 # perform automatic EOL conversion
3016 if (
3017 self.__getEditorConfig("EOLMode", nodefault=True) or
3018 Preferences.getEditor("AutomaticEOLConversion")
3019 ):
3020 self.convertEols(self.eolMode())
3021 else:
3022 fileEol = self.detectEolString(txt)
3023 self.setEolModeByEolString(fileEol)
3024
3025 self.extractTasks()
3026
3027 QApplication.restoreOverrideCursor()
3028
3029 self.setModified(modified)
3030 self.lastModified = QFileInfo(self.fileName).lastModified()
3031
3032 def __convertTabs(self):
3033 """
3034 Private slot to convert tabulators to spaces.
3035 """
3036 if (
3037 (not self.__getEditorConfig("TabForIndentation")) and
3038 Preferences.getEditor("ConvertTabsOnLoad") and
3039 not (self.lexer_ and
3040 self.lexer_.alwaysKeepTabs())
3041 ):
3042 txt = self.text()
2960 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth")) 3043 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth"))
2961 if txtExpanded != txt: 3044 if txtExpanded != txt:
2962 modified = True 3045 self.beginUndoAction
2963 txt = txtExpanded 3046 self.setText(txt)
2964 3047 self.endUndoAction()
2965 self.setText(txt) 3048
2966 3049 self.setModified(True)
2967 # get eric specific flags 3050
2968 self.__processFlags()
2969
2970 # perform automatic EOL conversion
2971 if self.__getEditorConfig("EOLMode", nodefault=True) or \
2972 Preferences.getEditor("AutomaticEOLConversion"):
2973 self.convertEols(self.eolMode())
2974 else:
2975 fileEol = self.detectEolString(txt)
2976 self.setEolModeByEolString(fileEol)
2977
2978 self.extractTasks()
2979
2980 QApplication.restoreOverrideCursor()
2981
2982 self.setModified(modified)
2983 self.lastModified = QFileInfo(self.fileName).lastModified()
2984
2985 def __removeTrailingWhitespace(self): 3051 def __removeTrailingWhitespace(self):
2986 """ 3052 """
2987 Private method to remove trailing whitespace. 3053 Private method to remove trailing whitespace.
2988 """ 3054 """
2989 searchRE = r"[ \t]+$" # whitespace at the end of a line 3055 searchRE = r"[ \t]+$" # whitespace at the end of a line
3071 @param path directory to save the file in (string) 3137 @param path directory to save the file in (string)
3072 @return file name (string) 3138 @return file name (string)
3073 """ 3139 """
3074 # save to project, if a project is loaded 3140 # save to project, if a project is loaded
3075 if self.project.isOpen(): 3141 if self.project.isOpen():
3076 if self.fileName and \ 3142 if (
3077 self.project.startswithProjectPath(self.fileName): 3143 self.fileName and
3144 self.project.startswithProjectPath(self.fileName)
3145 ):
3078 path = os.path.dirname(self.fileName) 3146 path = os.path.dirname(self.fileName)
3079 else: 3147 else:
3080 path = self.project.getProjectPath() 3148 path = self.project.getProjectPath()
3081 3149
3082 if not path and self.fileName: 3150 if not path and self.fileName:
3083 path = os.path.dirname(self.fileName) 3151 path = os.path.dirname(self.fileName)
3084 if not path: 3152 if not path:
3085 path = Preferences.getMultiProject("Workspace") or \ 3153 path = (
3154 Preferences.getMultiProject("Workspace") or
3086 Utilities.getHomeDir() 3155 Utilities.getHomeDir()
3156 )
3087 3157
3088 from . import Lexers 3158 from . import Lexers
3089 if self.fileName: 3159 if self.fileName:
3090 filterPattern = "(*{0})".format( 3160 filterPattern = "(*{0})".format(
3091 os.path.splitext(self.fileName)[1]) 3161 os.path.splitext(self.fileName)[1])
3139 return False 3209 return False
3140 3210
3141 res = self.writeFile(fn) 3211 res = self.writeFile(fn)
3142 if res: 3212 if res:
3143 # save to project, if a project is loaded 3213 # save to project, if a project is loaded
3144 if self.project.isOpen() and \ 3214 if (
3145 self.project.startswithProjectPath(fn): 3215 self.project.isOpen() and
3216 self.project.startswithProjectPath(fn)
3217 ):
3146 self.project.appendFile(fn) 3218 self.project.appendFile(fn)
3147 3219
3148 return res 3220 return res
3149 3221
3150 def saveFile(self, saveas=False, path=None): 3222 def saveFile(self, saveas=False, path=None):
3167 return False 3239 return False
3168 3240
3169 newName = fn 3241 newName = fn
3170 3242
3171 # save to project, if a project is loaded 3243 # save to project, if a project is loaded
3172 if self.project.isOpen() and \ 3244 if (
3173 self.project.startswithProjectPath(fn): 3245 self.project.isOpen() and
3246 self.project.startswithProjectPath(fn)
3247 ):
3174 editorConfigEol = self.__getEditorConfig( 3248 editorConfigEol = self.__getEditorConfig(
3175 "EOLMode", nodefault=True, 3249 "EOLMode", nodefault=True,
3176 config=self.__loadEditorConfigObject(fn)) 3250 config=self.__loadEditorConfigObject(fn))
3177 if editorConfigEol is not None: 3251 if editorConfigEol is not None:
3178 self.setEolMode(editorConfigEol) 3252 self.setEolMode(editorConfigEol)
3200 self.isResourcesFile = self.fileName.endswith(".qrc") 3274 self.isResourcesFile = self.fileName.endswith(".qrc")
3201 self.__initContextMenu() 3275 self.__initContextMenu()
3202 self.editorRenamed.emit(self.fileName) 3276 self.editorRenamed.emit(self.fileName)
3203 3277
3204 # save to project, if a project is loaded 3278 # save to project, if a project is loaded
3205 if self.project.isOpen() and \ 3279 if (
3206 self.project.startswithProjectPath(fn): 3280 self.project.isOpen() and
3281 self.project.startswithProjectPath(fn)
3282 ):
3207 self.project.appendFile(fn) 3283 self.project.appendFile(fn)
3208 self.addedToProject() 3284 self.addedToProject()
3209 3285
3210 self.setLanguage(self.fileName) 3286 self.setLanguage(self.fileName)
3211 3287
3626 commentStr = self.lexer_.commentStr() 3702 commentStr = self.lexer_.commentStr()
3627 line, index = self.getCursorPosition() 3703 line, index = self.getCursorPosition()
3628 3704
3629 # check if line starts with our comment string (i.e. was commented 3705 # check if line starts with our comment string (i.e. was commented
3630 # by our comment...() slots 3706 # by our comment...() slots
3631 if self.hasSelectedText() and \ 3707 if (
3632 self.__isCommentedLine(self.text(self.getSelection()[0]), 3708 self.hasSelectedText() and
3633 commentStr): 3709 self.__isCommentedLine(self.text(self.getSelection()[0]),
3710 commentStr)
3711 ):
3634 self.uncommentLineOrSelection() 3712 self.uncommentLineOrSelection()
3635 elif not self.__isCommentedLine(self.text(line), commentStr): 3713 elif not self.__isCommentedLine(self.text(line), commentStr):
3636 # it doesn't, so comment the line or selection 3714 # it doesn't, so comment the line or selection
3637 self.commentLineOrSelection() 3715 self.commentLineOrSelection()
3638 else: 3716 else:
3639 # determine the start of the comment block 3717 # determine the start of the comment block
3640 begline = line 3718 begline = line
3641 while begline > 0 and \ 3719 while (
3642 self.__isCommentedLine(self.text(begline - 1), commentStr): 3720 begline > 0 and
3721 self.__isCommentedLine(self.text(begline - 1), commentStr)
3722 ):
3643 begline -= 1 3723 begline -= 1
3644 # determine the end of the comment block 3724 # determine the end of the comment block
3645 endline = line 3725 endline = line
3646 lines = self.lines() 3726 lines = self.lines()
3647 while endline < lines and \ 3727 while (
3648 self.__isCommentedLine(self.text(endline + 1), commentStr): 3728 endline < lines and
3729 self.__isCommentedLine(self.text(endline + 1), commentStr)
3730 ):
3649 endline += 1 3731 endline += 1
3650 3732
3651 self.setSelection(begline, 0, endline, self.lineLength(endline)) 3733 self.setSelection(begline, 0, endline, self.lineLength(endline))
3652 self.uncommentLineOrSelection() 3734 self.uncommentLineOrSelection()
3653 3735
4272 marginBmMask = (1 << self.bookmark) 4354 marginBmMask = (1 << self.bookmark)
4273 self.setMarginWidth(self.__bmMargin, 16) 4355 self.setMarginWidth(self.__bmMargin, 16)
4274 self.setMarginSensitivity(self.__bmMargin, True) 4356 self.setMarginSensitivity(self.__bmMargin, True)
4275 self.setMarginMarkerMask(self.__bmMargin, marginBmMask) 4357 self.setMarginMarkerMask(self.__bmMargin, marginBmMask)
4276 4358
4277 marginBpMask = (1 << self.breakpoint) | \ 4359 marginBpMask = (
4278 (1 << self.cbreakpoint) | \ 4360 (1 << self.breakpoint) |
4279 (1 << self.tbreakpoint) | \ 4361 (1 << self.cbreakpoint) |
4280 (1 << self.tcbreakpoint) | \ 4362 (1 << self.tbreakpoint) |
4281 (1 << self.dbreakpoint) 4363 (1 << self.tcbreakpoint) |
4364 (1 << self.dbreakpoint)
4365 )
4282 self.setMarginWidth(self.__bpMargin, 16) 4366 self.setMarginWidth(self.__bpMargin, 16)
4283 self.setMarginSensitivity(self.__bpMargin, True) 4367 self.setMarginSensitivity(self.__bpMargin, True)
4284 self.setMarginMarkerMask(self.__bpMargin, marginBpMask) 4368 self.setMarginMarkerMask(self.__bpMargin, marginBpMask)
4285 4369
4286 marginIndicMask = (1 << self.syntaxerror) | \ 4370 marginIndicMask = (
4287 (1 << self.notcovered) | \ 4371 (1 << self.syntaxerror) |
4288 (1 << self.taskmarker) | \ 4372 (1 << self.notcovered) |
4289 (1 << self.warning) | \ 4373 (1 << self.taskmarker) |
4290 (1 << self.__changeMarkerUnsaved) | \ 4374 (1 << self.warning) |
4291 (1 << self.__changeMarkerSaved) | \ 4375 (1 << self.__changeMarkerUnsaved) |
4292 (1 << self.currentline) | \ 4376 (1 << self.__changeMarkerSaved) |
4293 (1 << self.errorline) 4377 (1 << self.currentline) |
4378 (1 << self.errorline)
4379 )
4294 self.setMarginWidth(self.__indicMargin, 16) 4380 self.setMarginWidth(self.__indicMargin, 16)
4295 self.setMarginSensitivity(self.__indicMargin, True) 4381 self.setMarginSensitivity(self.__indicMargin, True)
4296 self.setMarginMarkerMask(self.__indicMargin, marginIndicMask) 4382 self.setMarginMarkerMask(self.__indicMargin, marginIndicMask)
4297 4383
4298 # set linenumber margin settings 4384 # set linenumber margin settings
4430 4516
4431 self.searchIndicator = QsciScintilla.INDIC_CONTAINER 4517 self.searchIndicator = QsciScintilla.INDIC_CONTAINER
4432 self.indicatorDefine( 4518 self.indicatorDefine(
4433 self.searchIndicator, QsciScintilla.INDIC_BOX, 4519 self.searchIndicator, QsciScintilla.INDIC_BOX,
4434 Preferences.getEditorColour("SearchMarkers")) 4520 Preferences.getEditorColour("SearchMarkers"))
4435 if not Preferences.getEditor("SearchMarkersEnabled") and \ 4521 if (
4436 not Preferences.getEditor("QuickSearchMarkersEnabled") and \ 4522 not Preferences.getEditor("SearchMarkersEnabled") and
4437 not Preferences.getEditor("MarkOccurrencesEnabled"): 4523 not Preferences.getEditor("QuickSearchMarkersEnabled") and
4524 not Preferences.getEditor("MarkOccurrencesEnabled")
4525 ):
4438 self.clearAllIndicators(self.searchIndicator) 4526 self.clearAllIndicators(self.searchIndicator)
4439 4527
4440 self.spellingIndicator = QsciScintilla.INDIC_CONTAINER + 1 4528 self.spellingIndicator = QsciScintilla.INDIC_CONTAINER + 1
4441 self.indicatorDefine( 4529 self.indicatorDefine(
4442 self.spellingIndicator, QsciScintilla.INDIC_SQUIGGLE, 4530 self.spellingIndicator, QsciScintilla.INDIC_SQUIGGLE,
4470 4558
4471 def __setEolMode(self): 4559 def __setEolMode(self):
4472 """ 4560 """
4473 Private method to configure the eol mode of the editor. 4561 Private method to configure the eol mode of the editor.
4474 """ 4562 """
4475 if self.fileName and \ 4563 if (
4476 self.project.isOpen() and \ 4564 self.fileName and
4477 self.project.isProjectFile(self.fileName): 4565 self.project.isOpen() and
4566 self.project.isProjectFile(self.fileName)
4567 ):
4478 eolMode = self.__getEditorConfig("EOLMode", nodefault=True) 4568 eolMode = self.__getEditorConfig("EOLMode", nodefault=True)
4479 if eolMode is None: 4569 if eolMode is None:
4480 eolStr = self.project.getEolString() 4570 eolStr = self.project.getEolString()
4481 self.setEolModeByEolString(eolStr) 4571 self.setEolModeByEolString(eolStr)
4482 else: 4572 else:
4531 pass 4621 pass
4532 4622
4533 if Preferences.getEditor("CallTipsEnabled"): 4623 if Preferences.getEditor("CallTipsEnabled"):
4534 if calltipsStyle == QsciScintilla.CallTipsNoContext: 4624 if calltipsStyle == QsciScintilla.CallTipsNoContext:
4535 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) 4625 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext)
4536 elif calltipsStyle == \ 4626 elif (
4537 QsciScintilla.CallTipsNoAutoCompletionContext: 4627 calltipsStyle == QsciScintilla.CallTipsNoAutoCompletionContext
4628 ):
4538 self.setCallTipsStyle( 4629 self.setCallTipsStyle(
4539 QsciScintilla.CallTipsNoAutoCompletionContext) 4630 QsciScintilla.CallTipsNoAutoCompletionContext)
4540 else: 4631 else:
4541 self.setCallTipsStyle(QsciScintilla.CallTipsContext) 4632 self.setCallTipsStyle(QsciScintilla.CallTipsContext)
4542 else: 4633 else:
4584 4675
4585 @param enable flag indicating the desired autocompletion status 4676 @param enable flag indicating the desired autocompletion status
4586 (boolean) 4677 (boolean)
4587 """ 4678 """
4588 if enable: 4679 if enable:
4589 autoCompletionSource = \ 4680 autoCompletionSource = Preferences.getEditor(
4590 Preferences.getEditor("AutoCompletionSource") 4681 "AutoCompletionSource")
4591 if autoCompletionSource == QsciScintilla.AcsDocument: 4682 if autoCompletionSource == QsciScintilla.AcsDocument:
4592 self.setAutoCompletionSource(QsciScintilla.AcsDocument) 4683 self.setAutoCompletionSource(QsciScintilla.AcsDocument)
4593 elif autoCompletionSource == QsciScintilla.AcsAPIs: 4684 elif autoCompletionSource == QsciScintilla.AcsAPIs:
4594 self.setAutoCompletionSource(QsciScintilla.AcsAPIs) 4685 self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
4595 else: 4686 else:
4614 4705
4615 @param charNumber value of the character entered (integer) 4706 @param charNumber value of the character entered (integer)
4616 """ 4707 """
4617 char = chr(charNumber) 4708 char = chr(charNumber)
4618 # update code documentation viewer 4709 # update code documentation viewer
4619 if char == "(" and \ 4710 if (
4620 Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"): 4711 char == "(" and
4712 Preferences.getDocuViewer("ShowInfoOnOpenParenthesis")
4713 ):
4621 self.vm.showEditorInfo(self) 4714 self.vm.showEditorInfo(self)
4622 4715
4623 if self.isListActive(): 4716 if self.isListActive():
4624 if self.__isStartChar(char): 4717 if self.__isStartChar(char):
4625 self.cancelList() 4718 self.cancelList()
4628 elif char == '(': 4721 elif char == '(':
4629 self.cancelList() 4722 self.cancelList()
4630 else: 4723 else:
4631 self.__acTimer.stop() 4724 self.__acTimer.stop()
4632 4725
4633 if self.callTipsStyle() != QsciScintilla.CallTipsNone and \ 4726 if (
4634 self.lexer_ is not None and chr(charNumber) in '()': 4727 self.callTipsStyle() != QsciScintilla.CallTipsNone and
4728 self.lexer_ is not None and chr(charNumber) in '()'
4729 ):
4635 self.callTip() 4730 self.callTip()
4636 4731
4637 if not self.isCallTipActive(): 4732 if not self.isCallTipActive():
4638 char = chr(charNumber) 4733 char = chr(charNumber)
4639 if self.__isStartChar(char): 4734 if self.__isStartChar(char):
4690 and function(editor, bool, str) returning nothing in case async 4785 and function(editor, bool, str) returning nothing in case async
4691 is True 4786 is True
4692 @param asynchroneous flag indicating an asynchroneous function 4787 @param asynchroneous flag indicating an asynchroneous function
4693 @type bool 4788 @type bool
4694 """ 4789 """
4695 if key in self.__completionListHookFunctions or \ 4790 if (
4696 key in self.__completionListAsyncHookFunctions: 4791 key in self.__completionListHookFunctions or
4792 key in self.__completionListAsyncHookFunctions
4793 ):
4697 # it was already registered 4794 # it was already registered
4698 E5MessageBox.warning( 4795 E5MessageBox.warning(
4699 self, 4796 self,
4700 self.tr("Auto-Completion Provider"), 4797 self.tr("Auto-Completion Provider"),
4701 self.tr("""The completion list provider '{0}' was already""" 4798 self.tr("""The completion list provider '{0}' was already"""
4746 return 4843 return
4747 4844
4748 if self.isListActive(): 4845 if self.isListActive():
4749 self.cancelList() 4846 self.cancelList()
4750 4847
4751 if self.__completionListHookFunctions or \ 4848 if (
4752 self.__completionListAsyncHookFunctions: 4849 self.__completionListHookFunctions or
4850 self.__completionListAsyncHookFunctions
4851 ):
4753 # Avoid delayed auto-completion after cursor repositioning 4852 # Avoid delayed auto-completion after cursor repositioning
4754 self.__acText = self.__getAcText() 4853 self.__acText = self.__getAcText()
4755 if auto and Preferences.getEditor("AutoCompletionTimeout"): 4854 if auto and Preferences.getEditor("AutoCompletionTimeout"):
4756 self.__acTimer.stop() 4855 self.__acTimer.stop()
4757 self.__acContext = context 4856 self.__acContext = context
4850 len(self.__completionListHookFunctions) 4949 len(self.__completionListHookFunctions)
4851 ): 4950 ):
4852 self.__acWatchdog.stop() 4951 self.__acWatchdog.stop()
4853 4952
4854 # Autocomplete with QScintilla if no results present 4953 # Autocomplete with QScintilla if no results present
4855 if Preferences.getEditor("AutoCompletionScintillaOnFail") and \ 4954 if (
4856 not self.__acCompletions: 4955 Preferences.getEditor("AutoCompletionScintillaOnFail") and
4956 not self.__acCompletions
4957 ):
4857 self.autoCompleteQScintilla() 4958 self.autoCompleteQScintilla()
4858 return 4959 return
4859 4960
4860 # ... or completions are not empty 4961 # ... or completions are not empty
4861 if not bool(completions): 4962 if not bool(completions):
5173 @param evt the context menu event (QContextMenuEvent) 5274 @param evt the context menu event (QContextMenuEvent)
5174 """ 5275 """
5175 evt.accept() 5276 evt.accept()
5176 if self.__marginNumber(evt.x()) == -1: 5277 if self.__marginNumber(evt.x()) == -1:
5177 self.spellingMenuPos = self.positionFromPoint(evt.pos()) 5278 self.spellingMenuPos = self.positionFromPoint(evt.pos())
5178 if self.spellingMenuPos >= 0 and \ 5279 if (
5179 self.spell is not None and \ 5280 self.spellingMenuPos >= 0 and
5180 self.hasIndicator(self.spellingIndicator, self.spellingMenuPos): 5281 self.spell is not None and
5282 self.hasIndicator(self.spellingIndicator,
5283 self.spellingMenuPos)
5284 ):
5181 self.spellingMenu.popup(evt.globalPos()) 5285 self.spellingMenu.popup(evt.globalPos())
5182 else: 5286 else:
5183 self.menu.popup(evt.globalPos()) 5287 self.menu.popup(evt.globalPos())
5184 else: 5288 else:
5185 self.line = self.lineAt(evt.pos()) 5289 self.line = self.lineAt(evt.pos())
5212 if not self.isResourcesFile: 5316 if not self.isResourcesFile:
5213 if self.fileName and self.isPyFile(): 5317 if self.fileName and self.isPyFile():
5214 self.menuActs["Show"].setEnabled(True) 5318 self.menuActs["Show"].setEnabled(True)
5215 else: 5319 else:
5216 self.menuActs["Show"].setEnabled(False) 5320 self.menuActs["Show"].setEnabled(False)
5217 if self.fileName and \ 5321 if (
5218 (self.isPyFile() or self.isRubyFile()): 5322 self.fileName and
5323 (self.isPyFile() or self.isRubyFile())
5324 ):
5219 self.menuActs["Diagrams"].setEnabled(True) 5325 self.menuActs["Diagrams"].setEnabled(True)
5220 else: 5326 else:
5221 self.menuActs["Diagrams"].setEnabled(False) 5327 self.menuActs["Diagrams"].setEnabled(False)
5222 if not self.miniMenu: 5328 if not self.miniMenu:
5223 if self.lexer_ is not None: 5329 if self.lexer_ is not None:
5293 """ 5399 """
5294 prEnable = False 5400 prEnable = False
5295 coEnable = False 5401 coEnable = False
5296 5402
5297 # first check if the file belongs to a project 5403 # first check if the file belongs to a project
5298 if self.project.isOpen() and \ 5404 if (
5299 self.project.isProjectSource(self.fileName): 5405 self.project.isOpen() and
5406 self.project.isProjectSource(self.fileName)
5407 ):
5300 fn = self.project.getMainScript(True) 5408 fn = self.project.getMainScript(True)
5301 if fn is not None: 5409 if fn is not None:
5302 tfn = Utilities.getTestFileName(fn) 5410 tfn = Utilities.getTestFileName(fn)
5303 basename = os.path.splitext(fn)[0] 5411 basename = os.path.splitext(fn)[0]
5304 tbasename = os.path.splitext(tfn)[0] 5412 tbasename = os.path.splitext(tfn)[0]
5305 prEnable = prEnable or \ 5413 prEnable = (
5306 os.path.isfile("{0}.profile".format(basename)) or \ 5414 prEnable or
5415 os.path.isfile("{0}.profile".format(basename)) or
5307 os.path.isfile("{0}.profile".format(tbasename)) 5416 os.path.isfile("{0}.profile".format(tbasename))
5417 )
5308 coEnable = ( 5418 coEnable = (
5309 coEnable or 5419 (coEnable or
5310 os.path.isfile("{0}.coverage".format(basename)) or 5420 os.path.isfile("{0}.coverage".format(basename)) or
5311 os.path.isfile("{0}.coverage".format(tbasename))) and \ 5421 os.path.isfile("{0}.coverage".format(tbasename))) and
5312 (self.project.isPy3Project() or 5422 (self.project.isPy3Project() or
5313 self.project.isPy2Project()) 5423 self.project.isPy2Project())
5424 )
5314 5425
5315 # now check ourselves 5426 # now check ourselves
5316 fn = self.getFileName() 5427 fn = self.getFileName()
5317 if fn is not None: 5428 if fn is not None:
5318 tfn = Utilities.getTestFileName(fn) 5429 tfn = Utilities.getTestFileName(fn)
5319 basename = os.path.splitext(fn)[0] 5430 basename = os.path.splitext(fn)[0]
5320 tbasename = os.path.splitext(tfn)[0] 5431 tbasename = os.path.splitext(tfn)[0]
5321 prEnable = prEnable or \ 5432 prEnable = (
5322 os.path.isfile("{0}.profile".format(basename)) or \ 5433 prEnable or
5434 os.path.isfile("{0}.profile".format(basename)) or
5323 os.path.isfile("{0}.profile".format(tbasename)) 5435 os.path.isfile("{0}.profile".format(tbasename))
5436 )
5324 coEnable = ( 5437 coEnable = (
5325 coEnable or 5438 (coEnable or
5326 os.path.isfile("{0}.coverage".format(basename)) or 5439 os.path.isfile("{0}.coverage".format(basename)) or
5327 os.path.isfile("{0}.coverage".format(tbasename))) and \ 5440 os.path.isfile("{0}.coverage".format(tbasename))) and
5328 self.isPyFile() 5441 self.isPyFile()
5442 )
5329 5443
5330 # now check for syntax errors 5444 # now check for syntax errors
5331 if self.hasSyntaxErrors(): 5445 if self.hasSyntaxErrors():
5332 coEnable = False 5446 coEnable = False
5333 5447
5343 def __showContextMenuGraphics(self): 5457 def __showContextMenuGraphics(self):
5344 """ 5458 """
5345 Private slot handling the aboutToShow signal of the diagrams context 5459 Private slot handling the aboutToShow signal of the diagrams context
5346 menu. 5460 menu.
5347 """ 5461 """
5348 if self.project.isOpen() and \ 5462 if (
5349 self.project.isProjectSource(self.fileName): 5463 self.project.isOpen() and
5464 self.project.isProjectSource(self.fileName)
5465 ):
5350 self.applicationDiagramMenuAct.setEnabled(True) 5466 self.applicationDiagramMenuAct.setEnabled(True)
5351 else: 5467 else:
5352 self.applicationDiagramMenuAct.setEnabled(False) 5468 self.applicationDiagramMenuAct.setEnabled(False)
5353 5469
5354 self.showMenu.emit("Graphics", self.graphicsMenu, self) 5470 self.showMenu.emit("Graphics", self.graphicsMenu, self)
5407 hasWarnings = bool(self.warnings) 5523 hasWarnings = bool(self.warnings)
5408 hasNotCoveredMarkers = bool(self.notcoveredMarkers) 5524 hasNotCoveredMarkers = bool(self.notcoveredMarkers)
5409 5525
5410 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors) 5526 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors)
5411 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors) 5527 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors)
5412 if hasSyntaxErrors and \ 5528 if (
5413 self.markersAtLine(self.line) & (1 << self.syntaxerror): 5529 hasSyntaxErrors and
5530 self.markersAtLine(self.line) & (1 << self.syntaxerror)
5531 ):
5414 self.marginMenuActs["ShowSyntaxError"].setEnabled(True) 5532 self.marginMenuActs["ShowSyntaxError"].setEnabled(True)
5415 else: 5533 else:
5416 self.marginMenuActs["ShowSyntaxError"].setEnabled(False) 5534 self.marginMenuActs["ShowSyntaxError"].setEnabled(False)
5417 5535
5418 self.marginMenuActs["NextWarningMarker"].setEnabled(hasWarnings) 5536 self.marginMenuActs["NextWarningMarker"].setEnabled(hasWarnings)
5419 self.marginMenuActs["PreviousWarningMarker"].setEnabled( 5537 self.marginMenuActs["PreviousWarningMarker"].setEnabled(
5420 hasWarnings) 5538 hasWarnings)
5421 self.marginMenuActs["ClearWarnings"].setEnabled(hasWarnings) 5539 self.marginMenuActs["ClearWarnings"].setEnabled(hasWarnings)
5422 if hasWarnings and \ 5540 if (
5423 self.markersAtLine(self.line) & (1 << self.warning): 5541 hasWarnings and
5542 self.markersAtLine(self.line) & (1 << self.warning)
5543 ):
5424 self.marginMenuActs["ShowWarning"].setEnabled(True) 5544 self.marginMenuActs["ShowWarning"].setEnabled(True)
5425 else: 5545 else:
5426 self.marginMenuActs["ShowWarning"].setEnabled(False) 5546 self.marginMenuActs["ShowWarning"].setEnabled(False)
5427 5547
5428 self.marginMenuActs["NextCoverageMarker"].setEnabled( 5548 self.marginMenuActs["NextCoverageMarker"].setEnabled(
5465 5585
5466 @param act reference to the action that was triggered (QAction) 5586 @param act reference to the action that was triggered (QAction)
5467 """ 5587 """
5468 encoding = act.data() 5588 encoding = act.data()
5469 self.readFile(self.fileName, encoding=encoding) 5589 self.readFile(self.fileName, encoding=encoding)
5590 self.__convertTabs()
5470 self.__checkEncoding() 5591 self.__checkEncoding()
5471 5592
5472 def __contextSave(self): 5593 def __contextSave(self):
5473 """ 5594 """
5474 Private slot handling the save context menu entry. 5595 Private slot handling the save context menu entry.
5542 line0Text = self.text(curLine) 5663 line0Text = self.text(curLine)
5543 line1Text = self.text(curLine + 1) 5664 line1Text = self.text(curLine + 1)
5544 if line1Text in ["", "\r", "\n", "\r\n"]: 5665 if line1Text in ["", "\r", "\n", "\r\n"]:
5545 return 5666 return
5546 5667
5547 if line0Text.rstrip("\r\n\\ \t").endswith(("'", '"')) and \ 5668 if (
5548 line1Text.lstrip().startswith(("'", '"')): 5669 line0Text.rstrip("\r\n\\ \t").endswith(("'", '"')) and
5670 line1Text.lstrip().startswith(("'", '"'))
5671 ):
5549 # merging multi line strings 5672 # merging multi line strings
5550 startChars = "\r\n\\ \t'\"" 5673 startChars = "\r\n\\ \t'\""
5551 endChars = " \t'\"" 5674 endChars = " \t'\""
5552 else: 5675 else:
5553 startChars = "\r\n\\ \t" 5676 startChars = "\r\n\\ \t"
5598 """ 5721 """
5599 Public slot to check the autosave flags. 5722 Public slot to check the autosave flags.
5600 5723
5601 @return flag indicating this editor should be saved (boolean) 5724 @return flag indicating this editor should be saved (boolean)
5602 """ 5725 """
5603 return bool(self.fileName) and \ 5726 return (
5604 not self.autosaveManuallyDisabled and \ 5727 bool(self.fileName) and
5728 not self.autosaveManuallyDisabled and
5605 not self.isReadOnly() 5729 not self.isReadOnly()
5730 )
5606 5731
5607 def checkSyntax(self): 5732 def checkSyntax(self):
5608 """ 5733 """
5609 Public method to perform an automatic syntax check of the file. 5734 Public method to perform an automatic syntax check of the file.
5610 """ 5735 """
5611 fileType = self.filetype 5736 fileType = self.filetype
5612 if fileType == "MicroPython": 5737 if fileType == "MicroPython":
5613 # adjustment for MicroPython 5738 # adjustment for MicroPython
5614 fileType = "Python3" 5739 fileType = "Python3"
5615 5740
5616 if self.syntaxCheckService is None or \ 5741 if (
5617 fileType not in self.syntaxCheckService.getLanguages(): 5742 self.syntaxCheckService is None or
5743 fileType not in self.syntaxCheckService.getLanguages()
5744 ):
5618 return 5745 return
5619 5746
5620 if Preferences.getEditor("AutoCheckSyntax"): 5747 if Preferences.getEditor("AutoCheckSyntax"):
5621 if Preferences.getEditor("OnlineSyntaxCheck"): 5748 if Preferences.getEditor("OnlineSyntaxCheck"):
5622 self.__onlineSyntaxCheckTimer.stop() 5749 self.__onlineSyntaxCheckTimer.stop()
5713 """ 5840 """
5714 files = [] 5841 files = []
5715 5842
5716 # first check if the file belongs to a project and there is 5843 # first check if the file belongs to a project and there is
5717 # a project coverage file 5844 # a project coverage file
5718 if self.project.isOpen() and \ 5845 if (
5719 self.project.isProjectSource(self.fileName): 5846 self.project.isOpen() and
5847 self.project.isProjectSource(self.fileName)
5848 ):
5720 fn = self.project.getMainScript(True) 5849 fn = self.project.getMainScript(True)
5721 if fn is not None: 5850 if fn is not None:
5722 tfn = Utilities.getTestFileName(fn) 5851 tfn = Utilities.getTestFileName(fn)
5723 basename = os.path.splitext(fn)[0] 5852 basename = os.path.splitext(fn)[0]
5724 tbasename = os.path.splitext(tfn)[0] 5853 tbasename = os.path.splitext(tfn)[0]
5891 """ 6020 """
5892 files = [] 6021 files = []
5893 6022
5894 # first check if the file belongs to a project and there is 6023 # first check if the file belongs to a project and there is
5895 # a project profile file 6024 # a project profile file
5896 if self.project.isOpen() and \ 6025 if (
5897 self.project.isProjectSource(self.fileName): 6026 self.project.isOpen() and
6027 self.project.isProjectSource(self.fileName)
6028 ):
5898 fn = self.project.getMainScript(True) 6029 fn = self.project.getMainScript(True)
5899 if fn is not None: 6030 if fn is not None:
5900 tfn = Utilities.getTestFileName(fn) 6031 tfn = Utilities.getTestFileName(fn)
5901 basename = os.path.splitext(fn)[0] 6032 basename = os.path.splitext(fn)[0]
5902 tbasename = os.path.splitext(tfn)[0] 6033 tbasename = os.path.splitext(tfn)[0]
5985 handle = self.markerAdd(line - 1, self.syntaxerror) 6116 handle = self.markerAdd(line - 1, self.syntaxerror)
5986 self.syntaxerrors[handle] = [(msg, index)] 6117 self.syntaxerrors[handle] = [(msg, index)]
5987 self.syntaxerrorToggled.emit(self) 6118 self.syntaxerrorToggled.emit(self)
5988 else: 6119 else:
5989 for handle in list(self.syntaxerrors.keys()): 6120 for handle in list(self.syntaxerrors.keys()):
5990 if self.markerLine(handle) == line - 1 and \ 6121 if (
5991 (msg, index) not in self.syntaxerrors[handle]: 6122 self.markerLine(handle) == line - 1 and
6123 (msg, index) not in self.syntaxerrors[handle]
6124 ):
5992 self.syntaxerrors[handle].append((msg, index)) 6125 self.syntaxerrors[handle].append((msg, index))
5993 if show: 6126 if show:
5994 self.setCursorPosition(line - 1, index) 6127 self.setCursorPosition(line - 1, index)
5995 self.ensureLineVisible(line - 1) 6128 self.ensureLineVisible(line - 1)
5996 else: 6129 else:
6140 handle = self.markerAdd(line - 1, self.warning) 6273 handle = self.markerAdd(line - 1, self.warning)
6141 self.warnings[handle] = [warn] 6274 self.warnings[handle] = [warn]
6142 self.syntaxerrorToggled.emit(self) 6275 self.syntaxerrorToggled.emit(self)
6143 else: 6276 else:
6144 for handle in list(self.warnings.keys()): 6277 for handle in list(self.warnings.keys()):
6145 if self.markerLine(handle) == line - 1 and \ 6278 if (
6146 warn not in self.warnings[handle]: 6279 self.markerLine(handle) == line - 1 and
6280 warn not in self.warnings[handle]
6281 ):
6147 self.warnings[handle].append(warn) 6282 self.warnings[handle].append(warn)
6148 else: 6283 else:
6149 for handle in list(self.warnings.keys()): 6284 for handle in list(self.warnings.keys()):
6150 if self.markerLine(handle) == line - 1: 6285 if self.markerLine(handle) == line - 1:
6151 del self.warnings[handle] 6286 del self.warnings[handle]
6308 def __setAnnotationStyles(self): 6443 def __setAnnotationStyles(self):
6309 """ 6444 """
6310 Private slot to define the style used by inline annotations. 6445 Private slot to define the style used by inline annotations.
6311 """ 6446 """
6312 if hasattr(QsciScintilla, "annotate"): 6447 if hasattr(QsciScintilla, "annotate"):
6313 self.annotationWarningStyle = \ 6448 self.annotationWarningStyle = (
6314 QsciScintilla.STYLE_LASTPREDEFINED + 1 6449 QsciScintilla.STYLE_LASTPREDEFINED + 1
6450 )
6315 self.SendScintilla( 6451 self.SendScintilla(
6316 QsciScintilla.SCI_STYLESETFORE, 6452 QsciScintilla.SCI_STYLESETFORE,
6317 self.annotationWarningStyle, 6453 self.annotationWarningStyle,
6318 Preferences.getEditorColour("AnnotationsWarningForeground")) 6454 Preferences.getEditorColour("AnnotationsWarningForeground"))
6319 self.SendScintilla( 6455 self.SendScintilla(
6399 """ 6535 """
6400 Private method to refresh the annotations. 6536 Private method to refresh the annotations.
6401 """ 6537 """
6402 if hasattr(QsciScintilla, "annotate"): 6538 if hasattr(QsciScintilla, "annotate"):
6403 self.clearAnnotations() 6539 self.clearAnnotations()
6404 for handle in list(self.warnings.keys()) + \ 6540 for handle in (
6405 list(self.syntaxerrors.keys()): 6541 list(self.warnings.keys()) +
6542 list(self.syntaxerrors.keys())
6543 ):
6406 line = self.markerLine(handle) 6544 line = self.markerLine(handle)
6407 self.__setAnnotation(line) 6545 self.__setAnnotation(line)
6408 6546
6409 ################################################################# 6547 #################################################################
6410 ## Fold handling methods 6548 ## Fold handling methods
6731 try: 6869 try:
6732 self.setCaretWidth(self.caretWidth) 6870 self.setCaretWidth(self.caretWidth)
6733 except AttributeError: 6871 except AttributeError:
6734 pass 6872 pass
6735 self.__updateReadOnly(False) 6873 self.__updateReadOnly(False)
6736 if self.vm.editorsCheckFocusInEnabled() and \ 6874 if (
6737 not self.inReopenPrompt and self.fileName and \ 6875 self.vm.editorsCheckFocusInEnabled() and
6738 QFileInfo(self.fileName).lastModified().toString() != \ 6876 not self.inReopenPrompt and self.fileName and
6739 self.lastModified.toString(): 6877 QFileInfo(self.fileName).lastModified().toString() !=
6878 self.lastModified.toString()
6879 ):
6740 self.inReopenPrompt = True 6880 self.inReopenPrompt = True
6741 if Preferences.getEditor("AutoReopen") and not self.isModified(): 6881 if Preferences.getEditor("AutoReopen") and not self.isModified():
6742 self.refresh() 6882 self.refresh()
6743 else: 6883 else:
6744 msg = self.tr( 6884 msg = self.tr(
6745 """<p>The file <b>{0}</b> has been changed while it""" 6885 """<p>The file <b>{0}</b> has been changed while it"""
6746 """ was opened in eric6. Reread it?</p>""")\ 6886 """ was opened in eric6. Reread it?</p>"""
6747 .format(self.fileName) 6887 ).format(self.fileName)
6748 yesDefault = True 6888 yesDefault = True
6749 if self.isModified(): 6889 if self.isModified():
6750 msg += self.tr( 6890 msg += self.tr(
6751 """<br><b>Warning:</b> You will lose""" 6891 """<br><b>Warning:</b> You will lose"""
6752 """ your changes upon reopening it.""") 6892 """ your changes upon reopening it.""")
6788 other modes. This is to make the editor windows work nicer 6928 other modes. This is to make the editor windows work nicer
6789 with the QWorkspace. 6929 with the QWorkspace.
6790 6930
6791 @param evt the event, that was generated (QEvent) 6931 @param evt the event, that was generated (QEvent)
6792 """ 6932 """
6793 if evt.type() == QEvent.WindowStateChange and \ 6933 if (
6794 bool(self.fileName): 6934 evt.type() == QEvent.WindowStateChange and
6935 bool(self.fileName)
6936 ):
6795 if self.windowState() == Qt.WindowStates(Qt.WindowMinimized): 6937 if self.windowState() == Qt.WindowStates(Qt.WindowMinimized):
6796 cap = os.path.basename(self.fileName) 6938 cap = os.path.basename(self.fileName)
6797 else: 6939 else:
6798 cap = self.fileName 6940 cap = self.fileName
6799 if self.isReadOnly(): 6941 if self.isReadOnly():
6815 """ 6957 """
6816 Protected method to handle wheel events. 6958 Protected method to handle wheel events.
6817 6959
6818 @param evt reference to the wheel event (QWheelEvent) 6960 @param evt reference to the wheel event (QWheelEvent)
6819 """ 6961 """
6820 if qVersionTuple() >= (5, 0, 0): 6962 delta = evt.angleDelta().y()
6821 delta = evt.angleDelta().y()
6822 else:
6823 delta = evt.delta()
6824 if evt.modifiers() & Qt.ControlModifier: 6963 if evt.modifiers() & Qt.ControlModifier:
6825 if delta < 0: 6964 if delta < 0:
6826 self.zoomOut() 6965 self.zoomOut()
6827 elif delta > 0: 6966 elif delta > 0:
6828 self.zoomIn() 6967 self.zoomIn()
6906 signal if there was an attribute change. 7045 signal if there was an attribute change.
6907 """ 7046 """
6908 if self.fileName == "": 7047 if self.fileName == "":
6909 return 7048 return
6910 7049
6911 readOnly = not QFileInfo(self.fileName).isWritable() or \ 7050 readOnly = (
7051 not QFileInfo(self.fileName).isWritable() or
6912 self.isReadOnly() 7052 self.isReadOnly()
7053 )
6913 if not bForce and (readOnly == self.isReadOnly()): 7054 if not bForce and (readOnly == self.isReadOnly()):
6914 return 7055 return
6915 7056
6916 cap = self.fileName 7057 cap = self.fileName
6917 if readOnly: 7058 if readOnly:
6952 self.readFile(self.fileName) 7093 self.readFile(self.fileName)
6953 except IOError: 7094 except IOError:
6954 # do not prompt for this change again... 7095 # do not prompt for this change again...
6955 self.lastModified = QDateTime.currentDateTime() 7096 self.lastModified = QDateTime.currentDateTime()
6956 self.setModified(False) 7097 self.setModified(False)
7098 self.__convertTabs()
6957 7099
6958 # re-initialize the online change tracer 7100 # re-initialize the online change tracer
6959 self.__reinitOnlineChangeTrace() 7101 self.__reinitOnlineChangeTrace()
6960 7102
6961 # reset cursor position 7103 # reset cursor position
7211 """ 7353 """
7212 from Graphics.UMLDialog import UMLDialog 7354 from Graphics.UMLDialog import UMLDialog
7213 if not self.checkDirty(): 7355 if not self.checkDirty():
7214 return 7356 return
7215 7357
7216 package = os.path.isdir(self.fileName) and \ 7358 package = (
7359 os.path.isdir(self.fileName) and
7217 self.fileName or os.path.dirname(self.fileName) 7360 self.fileName or os.path.dirname(self.fileName)
7361 )
7218 res = E5MessageBox.yesNo( 7362 res = E5MessageBox.yesNo(
7219 self, 7363 self,
7220 self.tr("Package Diagram"), 7364 self.tr("Package Diagram"),
7221 self.tr("""Include class attributes?"""), 7365 self.tr("""Include class attributes?"""),
7222 yesDefault=True) 7366 yesDefault=True)
7231 """ 7375 """
7232 from Graphics.UMLDialog import UMLDialog 7376 from Graphics.UMLDialog import UMLDialog
7233 if not self.checkDirty(): 7377 if not self.checkDirty():
7234 return 7378 return
7235 7379
7236 package = os.path.isdir(self.fileName) and self.fileName \ 7380 package = (
7237 or os.path.dirname(self.fileName) 7381 os.path.isdir(self.fileName) and
7382 self.fileName or os.path.dirname(self.fileName)
7383 )
7238 res = E5MessageBox.yesNo( 7384 res = E5MessageBox.yesNo(
7239 self, 7385 self,
7240 self.tr("Imports Diagram"), 7386 self.tr("Imports Diagram"),
7241 self.tr("""Include imports from external modules?""")) 7387 self.tr("""Include imports from external modules?"""))
7242 self.importsDiagram = UMLDialog( 7388 self.importsDiagram = UMLDialog(
7378 7524
7379 def projectOpened(self): 7525 def projectOpened(self):
7380 """ 7526 """
7381 Public slot to handle the opening of a project. 7527 Public slot to handle the opening of a project.
7382 """ 7528 """
7383 if self.fileName and \ 7529 if (
7384 self.project.isProjectSource(self.fileName): 7530 self.fileName and
7531 self.project.isProjectSource(self.fileName)
7532 ):
7385 self.project.projectPropertiesChanged.connect( 7533 self.project.projectPropertiesChanged.connect(
7386 self.__projectPropertiesChanged) 7534 self.__projectPropertiesChanged)
7387 self.setSpellingForProject() 7535 self.setSpellingForProject()
7388 7536
7389 def projectClosed(self): 7537 def projectClosed(self):
7435 def setSpellingForProject(self): 7583 def setSpellingForProject(self):
7436 """ 7584 """
7437 Public method to set the spell checking options for files belonging 7585 Public method to set the spell checking options for files belonging
7438 to the current project. 7586 to the current project.
7439 """ 7587 """
7440 if self.fileName and \ 7588 if (
7441 self.project.isOpen() and \ 7589 self.fileName and
7442 self.project.isProjectSource(self.fileName): 7590 self.project.isOpen() and
7591 self.project.isProjectSource(self.fileName)
7592 ):
7443 pwl, pel = self.project.getProjectDictionaries() 7593 pwl, pel = self.project.getProjectDictionaries()
7444 self.__setSpellingLanguage(self.project.getProjectSpellLanguage(), 7594 self.__setSpellingLanguage(self.project.getProjectSpellLanguage(),
7445 pwl=pwl, pel=pel) 7595 pwl=pwl, pel=pel)
7446 7596
7447 def setAutoSpellChecking(self): 7597 def setAutoSpellChecking(self):
7471 @return flag indicating pos is in a spell check region (boolean) 7621 @return flag indicating pos is in a spell check region (boolean)
7472 """ 7622 """
7473 if self.__spellCheckStringsOnly: 7623 if self.__spellCheckStringsOnly:
7474 style = self.styleAt(pos) 7624 style = self.styleAt(pos)
7475 if self.lexer_ is not None: 7625 if self.lexer_ is not None:
7476 return self.lexer_.isCommentStyle(style) or \ 7626 return (
7627 self.lexer_.isCommentStyle(style) or
7477 self.lexer_.isStringStyle(style) 7628 self.lexer_.isStringStyle(style)
7629 )
7478 return True 7630 return True
7479 7631
7480 @pyqtSlot(int) 7632 @pyqtSlot(int)
7481 def __spellCharAdded(self, charNumber): 7633 def __spellCharAdded(self, charNumber):
7482 """ 7634 """
7617 @return tuple indicating, if the editor is sharable, the sharing 7769 @return tuple indicating, if the editor is sharable, the sharing
7618 status, if it is inside a locally initiated shared edit session 7770 status, if it is inside a locally initiated shared edit session
7619 and if it is inside a remotely initiated shared edit session 7771 and if it is inside a remotely initiated shared edit session
7620 (boolean, boolean, boolean, boolean) 7772 (boolean, boolean, boolean, boolean)
7621 """ 7773 """
7622 return bool(self.fileName) and \ 7774 return (
7623 self.project.isOpen() and \ 7775 (bool(self.fileName) and
7624 self.project.isProjectFile(self.fileName), \ 7776 self.project.isOpen() and
7625 self.__isShared, self.__inSharedEdit, self.__inRemoteSharedEdit 7777 self.project.isProjectFile(self.fileName)),
7778 self.__isShared,
7779 self.__inSharedEdit,
7780 self.__inRemoteSharedEdit
7781 )
7626 7782
7627 def shareConnected(self, connected): 7783 def shareConnected(self, connected):
7628 """ 7784 """
7629 Public slot to handle a change of the connected state. 7785 Public slot to handle a change of the connected state.
7630 7786
7713 Public slot to handle received editor commands. 7869 Public slot to handle received editor commands.
7714 7870
7715 @param command command string (string) 7871 @param command command string (string)
7716 """ 7872 """
7717 if self.__isShared: 7873 if self.__isShared:
7718 if self.__isSyncing and \ 7874 if (
7719 not command.startswith(Editor.SyncToken + Editor.Separator): 7875 self.__isSyncing and
7876 not command.startswith(Editor.SyncToken + Editor.Separator)
7877 ):
7720 self.__receivedWhileSyncing.append(command) 7878 self.__receivedWhileSyncing.append(command)
7721 else: 7879 else:
7722 self.__dispatchCommand(command) 7880 self.__dispatchCommand(command)
7723 7881
7724 def __dispatchCommand(self, command): 7882 def __dispatchCommand(self, command):
7935 8093
7936 from .SortOptionsDialog import SortOptionsDialog 8094 from .SortOptionsDialog import SortOptionsDialog
7937 dlg = SortOptionsDialog() 8095 dlg = SortOptionsDialog()
7938 if dlg.exec_() == QDialog.Accepted: 8096 if dlg.exec_() == QDialog.Accepted:
7939 ascending, alnum, caseSensitive = dlg.getData() 8097 ascending, alnum, caseSensitive = dlg.getData()
7940 origStartLine, origStartIndex, origEndLine, origEndIndex = \ 8098 origStartLine, origStartIndex, origEndLine, origEndIndex = (
7941 self.getRectangularSelection() 8099 self.getRectangularSelection()
8100 )
7942 # convert to upper-left to lower-right 8101 # convert to upper-left to lower-right
7943 startLine = min(origStartLine, origEndLine) 8102 startLine = min(origStartLine, origEndLine)
7944 startIndex = min(origStartIndex, origEndIndex) 8103 startIndex = min(origStartIndex, origEndIndex)
7945 endLine = max(origStartLine, origEndLine) 8104 endLine = max(origStartLine, origEndLine)
7946 endIndex = max(origStartIndex, origEndIndex) 8105 endIndex = max(origStartIndex, origEndIndex)
8017 key = (int(modifiers), int(button)) 8176 key = (int(modifiers), int(button))
8018 8177
8019 self.vm.eventFilter(self, evt) 8178 self.vm.eventFilter(self, evt)
8020 super(Editor, self).mouseReleaseEvent(evt) 8179 super(Editor, self).mouseReleaseEvent(evt)
8021 8180
8022 if button != Qt.NoButton and \ 8181 if (
8023 Preferences.getEditor("MouseClickHandlersEnabled") and \ 8182 button != Qt.NoButton and
8024 key in self.__mouseClickHandlers: 8183 Preferences.getEditor("MouseClickHandlersEnabled") and
8184 key in self.__mouseClickHandlers
8185 ):
8025 evt.accept() 8186 evt.accept()
8026 self.__mouseClickHandlers[key][1](self) 8187 self.__mouseClickHandlers[key][1](self)
8027 8188
8028 def setMouseClickHandler(self, name, modifiers, button, function): 8189 def setMouseClickHandler(self, name, modifiers, button, function):
8029 """ 8190 """
8198 8359
8199 if not config: 8360 if not config:
8200 if nodefault: 8361 if nodefault:
8201 return None 8362 return None
8202 else: 8363 else:
8203 return Preferences.getEditor(option) 8364 value = self.__getOverrideValue(option)
8365 if value is None:
8366 # no override
8367 value = Preferences.getEditor(option)
8368 return value
8204 8369
8205 try: 8370 try:
8206 if option == "EOLMode": 8371 if option == "EOLMode":
8207 value = config["end_of_line"] 8372 value = config["end_of_line"]
8208 if value == "lf": 8373 if value == "lf":
8232 except KeyError: 8397 except KeyError:
8233 value = None 8398 value = None
8234 8399
8235 if value is None and not nodefault: 8400 if value is None and not nodefault:
8236 # use Preferences in case of error 8401 # use Preferences in case of error
8237 value = Preferences.getEditor(option) 8402 value = self.__getOverrideValue(option)
8403 if value is None:
8404 # no override
8405 value = Preferences.getEditor(option)
8238 8406
8239 return value 8407 return value
8240 8408
8241 def getEditorConfig(self, option): 8409 def getEditorConfig(self, option):
8242 """ 8410 """
8247 @return value of requested setting 8415 @return value of requested setting
8248 @rtype any 8416 @rtype any
8249 """ 8417 """
8250 return self.__getEditorConfig(option) 8418 return self.__getEditorConfig(option)
8251 8419
8420 def __getOverrideValue(self, option):
8421 """
8422 Private method to get an override value for the current file type.
8423
8424 @param option Preferences option key
8425 @type str
8426 @return override value; None in case nothing is defined
8427 @rtype any
8428 """
8429 if option in ("TabWidth", "IndentWidth"):
8430 overrides = Preferences.getEditor("TabIndentOverride")
8431 if self.filetype in overrides:
8432 if option == "TabWidth":
8433 return overrides[self.filetype][0]
8434 elif option == "IndentWidth":
8435 return overrides[self.filetype][1]
8436
8437 return None
8438
8252 def mouseDoubleClickEvent(self, evt): 8439 def mouseDoubleClickEvent(self, evt):
8253 """ 8440 """
8254 Protected method to handle mouse double click events. 8441 Protected method to handle mouse double click events.
8255 8442
8256 @param evt reference to the mouse event 8443 @param evt reference to the mouse event

eric ide

mercurial