--- a/QScintilla/Editor.py Sun Mar 30 22:00:14 2014 +0200 +++ b/QScintilla/Editor.py Thu Apr 03 23:05:31 2014 +0200 @@ -28,6 +28,7 @@ from E5Gui import E5FileDialog, E5MessageBox from .QsciScintillaCompat import QsciScintillaCompat, QSCINTILLA_VERSION +from .EditorMarkerMap import EditorMarkerMap import Preferences import Utilities @@ -149,7 +150,6 @@ @exception IOError raised to indicate an issue accessing the file """ super(Editor, self).__init__() -## self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_KeyCompression) self.setUtf8(True) @@ -299,6 +299,8 @@ self.changeMarkersMask = (1 << self.__changeMarkerSaved) | \ (1 << self.__changeMarkerUnsaved) + self.__markerMap = EditorMarkerMap(self) + # configure the margins self.__setMarginsDisplay() self.linesChanged.connect(self.__resizeLinenoMargin) @@ -323,10 +325,10 @@ Preferences.getEditor("WarnFilesize"): res = E5MessageBox.yesNo( self, - self.trUtf8("Open File"), - self.trUtf8("""<p>The size of the file <b>{0}</b>""" - """ is <b>{1} KB</b>.""" - """ Do you really want to load it?</p>""") + self.tr("Open File"), + self.tr("""<p>The size of the file <b>{0}</b>""" + """ is <b>{1} KB</b>.""" + """ Do you really want to load it?</p>""") .format(self.fileName, QFileInfo(self.fileName).size() // 1024), icon=E5MessageBox.Warning) @@ -374,7 +376,7 @@ self.__updateReadOnly(True) - self.setWhatsThis(self.trUtf8( + self.setWhatsThis(self.tr( """<b>A Source Editor Window</b>""" """<p>This window is used to display and edit a source file.""" """ You can open as many of these as you like. The name of the""" @@ -450,6 +452,9 @@ self.__projectPropertiesChanged) self.grabGesture(Qt.PinchGesture) + + self.SCN_ZOOM.connect(self.__markerMap.update) + self.__markerMap.update() def __registerImages(self): """ @@ -541,6 +546,8 @@ bindName = "dummy.d" elif self.filetype == "Properties": bindName = "dummy.ini" + elif self.filetype == "JavaScript": + bindName = "dummy.js" # #! marker detection if not bindName and line0.startswith("#!"): @@ -628,86 +635,86 @@ self.menuActs["Undo"] = self.menu.addAction( UI.PixmapCache.getIcon("editUndo.png"), - self.trUtf8('Undo'), self.undo) + self.tr('Undo'), self.undo) self.menuActs["Redo"] = self.menu.addAction( UI.PixmapCache.getIcon("editRedo.png"), - self.trUtf8('Redo'), self.redo) + self.tr('Redo'), self.redo) self.menuActs["Revert"] = self.menu.addAction( - self.trUtf8("Revert to last saved state"), + self.tr("Revert to last saved state"), self.revertToUnmodified) self.menu.addSeparator() self.menuActs["Cut"] = self.menu.addAction( UI.PixmapCache.getIcon("editCut.png"), - self.trUtf8('Cut'), self.cut) + self.tr('Cut'), self.cut) self.menuActs["Copy"] = self.menu.addAction( UI.PixmapCache.getIcon("editCopy.png"), - self.trUtf8('Copy'), self.copy) + self.tr('Copy'), self.copy) self.menu.addAction( UI.PixmapCache.getIcon("editPaste.png"), - self.trUtf8('Paste'), self.paste) + self.tr('Paste'), self.paste) if not self.miniMenu: self.menu.addSeparator() self.menu.addAction( UI.PixmapCache.getIcon("editIndent.png"), - self.trUtf8('Indent'), self.indentLineOrSelection) + self.tr('Indent'), self.indentLineOrSelection) self.menu.addAction( UI.PixmapCache.getIcon("editUnindent.png"), - self.trUtf8('Unindent'), self.unindentLineOrSelection) + self.tr('Unindent'), self.unindentLineOrSelection) self.menuActs["Comment"] = self.menu.addAction( UI.PixmapCache.getIcon("editComment.png"), - self.trUtf8('Comment'), self.commentLineOrSelection) + self.tr('Comment'), self.commentLineOrSelection) self.menuActs["Uncomment"] = self.menu.addAction( UI.PixmapCache.getIcon("editUncomment.png"), - self.trUtf8('Uncomment'), self.uncommentLineOrSelection) + self.tr('Uncomment'), self.uncommentLineOrSelection) self.menuActs["StreamComment"] = self.menu.addAction( - self.trUtf8('Stream Comment'), + self.tr('Stream Comment'), self.streamCommentLineOrSelection) self.menuActs["BoxComment"] = self.menu.addAction( - self.trUtf8('Box Comment'), + self.tr('Box Comment'), self.boxCommentLineOrSelection) self.menu.addSeparator() self.menu.addAction( - self.trUtf8('Select to brace'), self.selectToMatchingBrace) - self.menu.addAction(self.trUtf8('Select all'), self.__selectAll) + self.tr('Select to brace'), self.selectToMatchingBrace) + self.menu.addAction(self.tr('Select all'), self.__selectAll) self.menu.addAction( - self.trUtf8('Deselect all'), self.__deselectAll) + self.tr('Deselect all'), self.__deselectAll) self.menu.addSeparator() self.menuActs["SpellCheck"] = self.menu.addAction( UI.PixmapCache.getIcon("spellchecking.png"), - self.trUtf8('Check spelling...'), self.checkSpelling) + self.tr('Check spelling...'), self.checkSpelling) self.menuActs["SpellCheckSelection"] = self.menu.addAction( UI.PixmapCache.getIcon("spellchecking.png"), - self.trUtf8('Check spelling of selection...'), + self.tr('Check spelling of selection...'), self.__checkSpellingSelection) self.menuActs["SpellCheckRemove"] = self.menu.addAction( - self.trUtf8("Remove from dictionary"), + self.tr("Remove from dictionary"), self.__removeFromSpellingDictionary) self.menu.addSeparator() self.menu.addAction( - self.trUtf8('Shorten empty lines'), self.shortenEmptyLines) + self.tr('Shorten empty lines'), self.shortenEmptyLines) self.menu.addSeparator() self.menuActs["Languages"] = self.menu.addMenu(self.languagesMenu) self.menuActs["Encodings"] = self.menu.addMenu(self.encodingsMenu) self.menuActs["Eol"] = self.menu.addMenu(self.eolMenu) self.menu.addSeparator() self.menuActs["MonospacedFont"] = self.menu.addAction( - self.trUtf8("Use Monospaced Font"), + self.tr("Use Monospaced Font"), self.handleMonospacedEnable) self.menuActs["MonospacedFont"].setCheckable(True) self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) self.menuActs["AutosaveEnable"] = self.menu.addAction( - self.trUtf8("Autosave enabled"), self.__autosaveEnable) + self.tr("Autosave enabled"), self.__autosaveEnable) self.menuActs["AutosaveEnable"].setCheckable(True) self.menuActs["AutosaveEnable"].setChecked(self.autosaveEnabled) self.menuActs["TypingAidsEnabled"] = self.menu.addAction( - self.trUtf8("Typing aids enabled"), self.__toggleTypingAids) + self.tr("Typing aids enabled"), self.__toggleTypingAids) self.menuActs["TypingAidsEnabled"].setCheckable(True) self.menuActs["TypingAidsEnabled"].setEnabled( self.completer is not None) self.menuActs["TypingAidsEnabled"].setChecked( self.completer is not None and self.completer.isEnabled()) self.menuActs["AutoCompletionEnable"] = self.menu.addAction( - self.trUtf8("Autocompletion enabled"), + self.tr("Autocompletion enabled"), self.__toggleAutoCompletionEnable) self.menuActs["AutoCompletionEnable"].setCheckable(True) self.menuActs["AutoCompletionEnable"].setChecked( @@ -728,35 +735,37 @@ self.menu.addSeparator() self.menu.addAction( UI.PixmapCache.getIcon("documentNewView.png"), - self.trUtf8('New Document View'), self.__newView) + self.tr('New Document View'), self.__newView) self.menuActs["NewSplit"] = self.menu.addAction( UI.PixmapCache.getIcon("splitVertical.png"), - self.trUtf8('New Document View (with new split)'), + self.tr('New Document View (with new split)'), self.__newViewNewSplit) self.menuActs["NewSplit"].setEnabled(self.vm.canSplit()) self.menu.addAction( UI.PixmapCache.getIcon("close.png"), - self.trUtf8('Close'), self.__contextClose) + self.tr('Close'), self.__contextClose) self.menu.addSeparator() + self.reopenEncodingMenu = self.__initContextMenuReopenWithEncoding() + self.menuActs["Reopen"] = self.menu.addMenu(self.reopenEncodingMenu) self.menuActs["Save"] = self.menu.addAction( UI.PixmapCache.getIcon("fileSave.png"), - self.trUtf8('Save'), self.__contextSave) + self.tr('Save'), self.__contextSave) self.menu.addAction( UI.PixmapCache.getIcon("fileSaveAs.png"), - self.trUtf8('Save As...'), self.__contextSaveAs) + self.tr('Save As...'), self.__contextSaveAs) if not self.miniMenu: self.menu.addMenu(self.exportersMenu) self.menu.addSeparator() self.menuActs["OpenRejections"] = self.menu.addAction( - self.trUtf8("Open 'rejection' file"), + self.tr("Open 'rejection' file"), self.__contextOpenRejections) self.menu.addSeparator() self.menu.addAction( UI.PixmapCache.getIcon("printPreview.png"), - self.trUtf8("Print Preview"), self.printPreviewFile) + self.tr("Print Preview"), self.printPreviewFile) self.menu.addAction( UI.PixmapCache.getIcon("print.png"), - self.trUtf8('Print'), self.printFile) + self.tr('Print'), self.printFile) else: self.menuActs["OpenRejections"] = None @@ -775,20 +784,20 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Autocomplete')) + menu = QMenu(self.tr('Autocomplete')) self.menuActs["acDynamic"] = menu.addAction( - self.trUtf8('dynamic'), self.autoComplete) + self.tr('dynamic'), self.autoComplete) menu.addSeparator() menu.addAction( - self.trUtf8('from Document'), self.autoCompleteFromDocument) + self.tr('from Document'), self.autoCompleteFromDocument) self.menuActs["acAPI"] = menu.addAction( - self.trUtf8('from APIs'), self.autoCompleteFromAPIs) + self.tr('from APIs'), self.autoCompleteFromAPIs) self.menuActs["acAPIDocument"] = menu.addAction( - self.trUtf8('from Document and APIs'), self.autoCompleteFromAll) + self.tr('from Document and APIs'), self.autoCompleteFromAll) menu.addSeparator() self.menuActs["calltip"] = menu.addAction( - self.trUtf8('Calltip'), self.callTip) + self.tr('Calltip'), self.callTip) menu.aboutToShow.connect(self.__showContextMenuAutocompletion) @@ -800,7 +809,7 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Check')) + menu = QMenu(self.tr('Check')) menu.aboutToShow.connect(self.__showContextMenuChecks) return menu @@ -810,7 +819,7 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Tools')) + menu = QMenu(self.tr('Tools')) menu.aboutToShow.connect(self.__showContextMenuTools) return menu @@ -820,19 +829,19 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Show')) - - menu.addAction(self.trUtf8('Code metrics...'), self.__showCodeMetrics) + menu = QMenu(self.tr('Show')) + + menu.addAction(self.tr('Code metrics...'), self.__showCodeMetrics) self.coverageMenuAct = menu.addAction( - self.trUtf8('Code coverage...'), self.__showCodeCoverage) + self.tr('Code coverage...'), self.__showCodeCoverage) self.coverageShowAnnotationMenuAct = menu.addAction( - self.trUtf8('Show code coverage annotations'), + self.tr('Show code coverage annotations'), self.codeCoverageShowAnnotations) self.coverageHideAnnotationMenuAct = menu.addAction( - self.trUtf8('Hide code coverage annotations'), + self.tr('Hide code coverage annotations'), self.__codeCoverageHideAnnotations) self.profileMenuAct = menu.addAction( - self.trUtf8('Profile data...'), self.__showProfileData) + self.tr('Profile data...'), self.__showProfileData) menu.aboutToShow.connect(self.__showContextMenuShow) @@ -844,21 +853,21 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Diagrams')) + menu = QMenu(self.tr('Diagrams')) menu.addAction( - self.trUtf8('Class Diagram...'), self.__showClassDiagram) + self.tr('Class Diagram...'), self.__showClassDiagram) menu.addAction( - self.trUtf8('Package Diagram...'), self.__showPackageDiagram) + self.tr('Package Diagram...'), self.__showPackageDiagram) menu.addAction( - self.trUtf8('Imports Diagram...'), self.__showImportsDiagram) + self.tr('Imports Diagram...'), self.__showImportsDiagram) self.applicationDiagramMenuAct = menu.addAction( - self.trUtf8('Application Diagram...'), + self.tr('Application Diagram...'), self.__showApplicationDiagram) menu.addSeparator() menu.addAction( UI.PixmapCache.getIcon("open.png"), - self.trUtf8("Load Diagram..."), self.__loadDiagram) + self.tr("Load Diagram..."), self.__loadDiagram) menu.aboutToShow.connect(self.__showContextMenuGraphics) @@ -870,10 +879,10 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8("Languages")) + menu = QMenu(self.tr("Languages")) self.languagesActGrp = QActionGroup(self) - self.noLanguageAct = menu.addAction(self.trUtf8("No Language")) + self.noLanguageAct = menu.addAction(self.tr("No Language")) self.noLanguageAct.setCheckable(True) self.noLanguageAct.setData("None") self.languagesActGrp.addAction(self.noLanguageAct) @@ -896,11 +905,11 @@ self.languagesActGrp.addAction(act) menu.addSeparator() - self.pygmentsAct = menu.addAction(self.trUtf8("Guessed")) + self.pygmentsAct = menu.addAction(self.tr("Guessed")) self.pygmentsAct.setCheckable(True) self.pygmentsAct.setData("Guessed") self.languagesActGrp.addAction(self.pygmentsAct) - self.pygmentsSelAct = menu.addAction(self.trUtf8("Alternatives")) + self.pygmentsSelAct = menu.addAction(self.tr("Alternatives")) self.pygmentsSelAct.setData("Alternatives") menu.triggered.connect(self.__languageMenuTriggered) @@ -916,7 +925,7 @@ """ self.supportedEncodings = {} - menu = QMenu(self.trUtf8("Encodings")) + menu = QMenu(self.tr("Encodings")) self.encodingsActGrp = QActionGroup(self) @@ -932,6 +941,23 @@ return menu + def __initContextMenuReopenWithEncoding(self): + """ + Private method used to setup the Reopen With Encoding context sub menu. + + @return reference to the generated menu (QMenu) + """ + menu = QMenu(self.tr("Re-Open With Encoding")) + menu.setIcon(UI.PixmapCache.getIcon("open.png")) + + for encoding in sorted(Utilities.supportedCodecs): + act = menu.addAction(encoding) + act.setData(encoding) + + menu.triggered.connect(self.__reopenWithEncodingMenuTriggered) + + return menu + def __initContextMenuEol(self): """ Private method to setup the eol context sub menu. @@ -940,26 +966,26 @@ """ self.supportedEols = {} - menu = QMenu(self.trUtf8("End-of-Line Type")) + menu = QMenu(self.tr("End-of-Line Type")) self.eolActGrp = QActionGroup(self) act = menu.addAction(UI.PixmapCache.getIcon("eolLinux.png"), - self.trUtf8("Unix")) + self.tr("Unix")) act.setCheckable(True) act.setData('\n') self.supportedEols['\n'] = act self.eolActGrp.addAction(act) act = menu.addAction(UI.PixmapCache.getIcon("eolWindows.png"), - self.trUtf8("Windows")) + self.tr("Windows")) act.setCheckable(True) act.setData('\r\n') self.supportedEols['\r\n'] = act self.eolActGrp.addAction(act) act = menu.addAction(UI.PixmapCache.getIcon("eolMac.png"), - self.trUtf8("Macintosh")) + self.tr("Macintosh")) act.setCheckable(True) act.setData('\r') self.supportedEols['\r'] = act @@ -976,7 +1002,7 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8("Export as")) + menu = QMenu(self.tr("Export as")) from . import Exporters supportedExporters = Exporters.getSupportedFormats() @@ -1009,13 +1035,13 @@ self.bmMarginMenu = QMenu() self.bmMarginMenu.addAction( - self.trUtf8('Toggle bookmark'), self.menuToggleBookmark) + self.tr('Toggle bookmark'), self.menuToggleBookmark) self.marginMenuActs["NextBookmark"] = self.bmMarginMenu.addAction( - self.trUtf8('Next bookmark'), self.nextBookmark) + self.tr('Next bookmark'), self.nextBookmark) self.marginMenuActs["PreviousBookmark"] = self.bmMarginMenu.addAction( - self.trUtf8('Previous bookmark'), self.previousBookmark) + self.tr('Previous bookmark'), self.previousBookmark) self.marginMenuActs["ClearBookmark"] = self.bmMarginMenu.addAction( - self.trUtf8('Clear all bookmarks'), self.clearBookmarks) + self.tr('Clear all bookmarks'), self.clearBookmarks) self.bmMarginMenu.aboutToShow.connect(self.__showContextMenuMargin) @@ -1023,23 +1049,23 @@ self.bpMarginMenu = QMenu() self.marginMenuActs["Breakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Toggle breakpoint'), self.menuToggleBreakpoint) + self.tr('Toggle breakpoint'), self.menuToggleBreakpoint) self.marginMenuActs["TempBreakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Toggle temporary breakpoint'), + self.tr('Toggle temporary breakpoint'), self.__menuToggleTemporaryBreakpoint) self.marginMenuActs["EditBreakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Edit breakpoint...'), self.menuEditBreakpoint) + self.tr('Edit breakpoint...'), self.menuEditBreakpoint) self.marginMenuActs["EnableBreakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Enable breakpoint'), + self.tr('Enable breakpoint'), self.__menuToggleBreakpointEnabled) self.marginMenuActs["NextBreakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Next breakpoint'), self.menuNextBreakpoint) + self.tr('Next breakpoint'), self.menuNextBreakpoint) self.marginMenuActs["PreviousBreakpoint"] = \ self.bpMarginMenu.addAction( - self.trUtf8('Previous breakpoint'), + self.tr('Previous breakpoint'), self.menuPreviousBreakpoint) self.marginMenuActs["ClearBreakpoint"] = self.bpMarginMenu.addAction( - self.trUtf8('Clear all breakpoints'), self.__menuClearBreakpoints) + self.tr('Clear all breakpoints'), self.__menuClearBreakpoints) self.bpMarginMenu.aboutToShow.connect(self.__showContextMenuMargin) @@ -1048,48 +1074,48 @@ self.marginMenuActs["GotoSyntaxError"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Goto syntax error'), self.gotoSyntaxError) + self.tr('Goto syntax error'), self.gotoSyntaxError) self.marginMenuActs["ShowSyntaxError"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Show syntax error message'), + self.tr('Show syntax error message'), self.__showSyntaxError) self.marginMenuActs["ClearSyntaxError"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Clear syntax error'), self.clearSyntaxError) + self.tr('Clear syntax error'), self.clearSyntaxError) self.indicMarginMenu.addSeparator() self.marginMenuActs["NextWarningMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8("Next warning"), self.nextWarning) + self.tr("Next warning"), self.nextWarning) self.marginMenuActs["PreviousWarningMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8("Previous warning"), self.previousWarning) + self.tr("Previous warning"), self.previousWarning) self.marginMenuActs["ShowWarning"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Show warning message'), self.__showWarning) + self.tr('Show warning message'), self.__showWarning) self.marginMenuActs["ClearWarnings"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Clear warnings'), self.clearWarnings) + self.tr('Clear warnings'), self.clearWarnings) self.indicMarginMenu.addSeparator() self.marginMenuActs["NextCoverageMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Next uncovered line'), self.nextUncovered) + self.tr('Next uncovered line'), self.nextUncovered) self.marginMenuActs["PreviousCoverageMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Previous uncovered line'), self.previousUncovered) + self.tr('Previous uncovered line'), self.previousUncovered) self.indicMarginMenu.addSeparator() self.marginMenuActs["NextTaskMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Next task'), self.nextTask) + self.tr('Next task'), self.nextTask) self.marginMenuActs["PreviousTaskMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Previous task'), self.previousTask) + self.tr('Previous task'), self.previousTask) self.indicMarginMenu.addSeparator() self.marginMenuActs["NextChangeMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Next change'), self.nextChange) + self.tr('Next change'), self.nextChange) self.marginMenuActs["PreviousChangeMarker"] = \ self.indicMarginMenu.addAction( - self.trUtf8('Previous change'), self.previousChange) + self.tr('Previous change'), self.previousChange) self.indicMarginMenu.aboutToShow.connect(self.__showContextMenuMargin) @@ -1100,71 +1126,71 @@ self.marginMenu = QMenu() self.marginMenu.addAction( - self.trUtf8('Toggle bookmark'), self.menuToggleBookmark) + self.tr('Toggle bookmark'), self.menuToggleBookmark) self.marginMenuActs["NextBookmark"] = self.marginMenu.addAction( - self.trUtf8('Next bookmark'), self.nextBookmark) + self.tr('Next bookmark'), self.nextBookmark) self.marginMenuActs["PreviousBookmark"] = self.marginMenu.addAction( - self.trUtf8('Previous bookmark'), self.previousBookmark) + self.tr('Previous bookmark'), self.previousBookmark) self.marginMenuActs["ClearBookmark"] = self.marginMenu.addAction( - self.trUtf8('Clear all bookmarks'), self.clearBookmarks) + self.tr('Clear all bookmarks'), self.clearBookmarks) self.marginMenu.addSeparator() self.marginMenuActs["GotoSyntaxError"] = self.marginMenu.addAction( - self.trUtf8('Goto syntax error'), self.gotoSyntaxError) + self.tr('Goto syntax error'), self.gotoSyntaxError) self.marginMenuActs["ShowSyntaxError"] = self.marginMenu.addAction( - self.trUtf8('Show syntax error message'), self.__showSyntaxError) + self.tr('Show syntax error message'), self.__showSyntaxError) self.marginMenuActs["ClearSyntaxError"] = self.marginMenu.addAction( - self.trUtf8('Clear syntax error'), self.clearSyntaxError) + self.tr('Clear syntax error'), self.clearSyntaxError) self.marginMenu.addSeparator() self.marginMenuActs["NextWarningMarker"] = self.marginMenu.addAction( - self.trUtf8("Next warning"), self.nextWarning) + self.tr("Next warning"), self.nextWarning) self.marginMenuActs["PreviousWarningMarker"] = \ self.marginMenu.addAction( - self.trUtf8("Previous warning"), self.previousWarning) + self.tr("Previous warning"), self.previousWarning) self.marginMenuActs["ShowWarning"] = self.marginMenu.addAction( - self.trUtf8('Show warning message'), self.__showWarning) + self.tr('Show warning message'), self.__showWarning) self.marginMenuActs["ClearWarnings"] = self.marginMenu.addAction( - self.trUtf8('Clear warnings'), self.clearWarnings) + self.tr('Clear warnings'), self.clearWarnings) self.marginMenu.addSeparator() self.marginMenuActs["Breakpoint"] = self.marginMenu.addAction( - self.trUtf8('Toggle breakpoint'), self.menuToggleBreakpoint) + self.tr('Toggle breakpoint'), self.menuToggleBreakpoint) self.marginMenuActs["TempBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Toggle temporary breakpoint'), + self.tr('Toggle temporary breakpoint'), self.__menuToggleTemporaryBreakpoint) self.marginMenuActs["EditBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Edit breakpoint...'), self.menuEditBreakpoint) + self.tr('Edit breakpoint...'), self.menuEditBreakpoint) self.marginMenuActs["EnableBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Enable breakpoint'), + self.tr('Enable breakpoint'), self.__menuToggleBreakpointEnabled) self.marginMenuActs["NextBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Next breakpoint'), self.menuNextBreakpoint) + self.tr('Next breakpoint'), self.menuNextBreakpoint) self.marginMenuActs["PreviousBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Previous breakpoint'), self.menuPreviousBreakpoint) + self.tr('Previous breakpoint'), self.menuPreviousBreakpoint) self.marginMenuActs["ClearBreakpoint"] = self.marginMenu.addAction( - self.trUtf8('Clear all breakpoints'), self.__menuClearBreakpoints) + self.tr('Clear all breakpoints'), self.__menuClearBreakpoints) self.marginMenu.addSeparator() self.marginMenuActs["NextCoverageMarker"] = self.marginMenu.addAction( - self.trUtf8('Next uncovered line'), self.nextUncovered) + self.tr('Next uncovered line'), self.nextUncovered) self.marginMenuActs["PreviousCoverageMarker"] = \ self.marginMenu.addAction( - self.trUtf8('Previous uncovered line'), self.previousUncovered) + self.tr('Previous uncovered line'), self.previousUncovered) self.marginMenu.addSeparator() self.marginMenuActs["NextTaskMarker"] = self.marginMenu.addAction( - self.trUtf8('Next task'), self.nextTask) + self.tr('Next task'), self.nextTask) self.marginMenuActs["PreviousTaskMarker"] = self.marginMenu.addAction( - self.trUtf8('Previous task'), self.previousTask) + self.tr('Previous task'), self.previousTask) self.marginMenu.addSeparator() self.marginMenuActs["NextChangeMarker"] = self.marginMenu.addAction( - self.trUtf8('Next change'), self.nextChange) + self.tr('Next change'), self.nextChange) self.marginMenuActs["PreviousChangeMarker"] = \ self.marginMenu.addAction( - self.trUtf8('Previous change'), self.previousChange) + self.tr('Previous change'), self.previousChange) self.marginMenu.addSeparator() self.marginMenuActs["LMBbookmarks"] = self.marginMenu.addAction( - self.trUtf8('LMB toggles bookmarks'), self.__lmBbookmarks) + self.tr('LMB toggles bookmarks'), self.__lmBbookmarks) self.marginMenuActs["LMBbookmarks"].setCheckable(True) self.marginMenuActs["LMBbookmarks"].setChecked(False) self.marginMenuActs["LMBbreakpoints"] = self.marginMenu.addAction( - self.trUtf8('LMB toggles breakpoints'), self.__lmBbreakpoints) + self.tr('LMB toggles breakpoints'), self.__lmBbreakpoints) self.marginMenuActs["LMBbreakpoints"].setCheckable(True) self.marginMenuActs["LMBbreakpoints"].setChecked(True) @@ -1193,16 +1219,16 @@ else: E5MessageBox.critical( self, - self.trUtf8("Export source"), - self.trUtf8( + self.tr("Export source"), + self.tr( """<p>No exporter available for the """ """export format <b>{0}</b>. Aborting...</p>""") .format(exporterFormat)) else: E5MessageBox.critical( self, - self.trUtf8("Export source"), - self.trUtf8("""No export format given. Aborting...""")) + self.tr("Export source"), + self.tr("""No export format given. Aborting...""")) def __showContextMenuLanguages(self): """ @@ -1211,11 +1237,11 @@ """ if self.apiLanguage.startswith("Pygments|"): self.pygmentsSelAct.setText( - self.trUtf8("Alternatives ({0})").format( + self.tr("Alternatives ({0})").format( self.getLanguage(normalized=False))) else: - self.pygmentsSelAct.setText(self.trUtf8("Alternatives")) - self.showMenu.emit("Languages", self.languagesMenu, self) + self.pygmentsSelAct.setText(self.tr("Alternatives")) + self.showMenu.emit("Languages", self.languagesMenu, self) def __selectPygmentsLexer(self): """ @@ -1232,8 +1258,8 @@ lexerSel = 0 lexerName, ok = QInputDialog.getItem( self, - self.trUtf8("Pygments Lexer"), - self.trUtf8("Select the Pygments lexer to apply."), + self.tr("Pygments Lexer"), + self.tr("Select the Pygments lexer to apply."), lexerList, lexerSel, False) @@ -1369,7 +1395,7 @@ Private slot handling the aboutToShow signal of the encodings context menu. """ - self.showMenu.emit("Encodings", self.encodingsMenu, self) + self.showMenu.emit("Encodings", self.encodingsMenu, self) def __encodingsMenuTriggered(self, act): """ @@ -1378,6 +1404,7 @@ @param act reference to the action that was triggered (QAction) """ encoding = act.data() + self.setModified(True) self.__encodingChanged("{0}-selected".format(encoding)) def __checkEncoding(self): @@ -1405,21 +1432,24 @@ self.encodingChanged.emit(self.encoding) self.inEncodingChanged = False - def __normalizedEncoding(self): + def __normalizedEncoding(self, encoding=""): """ Private method to calculate the normalized encoding string. + @param encoding encoding to be normalized (string) @return normalized encoding (string) """ - return self.encoding.replace("-default", "")\ - .replace("-guessed", "")\ - .replace("-selected", "") + if not encoding: + encoding = self.encoding + return encoding.replace("-default", "")\ + .replace("-guessed", "")\ + .replace("-selected", "") def __showContextMenuEol(self): """ Private slot handling the aboutToShow signal of the eol context menu. """ - self.showMenu.emit("Eol", self.eolMenu, self) + self.showMenu.emit("Eol", self.eolMenu, self) def __eolMenuTriggered(self, act): """ @@ -1466,22 +1496,25 @@ language = "" basename = os.path.basename(filename) - if self.project.isOpen() and self.project.isProjectFile(filename): - language = self.project.getEditorLexerAssoc(basename) - if not language: - language = Preferences.getEditorLexerAssoc(basename) - if not language: - bindName = self.__bindName(self.text(0)) - language = Preferences.getEditorLexerAssoc(bindName) - if language == "Python": - # correction for Python - pyVer = Utilities.determinePythonVersion( - filename, self.text(0), self) - language = "Python{0}".format(pyVer) - if language in ['Python2', 'Python3']: - self.filetype = language + if not self.filetype: + if self.project.isOpen() and self.project.isProjectFile(filename): + language = self.project.getEditorLexerAssoc(basename) + if not language: + language = Preferences.getEditorLexerAssoc(basename) + if not language: + bindName = self.__bindName(self.text(0)) + language = Preferences.getEditorLexerAssoc(bindName) + if language == "Python": + # correction for Python + pyVer = Utilities.determinePythonVersion( + filename, self.text(0), self) + language = "Python{0}".format(pyVer) + if language in ['Python2', 'Python3']: + self.filetype = language + else: + self.filetype = "" else: - self.filetype = "" + language = self.filetype if language.startswith("Pygments|"): pyname = language.split("|", 1)[1] @@ -1590,7 +1623,7 @@ filename = os.path.basename(filename) apiLanguage = Preferences.getEditorLexerAssoc(filename) if apiLanguage == "": - pyVer = self.getPyVersion() + pyVer = self.__getPyVersion() if pyVer: apiLanguage = "Python{0}".format(pyVer) elif self.isRubyFile(): @@ -1655,6 +1688,9 @@ pos = self.positionFromLineIndex(self.lastLine, self.lastIndex) self.spell.checkWord(pos) + if self.lastLine != line: + self.__markerMap.update() + self.lastLine = line self.lastIndex = index @@ -1664,9 +1700,9 @@ """ E5MessageBox.warning( self, - self.trUtf8("Modification of Read Only file"), - self.trUtf8("""You are attempting to change a read only file. """ - """Please save to a different file first.""")) + self.tr("Modification of Read Only file"), + self.tr("""You are attempting to change a read only file. """ + """Please save to a different file first.""")) def setNoName(self, noName): """ @@ -1721,7 +1757,7 @@ """ ftype = self.filetype if not ftype: - pyVer = self.getPyVersion() + pyVer = self.__getPyVersion() if pyVer: ftype = "Python{0}".format(pyVer) elif self.isRubyFile(): @@ -1739,23 +1775,31 @@ """ return self.encoding - def getPyVersion(self): - """ - Public methode to return the Python main version (2 or 3) or 0 if it's + def __getPyVersion(self): + """ + Private method to return the Python main version (2 or 3) or 0 if it's not a Python file at all. @return Python version (2 or 3) or 0 if it's not a Python file (int) """ return Utilities.determinePythonVersion( self.fileName, self.text(0), self) - + + def isPyFile(self): + """ + Public method to return a flag indicating a Python (2 or 3) file. + + @return flag indicating a Python (2 or 3) file (boolean) + """ + return self.__getPyVersion() in [2, 3] + def isPy2File(self): """ - Public method to return a flag indicating a Python file. - - @return flag indicating a Python file (boolean) - """ - return self.getPyVersion() == 2 + Public method to return a flag indicating a Python2 file. + + @return flag indicating a Python2 file (boolean) + """ + return self.__getPyVersion() == 2 def isPy3File(self): """ @@ -1763,7 +1807,7 @@ @return flag indicating a Python3 file (boolean) """ - return self.getPyVersion() == 3 + return self.__getPyVersion() == 3 def isRubyFile(self): """ @@ -1788,6 +1832,23 @@ return True return False + + def isJavascriptFile(self): + """ + Public method to return a flag indicating a Javascript file. + + @return flag indicating a Javascript file (boolean) + """ + if self.filetype == "JavaScript": + return True + + if self.filetype == "": + if self.fileName is not None and \ + os.path.splitext(self.fileName)[1] == ".js": + self.filetype = "JavaScript" + return True + + return False def highlightVisible(self): """ @@ -1887,6 +1948,7 @@ self.markerDeleteHandle(handle) self.__addBreakPoints( QModelIndex(), 0, self.breakpointModel.rowCount() - 1) + self.__markerMap.update() def __deleteBreakPoints(self, parentIndex, start, end): """ @@ -1963,6 +2025,7 @@ del self.breaks[handle] self.markerDeleteHandle(handle) + self.__markerMap.update() def newBreakpointWithProperties(self, line, properties): """ @@ -1983,6 +2046,7 @@ handle = self.markerAdd(line - 1, marker) self.breaks[handle] = (line,) + properties self.breakpointToggled.emit(self) + self.__markerMap.update() def __toggleBreakpoint(self, line, temporary=False): """ @@ -2016,7 +2080,7 @@ @param temporary flag indicating a temporary breakpoint (boolean) """ if self.fileName and \ - (self.getPyVersion() or self.isRubyFile()): + (self.isPyFile() or self.isRubyFile()): self.breakpointModel.addBreakPoint( self.fileName, line, ('', temporary, True, 0)) self.breakpointToggled.emit(self) @@ -2048,6 +2112,22 @@ line, _ = self.getCursorPosition() return self.markersAtLine(line) & self.breakpointMask != 0 + def getBreakpointLines(self): + """ + Public method to get the lines containing a breakpoint. + + @return list of lines containing a breakpoint (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, self.breakpointMask) + if line < 0: + break + else: + lines.append(line) + return lines + def hasBreakpoints(self): """ Public method to check for the presence of breakpoints. @@ -2190,17 +2270,15 @@ """ for handle in self.bookmarks: if self.markerLine(handle) == line - 1: + self.bookmarks.remove(handle) + self.markerDeleteHandle(handle) break else: # set a new bookmark handle = self.markerAdd(line - 1, self.bookmark) self.bookmarks.append(handle) - self.bookmarkToggled.emit(self) - return - - self.bookmarks.remove(handle) - self.markerDeleteHandle(handle) self.bookmarkToggled.emit(self) + self.__markerMap.update() def getBookmarks(self): """ @@ -2216,6 +2294,22 @@ bmlist.sort() return bmlist + def getBookmarkLines(self): + """ + Public method to get the lines containing a bookmark. + + @return list of lines containing a bookmark (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, 1 << self.bookmark) + if line < 0: + break + else: + lines.append(line) + return lines + def hasBookmarks(self): """ Public method to check for the presence of bookmarks. @@ -2277,6 +2371,7 @@ self.markerDeleteHandle(handle) self.bookmarks = [] self.bookmarkToggled.emit(self) + self.__markerMap.update() ########################################################################### ## Printing methods below @@ -2293,7 +2388,7 @@ if self.hasSelectedText(): printDialog.addEnabledOption(QAbstractPrintDialog.PrintSelection) if printDialog.exec_() == QDialog.Accepted: - sb.showMessage(self.trUtf8('Printing...')) + sb.showMessage(self.tr('Printing...')) QApplication.processEvents() fn = self.getFileName() if fn is not None: @@ -2310,12 +2405,12 @@ else: res = printer.printRange(self) if res: - sb.showMessage(self.trUtf8('Printing completed'), 2000) + sb.showMessage(self.tr('Printing completed'), 2000) else: - sb.showMessage(self.trUtf8('Error while printing'), 2000) + sb.showMessage(self.tr('Error while printing'), 2000) QApplication.processEvents() else: - sb.showMessage(self.trUtf8('Printing aborted'), 2000) + sb.showMessage(self.tr('Printing aborted'), 2000) QApplication.processEvents() def printPreviewFile(self): @@ -2347,7 +2442,23 @@ ########################################################################### ## Task handling methods below ########################################################################### - + + def getTaskLines(self): + """ + Public method to get the lines containing a task. + + @return list of lines containing a task (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, 1 << self.taskmarker) + if line < 0: + break + else: + lines.append(line) + return lines + def hasTaskMarkers(self): """ Public method to determine, if this editor contains any task markers. @@ -2433,6 +2544,7 @@ if shouldBreak: break self.taskMarkersUpdated.emit(self) + self.__markerMap.update() ########################################################################### ## Change tracing methods below @@ -2516,6 +2628,7 @@ if self.__hasChangeMarkers: self.changeMarkersUpdated.emit(self) + self.__markerMap.update() def __resetOnlineChangeTraceInfo(self): """ @@ -2537,6 +2650,7 @@ if self.__hasChangeMarkers: self.changeMarkersUpdated.emit(self) + self.__markerMap.update() def __deleteAllChangeMarkers(self): """ @@ -2546,6 +2660,23 @@ self.markerDeleteAll(self.__changeMarkerSaved) self.__hasChangeMarkers = False self.changeMarkersUpdated.emit(self) + self.__markerMap.update() + + def getChangeLines(self): + """ + Public method to get the lines containing a change. + + @return list of lines containing a change (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, self.changeMarkersMask) + if line < 0: + break + else: + lines.append(line) + return lines def hasChangeMarkers(self): """ @@ -2638,8 +2769,8 @@ fn = self.noName res = E5MessageBox.okToClearData( self, - self.trUtf8("File Modified"), - self.trUtf8("<p>The file <b>{0}</b> has unsaved changes.</p>") + self.tr("File Modified"), + self.tr("<p>The file <b>{0}</b> has unsaved changes.</p>") .format(fn), self.saveFile) if res: @@ -2668,13 +2799,15 @@ break # Couldn't find the unmodified state - def readFile(self, fn, createIt=False): + def readFile(self, fn, createIt=False, encoding=""): """ Public slot to read the text from a file. @param fn filename to read from (string) - @param createIt flag indicating the creation of a new file, if the + @keyparam createIt flag indicating the creation of a new file, if the given one doesn't exist (boolean) + @keyparam encoding encoding to be used to read the file (string) + (Note: this parameter overrides encoding detection) """ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) @@ -2682,14 +2815,18 @@ if createIt and not os.path.exists(fn): f = open(fn, "w") f.close() - txt, self.encoding = Utilities.readEncodedFile(fn) + if encoding: + txt, self.encoding = Utilities.readEncodedFileWithEncoding( + fn, encoding) + else: + txt, self.encoding = Utilities.readEncodedFile(fn) except (UnicodeDecodeError, IOError) as why: QApplication.restoreOverrideCursor() E5MessageBox.critical( self.vm, - self.trUtf8('Open File'), - self.trUtf8('<p>The file <b>{0}</b> could not be opened.</p>' - '<p>Reason: {1}</p>') + self.tr('Open File'), + self.tr('<p>The file <b>{0}</b> could not be opened.</p>' + '<p>Reason: {1}</p>') .format(fn, str(why))) QApplication.restoreOverrideCursor() raise @@ -2790,9 +2927,9 @@ except (IOError, Utilities.CodingError, UnicodeError) as why: E5MessageBox.critical( self, - self.trUtf8('Save File'), - self.trUtf8('<p>The file <b>{0}</b> could not be saved.<br/>' - 'Reason: {1}</p>') + self.tr('Save File'), + self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' + 'Reason: {1}</p>') .format(fn, str(why))) return False @@ -2839,7 +2976,7 @@ defaultFilter = Preferences.getEditor("DefaultSaveFilter") fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( self, - self.trUtf8("Save File"), + self.tr("Save File"), path, Lexers.getSaveFileFiltersList(True, True), defaultFilter, @@ -2857,9 +2994,9 @@ if QFileInfo(fn).exists(): res = E5MessageBox.yesNo( self, - self.trUtf8("Save File"), - self.trUtf8("<p>The file <b>{0}</b> already exists." - " Overwrite it?</p>").format(fn), + self.tr("Save File"), + self.tr("<p>The file <b>{0}</b> already exists." + " Overwrite it?</p>").format(fn), icon=E5MessageBox.Warning) if not res: return False @@ -3701,7 +3838,7 @@ @param goUp flag indicating the move direction (boolean) """ - if self.getPyVersion() or self.isRubyFile(): + if self.isPyFile() or self.isRubyFile(): lineNo = self.getCursorPosition()[0] line = self.text(lineNo) if line.strip().startswith(("class ", "def ", "module ")): @@ -3827,6 +3964,8 @@ # refresh the annotations display self.__refreshAnnotations() + + self.__markerMap.initColors() def __setLineMarkerColours(self): """ @@ -4064,6 +4203,8 @@ self.setVirtualSpaceOptions( Preferences.getEditor("VirtualSpaceOptions")) + + self.__markerMap.setEnabled(True) def __setEolMode(self): """ @@ -4164,8 +4305,8 @@ else: E5MessageBox.information( self, - self.trUtf8("Autocompletion"), - self.trUtf8( + self.tr("Autocompletion"), + self.tr( """Autocompletion is not available because""" """ there is no autocompletion source set.""")) @@ -4265,10 +4406,10 @@ # there is another provider registered already E5MessageBox.warning( self, - self.trUtf8("Activating Auto-Completion Provider"), - self.trUtf8("""Auto-completion provider cannot be connected""" - """ because there is already another one active.""" - """ Please check your configuration.""")) + self.tr("Activating Auto-Completion Provider"), + self.tr("""Auto-completion provider cannot be connected""" + """ because there is already another one active.""" + """ Please check your configuration.""")) return if self.autoCompletionThreshold() > 0: @@ -4349,7 +4490,7 @@ depth -= 1 if depth == 0: break - ch, pos = self.__getCharacter(pos) + ch, pos = self.__getCharacter(pos) elif ch == '(': found = True break @@ -4455,10 +4596,10 @@ # there is another provider registered already E5MessageBox.warning( self, - self.trUtf8("Activating Calltip Provider"), - self.trUtf8("""Calltip provider cannot be connected""" - """ because there is already another one active.""" - """ Please check your configuration.""")) + self.tr("Activating Calltip Provider"), + self.tr("""Calltip provider cannot be connected""" + """ because there is already another one active.""" + """ Please check your configuration.""")) return self.__ctHookFunction = func @@ -4527,6 +4668,8 @@ """ Private slot handling the aboutToShow signal of the context menu. """ + self.menuActs["Reopen"].setEnabled( + not self.isModified() and bool(self.fileName)) self.menuActs["Save"].setEnabled(self.isModified()) self.menuActs["Undo"].setEnabled(self.isUndoAvailable()) self.menuActs["Redo"].setEnabled(self.isRedoAvailable()) @@ -4535,12 +4678,12 @@ self.menuActs["Cut"].setEnabled(self.hasSelectedText()) self.menuActs["Copy"].setEnabled(self.hasSelectedText()) if not self.isResourcesFile: - if self.fileName and self.getPyVersion(): + if self.fileName and self.isPyFile(): self.menuActs["Show"].setEnabled(True) else: self.menuActs["Show"].setEnabled(False) if self.fileName and \ - (self.getPyVersion() or self.isRubyFile()): + (self.isPyFile() or self.isRubyFile()): self.menuActs["Diagrams"].setEnabled(True) else: self.menuActs["Diagrams"].setEnabled(False) @@ -4592,7 +4735,7 @@ self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty()) - self.showMenu.emit("Main", self.menu, self) + self.showMenu.emit("Main", self.menu, self) def __showContextMenuAutocompletion(self): """ @@ -4604,7 +4747,7 @@ self.menuActs["acAPIDocument"].setEnabled(self.acAPI) self.menuActs["calltip"].setEnabled(self.acAPI) - self.showMenu.emit("Autocompletion", self.autocompletionMenu, self) + self.showMenu.emit("Autocompletion", self.autocompletionMenu, self) def __showContextMenuShow(self): """ @@ -4656,7 +4799,7 @@ self.coverageHideAnnotationMenuAct.setEnabled( len(self.notcoveredMarkers) > 0) - self.showMenu.emit("Show", self.menuShow, self) + self.showMenu.emit("Show", self.menuShow, self) def __showContextMenuGraphics(self): """ @@ -4669,14 +4812,14 @@ else: self.applicationDiagramMenuAct.setEnabled(False) - self.showMenu.emit("Graphics", self.graphicsMenu, self) + self.showMenu.emit("Graphics", self.graphicsMenu, self) def __showContextMenuMargin(self): """ Private slot handling the aboutToShow signal of the margins context menu. """ - if self.fileName and (self.getPyVersion() or self.isRubyFile()): + if self.fileName and (self.isPyFile() or self.isRubyFile()): self.marginMenuActs["Breakpoint"].setEnabled(True) self.marginMenuActs["TempBreakpoint"].setEnabled(True) if self.markersAtLine(self.line) & self.breakpointMask: @@ -4687,10 +4830,10 @@ self.marginMenuActs["EnableBreakpoint"].setEnabled(False) if self.markersAtLine(self.line) & (1 << self.dbreakpoint): self.marginMenuActs["EnableBreakpoint"].setText( - self.trUtf8('Enable breakpoint')) + self.tr('Enable breakpoint')) else: self.marginMenuActs["EnableBreakpoint"].setText( - self.trUtf8('Disable breakpoint')) + self.tr('Disable breakpoint')) if self.breaks: self.marginMenuActs["NextBreakpoint"].setEnabled(True) self.marginMenuActs["PreviousBreakpoint"].setEnabled(True) @@ -4764,21 +4907,31 @@ self.marginMenuActs["PreviousChangeMarker"].setEnabled(False) self.marginMenuActs["NextChangeMarker"].setEnabled(False) - self.showMenu.emit("Margin", self.sender(), self) + self.showMenu.emit("Margin", self.sender(), self) def __showContextMenuChecks(self): """ Private slot handling the aboutToShow signal of the checks context menu. """ - self.showMenu.emit("Checks", self.checksMenu, self) + self.showMenu.emit("Checks", self.checksMenu, self) def __showContextMenuTools(self): """ Private slot handling the aboutToShow signal of the tools context menu. """ - self.showMenu.emit("Tools", self.toolsMenu, self) + self.showMenu.emit("Tools", self.toolsMenu, self) + + def __reopenWithEncodingMenuTriggered(self, act): + """ + Private method to handle the rereading of the file with a selected + encoding. + + @param act reference to the action that was triggered (QAction) + """ + encoding = act.data() + self.readFile(self.fileName, encoding=encoding) def __contextSave(self): """ @@ -5025,8 +5178,8 @@ if len(files) > 1: fn, ok = QInputDialog.getItem( self, - self.trUtf8("Code Coverage"), - self.trUtf8("Please select a coverage file"), + self.tr("Code Coverage"), + self.tr("Please select a coverage file"), files, 0, False) if not ok: @@ -5076,20 +5229,21 @@ for line in missing: handle = self.markerAdd(line - 1, self.notcovered) self.notcoveredMarkers.append(handle) - self.coverageMarkersShown.emit(True) + self.coverageMarkersShown.emit(True) + self.__markerMap.update() else: if not silent: E5MessageBox.information( self, - self.trUtf8("Show Code Coverage Annotations"), - self.trUtf8("""All lines have been covered.""")) + self.tr("Show Code Coverage Annotations"), + self.tr("""All lines have been covered.""")) self.showingNotcoveredMarkers = True else: if not silent: E5MessageBox.warning( self, - self.trUtf8("Show Code Coverage Annotations"), - self.trUtf8("""There is no coverage file available.""")) + self.tr("Show Code Coverage Annotations"), + self.tr("""There is no coverage file available.""")) def __codeCoverageHideAnnotations(self): """ @@ -5101,6 +5255,23 @@ self.notcoveredMarkers = [] self.coverageMarkersShown.emit(False) self.showingNotcoveredMarkers = False + self.__markerMap.update() + + def getCoverageLines(self): + """ + Public method to get the lines containing a coverage marker. + + @return list of lines containing a coverage marker (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, 1 << self.notcovered) + if line < 0: + break + else: + lines.append(line) + return lines def hasCoverageMarkers(self): """ @@ -5186,8 +5357,8 @@ if len(files) > 1: fn, ok = QInputDialog.getItem( self, - self.trUtf8("Profile Data"), - self.trUtf8("Please select a profile file"), + self.tr("Profile Data"), + self.tr("Please select a profile file"), files, 0, False) if not ok: @@ -5240,9 +5411,9 @@ if error: # set a new syntax error marker markers = self.markersAtLine(line - 1) + index += self.indentation(line - 1) if not (markers & (1 << self.syntaxerror)): handle = self.markerAdd(line - 1, self.syntaxerror) - index += self.indentation(line - 1) self.syntaxerrors[handle] = [(msg, index)] self.syntaxerrorToggled.emit(self) else: @@ -5261,6 +5432,7 @@ self.syntaxerrorToggled.emit(self) self.__setAnnotation(line - 1) + self.__markerMap.update() def getSyntaxErrors(self): """ @@ -5276,6 +5448,22 @@ selist.sort() return selist + def getSyntaxErrorLines(self): + """ + Public method to get the lines containing a syntax error. + + @return list of lines containing a syntax error (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, 1 << self.syntaxerror) + if line < 0: + break + else: + lines.append(line) + return lines + def hasSyntaxErrors(self): """ Public method to check for the presence of syntax errors. @@ -5323,14 +5511,14 @@ errors = [e[0] for e in self.syntaxerrors[handle]] E5MessageBox.critical( self, - self.trUtf8("Syntax Error"), + self.tr("Syntax Error"), "\n".join(errors)) break else: E5MessageBox.critical( self, - self.trUtf8("Syntax Error"), - self.trUtf8("No syntax error message available.")) + self.tr("Syntax Error"), + self.tr("No syntax error message available.")) ########################################################################### ## Warning handling methods below @@ -5374,6 +5562,7 @@ self.syntaxerrorToggled.emit(self) self.__setAnnotation(line - 1) + self.__markerMap.update() def getWarnings(self): """ @@ -5389,6 +5578,22 @@ fwlist.sort() return fwlist + def getWarningLines(self): + """ + Public method to get the lines containing a warning. + + @return list of lines containing a warning (list of integer) + """ + lines = [] + line = -1 + while True: + line = self.markerFindNext(line + 1, 1 << self.warning) + if line < 0: + break + else: + lines.append(line) + return lines + def hasWarnings(self): """ Public method to check for the presence of warnings. @@ -5469,6 +5674,7 @@ self.__setAnnotation(self.markerLine(handle)) self.markerDeleteHandle(handle) self.syntaxerrorToggled.emit(self) + self.__markerMap.update() def clearWarnings(self): """ @@ -5480,6 +5686,7 @@ self.markerDeleteHandle(handle) self.warnings = {} self.syntaxerrorToggled.emit(self) + self.__markerMap.update() def __showWarning(self, line=-1): """ @@ -5494,14 +5701,14 @@ if self.markerLine(handle) == line: E5MessageBox.warning( self, - self.trUtf8("Warning"), + self.tr("Warning"), '\n'.join([w[0] for w in self.warnings[handle]])) break else: E5MessageBox.warning( self, - self.trUtf8("Warning"), - self.trUtf8("No warning messages available.")) + self.tr("Warning"), + self.tr("No warning messages available.")) ########################################################################### ## Annotation handling methods below @@ -5560,17 +5767,17 @@ for msg, warningType in self.warnings[handle]: if warningType == self.WarningStyle: styleAnnotations.append( - self.trUtf8("Style: {0}").format(msg)) + self.tr("Style: {0}").format(msg)) else: warningAnnotations.append( - self.trUtf8("Warning: {0}").format(msg)) + self.tr("Warning: {0}").format(msg)) # step 2: do syntax errors for handle in self.syntaxerrors.keys(): if self.markerLine(handle) == line: for msg, _ in self.syntaxerrors[handle]: errorAnnotations.append( - self.trUtf8("Error: {0}").format(msg)) + self.tr("Error: {0}").format(msg)) annotations = [] if styleAnnotations: @@ -5625,8 +5832,8 @@ qs.sort() return QInputDialog.getItem( self, - self.trUtf8("Macro Name"), - self.trUtf8("Select a macro name:"), + self.tr("Macro Name"), + self.tr("Select a macro name:"), qs, 0, False) @@ -5653,9 +5860,9 @@ configDir = Utilities.getConfigDir() fname = E5FileDialog.getOpenFileName( self, - self.trUtf8("Load macro file"), + self.tr("Load macro file"), configDir, - self.trUtf8("Macro files (*.macro)")) + self.tr("Macro files (*.macro)")) if not fname: return # user aborted @@ -5667,8 +5874,8 @@ except IOError: E5MessageBox.critical( self, - self.trUtf8("Error loading macro"), - self.trUtf8( + self.tr("Error loading macro"), + self.tr( "<p>The macro file <b>{0}</b> could not be read.</p>") .format(fname)) return @@ -5676,8 +5883,8 @@ if len(lines) != 2: E5MessageBox.critical( self, - self.trUtf8("Error loading macro"), - self.trUtf8("<p>The macro file <b>{0}</b> is corrupt.</p>") + self.tr("Error loading macro"), + self.tr("<p>The macro file <b>{0}</b> is corrupt.</p>") .format(fname)) return @@ -5696,9 +5903,9 @@ fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( self, - self.trUtf8("Save macro file"), + self.tr("Save macro file"), configDir, - self.trUtf8("Macro files (*.macro)"), + self.tr("Macro files (*.macro)"), "", E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) @@ -5713,9 +5920,9 @@ if QFileInfo(fname).exists(): res = E5MessageBox.yesNo( self, - self.trUtf8("Save macro"), - self.trUtf8("<p>The macro file <b>{0}</b> already exists." - " Overwrite it?</p>").format(fname), + self.tr("Save macro"), + self.tr("<p>The macro file <b>{0}</b> already exists." + " Overwrite it?</p>").format(fname), icon=E5MessageBox.Warning) if not res: return @@ -5729,8 +5936,8 @@ except IOError: E5MessageBox.critical( self, - self.trUtf8("Error saving macro"), - self.trUtf8( + self.tr("Error saving macro"), + self.tr( "<p>The macro file <b>{0}</b> could not be written.</p>") .format(fname)) return @@ -5742,8 +5949,8 @@ if self.recording: res = E5MessageBox.yesNo( self, - self.trUtf8("Start Macro Recording"), - self.trUtf8("Macro recording is already active. Start new?"), + self.tr("Start Macro Recording"), + self.tr("Macro recording is already active. Start new?"), icon=E5MessageBox.Warning, yesDefault=True) if res: @@ -5768,8 +5975,8 @@ name, ok = QInputDialog.getText( self, - self.trUtf8("Macro Recording"), - self.trUtf8("Enter name of the macro:"), + self.tr("Macro Recording"), + self.tr("Enter name of the macro:"), QLineEdit.Normal) if ok and name: @@ -5890,19 +6097,19 @@ if Preferences.getEditor("AutoReopen") and not self.isModified(): self.refresh() else: - msg = self.trUtf8( + msg = self.tr( """<p>The file <b>{0}</b> has been changed while it""" """ was opened in eric5. Reread it?</p>""")\ .format(self.fileName) yesDefault = True if self.isModified(): - msg += self.trUtf8( + msg += self.tr( """<br><b>Warning:</b> You will lose""" """ your changes upon reopening it.""") yesDefault = False res = E5MessageBox.yesNo( self, - self.trUtf8("File changed"), msg, + self.tr("File changed"), msg, icon=E5MessageBox.Warning, yesDefault=yesDefault) if res: @@ -5946,7 +6153,7 @@ else: cap = self.fileName if self.isReadOnly(): - cap = self.trUtf8("{0} (ro)").format(cap) + cap = self.tr("{0} (ro)").format(cap) self.setWindowTitle(cap) super(Editor, self).changeEvent(evt) @@ -6019,6 +6226,25 @@ self.zoomTo(zoom) evt.accept() + def resizeEvent(self, evt): + """ + Protected method handling resize events. + + @param evt reference to the resize event (QResizeEvent) + """ + super(Editor, self).resizeEvent(evt) + self.__markerMap.calculateGeometry() + + def viewportEvent(self, evt): + """ + Protected method handling event of the viewport. + + @param evt reference to the event (QEvent) + @return flag indiating that the event was handled (boolean) + """ + self.__markerMap.calculateGeometry() + return super(Editor, self).viewportEvent(evt) + def __updateReadOnly(self, bForce=True): """ Private method to update the readOnly information for this editor. @@ -6039,7 +6265,7 @@ return cap = self.fileName if readOnly: - cap = self.trUtf8("{0} (ro)".format(cap)) + cap = self.tr("{0} (ro)".format(cap)) self.setReadOnly(readOnly) self.setWindowTitle(cap) self.captionChanged.emit(cap, self) @@ -6066,6 +6292,11 @@ self.markerDeleteHandle(handle) self.breaks = {} + if not os.path.exists(self.fileName): + # close the file, if it was deleted in the background + self.close() + return + # reread the file try: self.readFile(self.fileName) @@ -6090,6 +6321,8 @@ self.editorSaved.emit(self.fileName) self.__autoSyntaxCheck() + self.__markerMap.update() + self.refreshed.emit() def setMonospaced(self, on): @@ -6174,8 +6407,8 @@ else: E5MessageBox.information( self, - self.trUtf8("Drop Error"), - self.trUtf8("""<p><b>{0}</b> is not a file.</p>""") + self.tr("Drop Error"), + self.tr("""<p><b>{0}</b> is not a file.</p>""") .format(fname)) event.acceptProposedAction() else: @@ -6193,21 +6426,21 @@ @return reference to the generated menu (QMenu) """ - menu = QMenu(self.trUtf8('Resources')) + menu = QMenu(self.tr('Resources')) menu.addAction( - self.trUtf8('Add file...'), self.__addFileResource) + self.tr('Add file...'), self.__addFileResource) menu.addAction( - self.trUtf8('Add files...'), self.__addFileResources) + self.tr('Add files...'), self.__addFileResources) menu.addAction( - self.trUtf8('Add aliased file...'), + self.tr('Add aliased file...'), self.__addFileAliasResource) menu.addAction( - self.trUtf8('Add localized resource...'), + self.tr('Add localized resource...'), self.__addLocalizedResource) menu.addSeparator() menu.addAction( - self.trUtf8('Add resource frame'), self.__addResourceFrame) + self.tr('Add resource frame'), self.__addResourceFrame) menu.aboutToShow.connect(self.__showContextMenuResources) @@ -6218,7 +6451,7 @@ Private slot handling the aboutToShow signal of the resources context menu. """ - self.showMenu.emit("Resources", self.resourcesMenu, self) + self.showMenu.emit("Resources", self.resourcesMenu, self) def __addFileResource(self): """ @@ -6227,7 +6460,7 @@ dirStr = os.path.dirname(self.fileName) file = E5FileDialog.getOpenFileName( self, - self.trUtf8("Add file resource"), + self.tr("Add file resource"), dirStr, "") if file: @@ -6243,7 +6476,7 @@ dirStr = os.path.dirname(self.fileName) files = E5FileDialog.getOpenFileNames( self, - self.trUtf8("Add file resources"), + self.tr("Add file resources"), dirStr, "") if files: @@ -6263,15 +6496,15 @@ dirStr = os.path.dirname(self.fileName) file = E5FileDialog.getOpenFileName( self, - self.trUtf8("Add aliased file resource"), + self.tr("Add aliased file resource"), dirStr, "") if file: relFile = QDir(dirStr).relativeFilePath(file) alias, ok = QInputDialog.getText( self, - self.trUtf8("Add aliased file resource"), - self.trUtf8("Alias for file <b>{0}</b>:").format(relFile), + self.tr("Add aliased file resource"), + self.tr("Alias for file <b>{0}</b>:").format(relFile), QLineEdit.Normal, relFile) if ok and alias: @@ -6334,8 +6567,8 @@ self.fileName or os.path.dirname(self.fileName) res = E5MessageBox.yesNo( self, - self.trUtf8("Package Diagram"), - self.trUtf8("""Include class attributes?"""), + self.tr("Package Diagram"), + self.tr("""Include class attributes?"""), yesDefault=True) self.packageDiagram = UMLDialog( UMLDialog.PackageDiagram, self.project, package, @@ -6354,8 +6587,8 @@ or os.path.dirname(self.fileName) res = E5MessageBox.yesNo( self, - self.trUtf8("Imports Diagram"), - self.trUtf8("""Include imports from external modules?""")) + self.tr("Imports Diagram"), + self.tr("""Include imports from external modules?""")) self.importsDiagram = UMLDialog( UMLDialog.ImportsDiagram, self.project, package, self, showExternalImports=res) @@ -6368,8 +6601,8 @@ from Graphics.UMLDialog import UMLDialog res = E5MessageBox.yesNo( self, - self.trUtf8("Application Diagram"), - self.trUtf8("""Include module names?"""), + self.tr("Application Diagram"), + self.tr("""Include module names?"""), yesDefault=True) self.applicationDiagram = UMLDialog( UMLDialog.ApplicationDiagram, self.project, @@ -6656,13 +6889,13 @@ self.spellingMenu.addSeparator() self.spellingMenu.addAction( UI.PixmapCache.getIcon("spellchecking.png"), - self.trUtf8("Check spelling..."), self.__checkSpellingWord) + self.tr("Check spelling..."), self.__checkSpellingWord) self.spellingMenu.addAction( - self.trUtf8("Add to dictionary"), self.__addToSpellingDictionary) + self.tr("Add to dictionary"), self.__addToSpellingDictionary) self.spellingMenu.addAction( - self.trUtf8("Ignore All"), self.__ignoreSpellingAlways) - - self.showMenu.emit("Spelling", self.spellingMenu, self) + self.tr("Ignore All"), self.__ignoreSpellingAlways) + + self.showMenu.emit("Spelling", self.spellingMenu, self) def __contextMenuSpellingTriggered(self, action): """ @@ -7070,8 +7303,8 @@ except ValueError: E5MessageBox.critical( self, - self.trUtf8("Sort Lines"), - self.trUtf8( + self.tr("Sort Lines"), + self.tr( """The selection contains illegal data for a""" """ numerical sort.""")) return