29 Qt, |
30 Qt, |
30 QTimer, |
31 QTimer, |
31 pyqtSignal, |
32 pyqtSignal, |
32 pyqtSlot, |
33 pyqtSlot, |
33 ) |
34 ) |
34 from PyQt6.QtGui import QAction, QActionGroup, QFont, QPainter, QPalette, QPixmap |
35 from PyQt6.QtGui import ( |
|
36 QAction, |
|
37 QActionGroup, |
|
38 QCursor, |
|
39 QFont, |
|
40 QPainter, |
|
41 QPalette, |
|
42 QPixmap, |
|
43 ) |
35 from PyQt6.QtPrintSupport import ( |
44 from PyQt6.QtPrintSupport import ( |
36 QAbstractPrintDialog, |
45 QAbstractPrintDialog, |
37 QPrintDialog, |
46 QPrintDialog, |
38 QPrinter, |
47 QPrinter, |
39 QPrintPreviewDialog, |
48 QPrintPreviewDialog, |
40 ) |
49 ) |
41 from PyQt6.QtWidgets import QApplication, QDialog, QInputDialog, QLineEdit, QMenu |
50 from PyQt6.QtWidgets import ( |
|
51 QApplication, |
|
52 QDialog, |
|
53 QInputDialog, |
|
54 QLineEdit, |
|
55 QMenu, |
|
56 QToolTip, |
|
57 ) |
42 |
58 |
43 from eric7 import Globals, Preferences, Utilities |
59 from eric7 import Globals, Preferences, Utilities |
44 from eric7.CodeFormatting.BlackFormattingAction import BlackFormattingAction |
60 from eric7.CodeFormatting.BlackFormattingAction import BlackFormattingAction |
45 from eric7.CodeFormatting.BlackUtilities import aboutBlack |
61 from eric7.CodeFormatting.BlackUtilities import aboutBlack |
46 from eric7.CodeFormatting.IsortFormattingAction import IsortFormattingAction |
62 from eric7.CodeFormatting.IsortFormattingAction import IsortFormattingAction |
144 lastEditPositionAvailable = pyqtSignal() |
194 lastEditPositionAvailable = pyqtSignal() |
145 refreshed = pyqtSignal() |
195 refreshed = pyqtSignal() |
146 settingsRead = pyqtSignal() |
196 settingsRead = pyqtSignal() |
147 mouseDoubleClick = pyqtSignal(QPoint, Qt.MouseButton) |
197 mouseDoubleClick = pyqtSignal(QPoint, Qt.MouseButton) |
148 |
198 |
149 # TODO: convert to an enum.Enum |
|
150 WarningCode = 1 |
|
151 WarningPython = 2 |
|
152 WarningStyle = 3 |
|
153 WarningInfo = 4 |
|
154 WarningError = 5 |
|
155 |
|
156 # TODO: convert to an enum.IntEnum (also in Assistant plugin) |
|
157 # Autocompletion icon definitions |
|
158 ClassID = 1 |
|
159 ClassProtectedID = 2 |
|
160 ClassPrivateID = 3 |
|
161 MethodID = 4 |
|
162 MethodProtectedID = 5 |
|
163 MethodPrivateID = 6 |
|
164 AttributeID = 7 |
|
165 AttributeProtectedID = 8 |
|
166 AttributePrivateID = 9 |
|
167 EnumID = 10 |
|
168 KeywordsID = 11 |
|
169 ModuleID = 12 |
|
170 |
|
171 FromDocumentID = 99 |
|
172 |
|
173 TemplateImageID = 100 |
|
174 |
|
175 # Cooperation related definitions |
199 # Cooperation related definitions |
176 Separator = "@@@" |
200 Separator = "@@@" |
177 |
201 |
178 StartEditToken = "START_EDIT" |
202 StartEditToken = "START_EDIT" |
179 EndEditToken = "END_EDIT" |
203 EndEditToken = "END_EDIT" |
655 Private method to register images for autocompletion lists. |
684 Private method to register images for autocompletion lists. |
656 """ |
685 """ |
657 # finale size of the completion images |
686 # finale size of the completion images |
658 imageSize = QSize(22, 22) |
687 imageSize = QSize(22, 22) |
659 |
688 |
660 self.registerImage(self.ClassID, EricPixmapCache.getPixmap("class", imageSize)) |
|
661 self.registerImage( |
689 self.registerImage( |
662 self.ClassProtectedID, |
690 EditorIconId.Class, |
|
691 EricPixmapCache.getPixmap("class", imageSize), |
|
692 ) |
|
693 self.registerImage( |
|
694 EditorIconId.ClassProtected, |
663 EricPixmapCache.getPixmap("class_protected", imageSize), |
695 EricPixmapCache.getPixmap("class_protected", imageSize), |
664 ) |
696 ) |
665 self.registerImage( |
697 self.registerImage( |
666 self.ClassPrivateID, EricPixmapCache.getPixmap("class_private", imageSize) |
698 EditorIconId.ClassPrivate, |
|
699 EricPixmapCache.getPixmap("class_private", imageSize), |
667 ) |
700 ) |
668 self.registerImage( |
701 self.registerImage( |
669 self.MethodID, EricPixmapCache.getPixmap("method", imageSize) |
702 EditorIconId.Method, |
|
703 EricPixmapCache.getPixmap("method", imageSize), |
670 ) |
704 ) |
671 self.registerImage( |
705 self.registerImage( |
672 self.MethodProtectedID, |
706 EditorIconId.MethodProtected, |
673 EricPixmapCache.getPixmap("method_protected", imageSize), |
707 EricPixmapCache.getPixmap("method_protected", imageSize), |
674 ) |
708 ) |
675 self.registerImage( |
709 self.registerImage( |
676 self.MethodPrivateID, EricPixmapCache.getPixmap("method_private", imageSize) |
710 EditorIconId.MethodPrivate, |
|
711 EricPixmapCache.getPixmap("method_private", imageSize), |
677 ) |
712 ) |
678 self.registerImage( |
713 self.registerImage( |
679 self.AttributeID, EricPixmapCache.getPixmap("attribute", imageSize) |
714 EditorIconId.Attribute, |
|
715 EricPixmapCache.getPixmap("attribute", imageSize), |
680 ) |
716 ) |
681 self.registerImage( |
717 self.registerImage( |
682 self.AttributeProtectedID, |
718 EditorIconId.AttributeProtected, |
683 EricPixmapCache.getPixmap("attribute_protected", imageSize), |
719 EricPixmapCache.getPixmap("attribute_protected", imageSize), |
684 ) |
720 ) |
685 self.registerImage( |
721 self.registerImage( |
686 self.AttributePrivateID, |
722 EditorIconId.AttributePrivate, |
687 EricPixmapCache.getPixmap("attribute_private", imageSize), |
723 EricPixmapCache.getPixmap("attribute_private", imageSize), |
688 ) |
724 ) |
689 self.registerImage(self.EnumID, EricPixmapCache.getPixmap("enum", imageSize)) |
|
690 self.registerImage( |
725 self.registerImage( |
691 self.KeywordsID, EricPixmapCache.getPixmap("keywords", imageSize) |
726 EditorIconId.Enum, |
|
727 EricPixmapCache.getPixmap("enum", imageSize), |
692 ) |
728 ) |
693 self.registerImage( |
729 self.registerImage( |
694 self.ModuleID, EricPixmapCache.getPixmap("module", imageSize) |
730 EditorIconId.Keywords, |
695 ) |
731 EricPixmapCache.getPixmap("keywords", imageSize), |
696 |
732 ) |
697 self.registerImage( |
733 self.registerImage( |
698 self.FromDocumentID, EricPixmapCache.getPixmap("editor", imageSize) |
734 EditorIconId.Module, |
|
735 EricPixmapCache.getPixmap("module", imageSize), |
699 ) |
736 ) |
700 |
737 |
701 self.registerImage( |
738 self.registerImage( |
702 self.TemplateImageID, EricPixmapCache.getPixmap("templateViewer", imageSize) |
739 EditorIconId.FromDocument, |
|
740 EricPixmapCache.getPixmap("editor", imageSize), |
|
741 ) |
|
742 |
|
743 self.registerImage( |
|
744 EditorIconId.TemplateImage, |
|
745 EricPixmapCache.getPixmap("templateViewer", imageSize), |
703 ) |
746 ) |
704 |
747 |
705 def addClone(self, editor): |
748 def addClone(self, editor): |
706 """ |
749 """ |
707 Public method to add a clone to our list. |
750 Public method to add a clone to our list. |
3508 self.lastModified = pathlib.Path(fn).stat().st_mtime |
3551 self.lastModified = pathlib.Path(fn).stat().st_mtime |
3509 |
3552 |
3510 @pyqtSlot() |
3553 @pyqtSlot() |
3511 def __convertTabs(self): |
3554 def __convertTabs(self): |
3512 """ |
3555 """ |
3513 Private slot to convert tabulators to spaces. |
3556 Private slot to automatically convert tabulators to spaces upon loading. |
3514 """ |
3557 """ |
3515 if ( |
3558 if ( |
3516 (not self.__getEditorConfig("TabForIndentation")) |
3559 (not self.__getEditorConfig("TabForIndentation")) |
3517 and Preferences.getEditor("ConvertTabsOnLoad") |
3560 and Preferences.getEditor("ConvertTabsOnLoad") |
3518 and not (self.lexer_ and self.lexer_.alwaysKeepTabs()) |
3561 and not (self.lexer_ and self.lexer_.alwaysKeepTabs()) |
3519 ): |
3562 ): |
3520 txt = self.text() |
3563 self.expandTabs() |
3521 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth")) |
3564 |
3522 if txtExpanded != txt: |
3565 @pyqtSlot() |
3523 self.beginUndoAction() |
3566 def expandTabs(self): |
3524 self.setText(txt) |
3567 """ |
3525 self.endUndoAction() |
3568 Public slot to expand tabulators to spaces. |
3526 |
3569 """ |
3527 self.setModified(True) |
3570 txt = self.text() |
|
3571 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth")) |
|
3572 if txtExpanded != txt: |
|
3573 self.beginUndoAction() |
|
3574 self.setText(txtExpanded) |
|
3575 self.endUndoAction() |
|
3576 |
|
3577 self.setModified(True) |
3528 |
3578 |
3529 def __removeTrailingWhitespace(self): |
3579 def __removeTrailingWhitespace(self): |
3530 """ |
3580 """ |
3531 Private method to remove trailing whitespace. |
3581 Private method to remove trailing whitespace. |
3532 """ |
3582 """ |
3926 elif margin == self.__indicMargin: |
3976 elif margin == self.__indicMargin: |
3927 if self.markersAtLine(line) & (1 << self.syntaxerror): |
3977 if self.markersAtLine(line) & (1 << self.syntaxerror): |
3928 self.__showSyntaxError(line) |
3978 self.__showSyntaxError(line) |
3929 elif self.markersAtLine(line) & (1 << self.warning): |
3979 elif self.markersAtLine(line) & (1 << self.warning): |
3930 self.__showWarning(line) |
3980 self.__showWarning(line) |
|
3981 |
|
3982 @pyqtSlot(int, int, int) |
|
3983 def __marginHoverStart(self, pos, x, y): |
|
3984 """ |
|
3985 Private slot showing the text of a syntax error or a warning marker. |
|
3986 |
|
3987 @param pos mouse position into the document |
|
3988 @type int |
|
3989 @param x x-value of mouse screen position |
|
3990 @type int |
|
3991 @param y y-value of mouse screen position |
|
3992 @type int |
|
3993 """ |
|
3994 margin = self.__marginNumber(x) |
|
3995 if margin == self.__indicMargin: |
|
3996 # determine width of all margins; needed to calculate document line |
|
3997 width = 0 |
|
3998 for margin in range(5): |
|
3999 width += self.marginWidth(margin) |
|
4000 |
|
4001 message = "" |
|
4002 line = self.lineIndexFromPoint(QPoint(width + 1, y))[0] |
|
4003 if self.markersAtLine(line) & (1 << self.syntaxerror): |
|
4004 for handle in self.syntaxerrors: |
|
4005 if self.markerLine(handle) == line: |
|
4006 message = "\n".join([e[0] for e in self.syntaxerrors[handle]]) |
|
4007 break |
|
4008 elif self.markersAtLine(line) & (1 << self.warning): |
|
4009 for handle in self._warnings: |
|
4010 if self.markerLine(handle) == line: |
|
4011 message = "\n".join([w[0] for w in self._warnings[handle]]) |
|
4012 break |
|
4013 |
|
4014 if message: |
|
4015 QToolTip.showText(QCursor.pos(), message) |
|
4016 |
|
4017 @pyqtSlot() |
|
4018 def __marginHoverEnd(self): |
|
4019 """ |
|
4020 Private slot cancelling the display of syntax error or a warning marker text. |
|
4021 """ |
|
4022 QToolTip.hideText() |
3931 |
4023 |
3932 @pyqtSlot() |
4024 @pyqtSlot() |
3933 def handleMonospacedEnable(self): |
4025 def handleMonospacedEnable(self): |
3934 """ |
4026 """ |
3935 Public slot to handle the Use Monospaced Font context menu entry. |
4027 Public slot to handle the Use Monospaced Font context menu entry. |
6737 if error: |
6827 if error: |
6738 _fn, lineno, col, code, msg = error |
6828 _fn, lineno, col, code, msg = error |
6739 self.toggleSyntaxError(lineno, col, True, msg) |
6829 self.toggleSyntaxError(lineno, col, True, msg) |
6740 |
6830 |
6741 for _fn, lineno, col, _code, msg in problems.get("py_warnings", []): |
6831 for _fn, lineno, col, _code, msg in problems.get("py_warnings", []): |
6742 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningPython) |
6832 self.toggleWarning( |
|
6833 lineno, col, True, msg, warningType=EditorWarningKind.Python |
|
6834 ) |
6743 |
6835 |
6744 for _fn, lineno, col, _code, msg in problems.get("warnings", []): |
6836 for _fn, lineno, col, _code, msg in problems.get("warnings", []): |
6745 self.toggleWarning(lineno, col, True, msg, warningType=Editor.WarningCode) |
6837 self.toggleWarning( |
|
6838 lineno, col, True, msg, warningType=EditorWarningKind.Code |
|
6839 ) |
6746 |
6840 |
6747 self.updateVerticalScrollBar() |
6841 self.updateVerticalScrollBar() |
6748 |
6842 |
6749 @pyqtSlot() |
6843 @pyqtSlot() |
6750 def __initOnlineSyntaxCheck(self): |
6844 def __initOnlineSyntaxCheck(self): |
7316 @pyqtSlot() |
7415 @pyqtSlot() |
7317 def clearFlakesWarnings(self): |
7416 def clearFlakesWarnings(self): |
7318 """ |
7417 """ |
7319 Public slot to clear all pyflakes warnings. |
7418 Public slot to clear all pyflakes warnings. |
7320 """ |
7419 """ |
7321 self.__clearTypedWarning(Editor.WarningCode) |
7420 self.__clearTypedWarning(EditorWarningKind.Code) |
7322 self.__clearTypedWarning(Editor.WarningPython) |
7421 self.__clearTypedWarning(EditorWarningKind.Python) |
7323 |
7422 |
7324 @pyqtSlot() |
7423 @pyqtSlot() |
7325 def clearStyleWarnings(self): |
7424 def clearStyleWarnings(self): |
7326 """ |
7425 """ |
7327 Public slot to clear all style warnings. |
7426 Public slot to clear all style warnings. |
7328 """ |
7427 """ |
7329 self.__clearTypedWarning(Editor.WarningStyle) |
7428 self.__clearTypedWarning(EditorWarningKind.Style) |
7330 |
7429 |
7331 @pyqtSlot() |
7430 @pyqtSlot() |
7332 def clearInfoWarnings(self): |
7431 def clearInfoWarnings(self): |
7333 """ |
7432 """ |
7334 Public slot to clear all info warnings. |
7433 Public slot to clear all info warnings. |
7335 """ |
7434 """ |
7336 self.__clearTypedWarning(Editor.WarningInfo) |
7435 self.__clearTypedWarning(EditorWarningKind.Info) |
7337 |
7436 |
7338 @pyqtSlot() |
7437 @pyqtSlot() |
7339 def clearErrorWarnings(self): |
7438 def clearErrorWarnings(self): |
7340 """ |
7439 """ |
7341 Public slot to clear all error warnings. |
7440 Public slot to clear all error warnings. |
7342 """ |
7441 """ |
7343 self.__clearTypedWarning(Editor.WarningError) |
7442 self.__clearTypedWarning(EditorWarningKind.Error) |
7344 |
7443 |
7345 @pyqtSlot() |
7444 @pyqtSlot() |
7346 def clearCodeWarnings(self): |
7445 def clearCodeWarnings(self): |
7347 """ |
7446 """ |
7348 Public slot to clear all code warnings. |
7447 Public slot to clear all code warnings. |
7349 """ |
7448 """ |
7350 self.__clearTypedWarning(Editor.WarningCode) |
7449 self.__clearTypedWarning(EditorWarningKind.Code) |
7351 |
7450 |
7352 def __clearTypedWarning(self, warningKind): |
7451 def __clearTypedWarning(self, warningKind): |
7353 """ |
7452 """ |
7354 Private method to clear warnings of a specific kind. |
7453 Private method to clear warnings of a specific kind. |
7355 |
7454 |
7356 @param warningKind kind of warning to clear (Editor.WarningCode, |
7455 @param warningKind kind of warning to clear |
7357 Editor.WarningPython, Editor.WarningStyle) |
7456 @type EditorWarningKind |
7358 @type int |
|
7359 """ |
7457 """ |
7360 for handle in list(self._warnings): |
7458 for handle in list(self._warnings): |
7361 issues = [] |
7459 issues = [] |
7362 for msg, warningType in self._warnings[handle]: |
7460 for msg, warningType in self._warnings[handle]: |
7363 if warningType == warningKind: |
7461 if warningType == warningKind: |
7485 |
7583 |
7486 # step 1: do warnings |
7584 # step 1: do warnings |
7487 for handle in self._warnings: |
7585 for handle in self._warnings: |
7488 if self.markerLine(handle) == line: |
7586 if self.markerLine(handle) == line: |
7489 for msg, warningType in self._warnings[handle]: |
7587 for msg, warningType in self._warnings[handle]: |
7490 if warningType == Editor.WarningInfo: |
7588 if warningType == EditorWarningKind.Info: |
7491 infoAnnotations.append(self.tr("Info: {0}").format(msg)) |
7589 infoAnnotations.append(self.tr("Info: {0}").format(msg)) |
7492 elif warningType == Editor.WarningError: |
7590 elif warningType == EditorWarningKind.Error: |
7493 errorAnnotations.append(self.tr("Error: {0}").format(msg)) |
7591 errorAnnotations.append(self.tr("Error: {0}").format(msg)) |
7494 elif warningType == Editor.WarningStyle: |
7592 elif warningType == EditorWarningKind.Style: |
7495 styleAnnotations.append(self.tr("Style: {0}").format(msg)) |
7593 styleAnnotations.append(self.tr("Style: {0}").format(msg)) |
7496 elif warningType == Editor.WarningPython: |
7594 elif warningType == EditorWarningKind.Python: |
7497 warningAnnotations.append(msg) |
7595 warningAnnotations.append(msg) |
7498 else: |
7596 else: |
7499 warningAnnotations.append( |
7597 warningAnnotations.append( |
7500 self.tr("Warning: {0}").format(msg) |
7598 self.tr("Warning: {0}").format(msg) |
7501 ) |
7599 ) |