QScintilla/Editor.py

branch
maintenance
changeset 6319
df201b9fbad4
parent 6273
0daf79d65080
parent 6306
af71f34a0cfb
child 6455
22a6fc33ab6d
--- a/QScintilla/Editor.py	Tue May 01 12:04:30 2018 +0200
+++ b/QScintilla/Editor.py	Sat Jun 02 12:44:41 2018 +0200
@@ -29,7 +29,7 @@
 from E5Gui import E5FileDialog, E5MessageBox
 from E5Utilities.E5Cache import E5Cache
 
-from .QsciScintillaCompat import QsciScintillaCompat, QSCINTILLA_VERSION
+from .QsciScintillaCompat import QsciScintillaCompat
 from .EditorMarkerMap import EditorMarkerMap
 
 import Preferences
@@ -273,12 +273,6 @@
         self.cursorPositionChanged.connect(self.__cursorPositionChanged)
         self.modificationAttempted.connect(self.__modificationReadOnly)
         
-        # margins layout
-        if QSCINTILLA_VERSION() >= 0x020301:
-            self.__unifiedMargins = Preferences.getEditor("UnifiedMargins")
-        else:
-            self.__unifiedMargins = True
-        
         # define the margins markers
         self.__changeMarkerSaved = self.markerDefine(
             self.__createChangeMarkerPixmap(
@@ -416,7 +410,8 @@
         self.__acWatchdog.timeout.connect(self.autoCompleteQScintilla)
         
         self.userListActivated.connect(self.__completionListSelected)
-        self.SCN_CHARADDED.connect(self.__charAddedPermanent)
+        self.SCN_CHARADDED.connect(self.__charAdded)
+        self.SCN_AUTOCCANCELLED.connect(self.__autocompletionCancelled)
         
         self.__completionListHookFunctions = {}
         self.__completionListAsyncHookFunctions = {}
@@ -1149,16 +1144,6 @@
         """
         self.marginMenuActs = {}
         
-        if self.__unifiedMargins:
-            self.__initContextMenuUnifiedMargins()
-        else:
-            self.__initContextMenuSeparateMargins()
-        
-    def __initContextMenuSeparateMargins(self):
-        """
-        Private method used to setup the context menu for the separated
-        margins.
-        """
         # bookmark margin
         self.bmMarginMenu = QMenu()
         
@@ -1199,6 +1184,39 @@
         self.bpMarginMenu.aboutToShow.connect(
             lambda: self.__showContextMenuMargin(self.bpMarginMenu))
         
+        # fold margin
+        self.foldMarginMenu = QMenu()
+        
+        self.marginMenuActs["ToggleAllFolds"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Toggle all folds"),
+                self.foldAll)
+        self.marginMenuActs["ToggleAllFoldsAndChildren"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Toggle all folds (including children)"),
+                lambda: self.foldAll(True))
+        self.marginMenuActs["ToggleCurrentFold"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Toggle current fold"),
+                self.toggleCurrentFold)
+        self.foldMarginMenu.addSeparator()
+        self.marginMenuActs["ExpandChildren"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Expand (including children)"),
+                self.__contextMenuExpandFoldWithChildren)
+        self.marginMenuActs["CollapseChildren"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Collapse (including children)"),
+                self.__contextMenuCollapseFoldWithChildren)
+        self.foldMarginMenu.addSeparator()
+        self.marginMenuActs["ClearAllFolds"] = \
+            self.foldMarginMenu.addAction(
+                self.tr("Clear all folds"),
+                self.clearFolds)
+        
+        self.foldMarginMenu.aboutToShow.connect(
+            lambda: self.__showContextMenuMargin(self.foldMarginMenu))
+        
         # indicator margin
         self.indicMarginMenu = QMenu()
         
@@ -1253,87 +1271,6 @@
         self.indicMarginMenu.aboutToShow.connect(
             lambda: self.__showContextMenuMargin(self.indicMarginMenu))
         
-    def __initContextMenuUnifiedMargins(self):
-        """
-        Private method used to setup the context menu for the unified margins.
-        """
-        self.marginMenu = QMenu()
-        
-        self.marginMenu.addAction(
-            self.tr('Toggle bookmark'), self.menuToggleBookmark)
-        self.marginMenuActs["NextBookmark"] = self.marginMenu.addAction(
-            self.tr('Next bookmark'), self.nextBookmark)
-        self.marginMenuActs["PreviousBookmark"] = self.marginMenu.addAction(
-            self.tr('Previous bookmark'), self.previousBookmark)
-        self.marginMenuActs["ClearBookmark"] = self.marginMenu.addAction(
-            self.tr('Clear all bookmarks'), self.clearBookmarks)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["GotoSyntaxError"] = self.marginMenu.addAction(
-            self.tr('Goto syntax error'), self.gotoSyntaxError)
-        self.marginMenuActs["ShowSyntaxError"] = self.marginMenu.addAction(
-            self.tr('Show syntax error message'), self.__showSyntaxError)
-        self.marginMenuActs["ClearSyntaxError"] = self.marginMenu.addAction(
-            self.tr('Clear syntax error'), self.clearSyntaxError)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["NextWarningMarker"] = self.marginMenu.addAction(
-            self.tr("Next warning"), self.nextWarning)
-        self.marginMenuActs["PreviousWarningMarker"] = \
-            self.marginMenu.addAction(
-                self.tr("Previous warning"), self.previousWarning)
-        self.marginMenuActs["ShowWarning"] = self.marginMenu.addAction(
-            self.tr('Show warning message'), self.__showWarning)
-        self.marginMenuActs["ClearWarnings"] = self.marginMenu.addAction(
-            self.tr('Clear warnings'), self.clearWarnings)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["Breakpoint"] = self.marginMenu.addAction(
-            self.tr('Toggle breakpoint'), self.menuToggleBreakpoint)
-        self.marginMenuActs["TempBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Toggle temporary breakpoint'),
-            self.__menuToggleTemporaryBreakpoint)
-        self.marginMenuActs["EditBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Edit breakpoint...'), self.menuEditBreakpoint)
-        self.marginMenuActs["EnableBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Enable breakpoint'),
-            self.__menuToggleBreakpointEnabled)
-        self.marginMenuActs["NextBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Next breakpoint'), self.menuNextBreakpoint)
-        self.marginMenuActs["PreviousBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Previous breakpoint'), self.menuPreviousBreakpoint)
-        self.marginMenuActs["ClearBreakpoint"] = self.marginMenu.addAction(
-            self.tr('Clear all breakpoints'), self.__menuClearBreakpoints)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["NextCoverageMarker"] = self.marginMenu.addAction(
-            self.tr('Next uncovered line'), self.nextUncovered)
-        self.marginMenuActs["PreviousCoverageMarker"] = \
-            self.marginMenu.addAction(
-                self.tr('Previous uncovered line'), self.previousUncovered)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["NextTaskMarker"] = self.marginMenu.addAction(
-            self.tr('Next task'), self.nextTask)
-        self.marginMenuActs["PreviousTaskMarker"] = self.marginMenu.addAction(
-            self.tr('Previous task'), self.previousTask)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["NextChangeMarker"] = self.marginMenu.addAction(
-            self.tr('Next change'), self.nextChange)
-        self.marginMenuActs["PreviousChangeMarker"] = \
-            self.marginMenu.addAction(
-                self.tr('Previous change'), self.previousChange)
-        self.marginMenuActs["ClearChangeMarkers"] = \
-            self.marginMenu.addAction(
-                self.tr('Clear changes'), self.__reinitOnlineChangeTrace)
-        self.marginMenu.addSeparator()
-        self.marginMenuActs["LMBbookmarks"] = self.marginMenu.addAction(
-            self.tr('LMB toggles bookmarks'), self.__lmBbookmarks)
-        self.marginMenuActs["LMBbookmarks"].setCheckable(True)
-        self.marginMenuActs["LMBbookmarks"].setChecked(False)
-        self.marginMenuActs["LMBbreakpoints"] = self.marginMenu.addAction(
-            self.tr('LMB toggles breakpoints'), self.__lmBbreakpoints)
-        self.marginMenuActs["LMBbreakpoints"].setCheckable(True)
-        self.marginMenuActs["LMBbreakpoints"].setChecked(True)
-        
-        self.marginMenu.aboutToShow.connect(
-            lambda: self.__showContextMenuMargin(self.marginMenu))
-        
     def __exportMenuTriggered(self, act):
         """
         Private method to handle the selection of an export format.
@@ -2358,6 +2295,7 @@
                     self.breakpointModel.setBreakPointByIndex(
                         index, self.fileName, ln,
                         (cond, temp, enabled, ignorecount))
+                    break
         
         self.line = -1
         
@@ -3313,22 +3251,36 @@
     ## Utility methods below
     ###########################################################################
 
-    def ensureVisible(self, line):
+    def ensureVisible(self, line, expand=False):
         """
         Public slot to ensure, that the specified line is visible.
         
         @param line line number to make visible
+        @type int
+        @keyparam expand flag indicating to expand all folds
+        @type bool
         """
         self.ensureLineVisible(line - 1)
-        
-    def ensureVisibleTop(self, line):
+        if expand:
+            self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line - 1,
+                               QsciScintilla.SC_FOLDACTION_EXPAND)
+        
+    def ensureVisibleTop(self, line, expand=False):
         """
         Public slot to ensure, that the specified line is visible at the top
         of the editor.
         
         @param line line number to make visible
-        """
+        @type int
+        @keyparam expand flag indicating to expand all folds
+        @type bool
+        """
+        self.ensureVisible(line)
         self.setFirstVisibleLine(line - 1)
+        self.ensureCursorVisible()
+        if expand:
+            self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line - 1,
+                               QsciScintilla.SC_FOLDACTION_EXPAND)
         
     def __marginClicked(self, margin, line, modifiers):
         """
@@ -3338,33 +3290,15 @@
         @param line line number of the click (integer)
         @param modifiers keyboard modifiers (Qt.KeyboardModifiers)
         """
-        if self.__unifiedMargins:
-            if margin == 1:
-                if modifiers & Qt.KeyboardModifiers(Qt.ShiftModifier):
-                    if self.marginMenuActs["LMBbreakpoints"].isChecked():
-                        self.toggleBookmark(line + 1)
-                    else:
-                        self.__toggleBreakpoint(line + 1)
-                elif modifiers & Qt.KeyboardModifiers(Qt.ControlModifier):
-                    if self.markersAtLine(line) & (1 << self.syntaxerror):
-                        self.__showSyntaxError(line)
-                    elif self.markersAtLine(line) & (1 << self.warning):
-                        self.__showWarning(line)
-                else:
-                    if self.marginMenuActs["LMBbreakpoints"].isChecked():
-                        self.__toggleBreakpoint(line + 1)
-                    else:
-                        self.toggleBookmark(line + 1)
-        else:
-            if margin == self.__bmMargin:
-                        self.toggleBookmark(line + 1)
-            elif margin == self.__bpMargin:
-                        self.__toggleBreakpoint(line + 1)
-            elif margin == self.__indicMargin:
-                if self.markersAtLine(line) & (1 << self.syntaxerror):
-                    self.__showSyntaxError(line)
-                elif self.markersAtLine(line) & (1 << self.warning):
-                    self.__showWarning(line)
+        if margin == self.__bmMargin:
+                    self.toggleBookmark(line + 1)
+        elif margin == self.__bpMargin:
+                    self.__toggleBreakpoint(line + 1)
+        elif margin == self.__indicMargin:
+            if self.markersAtLine(line) & (1 << self.syntaxerror):
+                self.__showSyntaxError(line)
+            elif self.markersAtLine(line) & (1 << self.warning):
+                self.__showWarning(line)
         
     def handleMonospacedEnable(self):
         """
@@ -4021,20 +3955,25 @@
             else:
                 self.__indentLine(True)
         
-    def gotoLine(self, line, pos=1, firstVisible=False):
+    def gotoLine(self, line, pos=1, firstVisible=False, expand=False):
         """
         Public slot to jump to the beginning of a line.
         
-        @param line line number to go to (integer)
-        @keyparam pos position in line to go to (integer)
+        @param line line number to go to
+        @type int
+        @keyparam pos position in line to go to
+        @type int
         @keyparam firstVisible flag indicating to make the line the first
-            visible line (boolean)
+            visible line
+        @type bool
+        @keyparam expand flag indicating to expand all folds
+        @type bool
         """
         self.setCursorPosition(line - 1, pos - 1)
         if firstVisible:
-            self.ensureVisibleTop(line)
+            self.ensureVisibleTop(line, expand)
         else:
-            self.ensureVisible(line)
+            self.ensureVisible(line, expand)
     
     def __textChanged(self):
         """
@@ -4142,10 +4081,6 @@
         if self.completer is not None:
             self.completer.readSettings()
         
-        # set the margins layout
-        if QSCINTILLA_VERSION() >= 0x020301:
-            self.__unifiedMargins = Preferences.getEditor("UnifiedMargins")
-        
         # set the line marker colours or pixmap
         if Preferences.getEditor("LineMarkersBackground"):
             self.markerDefine(QsciScintilla.Background, self.currentline)
@@ -4223,6 +4158,8 @@
         # refresh the annotations display
         self.__refreshAnnotations()
         
+        self.__markerMap.setMapPosition(
+            Preferences.getEditor("ShowMarkerMapOnRight"))
         self.__markerMap.initColors()
         
         self.settingsRead.emit()
@@ -4259,60 +4196,37 @@
             self.setMarginSensitivity(margin, False)
         
         # set marker margin(s) settings
-        if self.__unifiedMargins:
-            margin1Mask = (1 << self.breakpoint) | \
-                          (1 << self.cbreakpoint) | \
-                          (1 << self.tbreakpoint) | \
-                          (1 << self.tcbreakpoint) | \
-                          (1 << self.dbreakpoint) | \
-                          (1 << self.currentline) | \
-                          (1 << self.errorline) | \
-                          (1 << self.bookmark) | \
-                          (1 << self.syntaxerror) | \
+        self.__bmMargin = 0
+        self.__linenoMargin = 1
+        self.__bpMargin = 2
+        self.__foldMargin = 3
+        self.__indicMargin = 4
+        
+        marginBmMask = (1 << self.bookmark)
+        self.setMarginWidth(self.__bmMargin, 16)
+        self.setMarginSensitivity(self.__bmMargin, True)
+        self.setMarginMarkerMask(self.__bmMargin, marginBmMask)
+        
+        marginBpMask = (1 << self.breakpoint) | \
+                       (1 << self.cbreakpoint) | \
+                       (1 << self.tbreakpoint) | \
+                       (1 << self.tcbreakpoint) | \
+                       (1 << self.dbreakpoint)
+        self.setMarginWidth(self.__bpMargin, 16)
+        self.setMarginSensitivity(self.__bpMargin, True)
+        self.setMarginMarkerMask(self.__bpMargin, marginBpMask)
+        
+        marginIndicMask = (1 << self.syntaxerror) | \
                           (1 << self.notcovered) | \
                           (1 << self.taskmarker) | \
                           (1 << self.warning) | \
                           (1 << self.__changeMarkerUnsaved) | \
-                          (1 << self.__changeMarkerSaved)
-            self.setMarginWidth(1, 16)
-            self.setMarginSensitivity(1, True)
-            self.setMarginMarkerMask(1, margin1Mask)
-            
-            self.__linenoMargin = 0
-            self.__foldMargin = 2
-        else:
-            
-            self.__bmMargin = 0
-            self.__linenoMargin = 1
-            self.__bpMargin = 2
-            self.__foldMargin = 3
-            self.__indicMargin = 4
-            
-            marginBmMask = (1 << self.bookmark)
-            self.setMarginWidth(self.__bmMargin, 16)
-            self.setMarginSensitivity(self.__bmMargin, True)
-            self.setMarginMarkerMask(self.__bmMargin, marginBmMask)
-            
-            marginBpMask = (1 << self.breakpoint) | \
-                           (1 << self.cbreakpoint) | \
-                           (1 << self.tbreakpoint) | \
-                           (1 << self.tcbreakpoint) | \
-                           (1 << self.dbreakpoint)
-            self.setMarginWidth(self.__bpMargin, 16)
-            self.setMarginSensitivity(self.__bpMargin, True)
-            self.setMarginMarkerMask(self.__bpMargin, marginBpMask)
-            
-            marginIndicMask = (1 << self.syntaxerror) | \
-                              (1 << self.notcovered) | \
-                              (1 << self.taskmarker) | \
-                              (1 << self.warning) | \
-                              (1 << self.__changeMarkerUnsaved) | \
-                              (1 << self.__changeMarkerSaved) | \
-                              (1 << self.currentline) | \
-                              (1 << self.errorline)
-            self.setMarginWidth(self.__indicMargin, 16)
-            self.setMarginSensitivity(self.__indicMargin, True)
-            self.setMarginMarkerMask(self.__indicMargin, marginIndicMask)
+                          (1 << self.__changeMarkerSaved) | \
+                          (1 << self.currentline) | \
+                          (1 << self.errorline)
+        self.setMarginWidth(self.__indicMargin, 16)
+        self.setMarginSensitivity(self.__indicMargin, True)
+        self.setMarginMarkerMask(self.__indicMargin, marginIndicMask)
         
         # set linenumber margin settings
         linenoMargin = Preferences.getEditor("LinenoMargin")
@@ -4507,6 +4421,7 @@
             Preferences.getEditor("AutoCompletionCaseSensitivity"))
         self.setAutoCompletionReplaceWord(
             Preferences.getEditor("AutoCompletionReplaceWord"))
+        self.setAutoCompletionThreshold(0)
         try:
             self.setAutoCompletionUseSingle(
                 Preferences.getEditor("AutoCompletionShowSingle"))
@@ -4520,16 +4435,9 @@
             self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
         else:
             self.setAutoCompletionSource(QsciScintilla.AcsAll)
-        if Preferences.getEditor("AutoCompletionEnabled"):
-            if not self.__completionListHookFunctions and \
-               not self.__completionListAsyncHookFunctions:
-                self.setAutoCompletionThreshold(
-                    Preferences.getEditor("AutoCompletionThreshold"))
-            else:
-                self.setAutoCompletionThreshold(0)
-        else:
-            self.setAutoCompletionThreshold(-1)
-            self.setAutoCompletionSource(QsciScintilla.AcsNone)
+        
+        self.maxLines = Preferences.getEditor("AutoCompletionMaxLines")
+        self.maxChars = Preferences.getEditor("AutoCompletionMaxChars")
         
     def __setCallTips(self):
         """
@@ -4601,8 +4509,6 @@
             (boolean)
         """
         if enable:
-            self.setAutoCompletionThreshold(
-                Preferences.getEditor("AutoCompletionThreshold"))
             autoCompletionSource = \
                 Preferences.getEditor("AutoCompletionSource")
             if autoCompletionSource == QsciScintilla.AcsDocument:
@@ -4611,10 +4517,7 @@
                 self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
             else:
                 self.setAutoCompletionSource(QsciScintilla.AcsAll)
-        else:
-            self.setAutoCompletionThreshold(-1)
-            self.setAutoCompletionSource(QsciScintilla.AcsNone)
-        
+    
     def __toggleAutoCompletionEnable(self):
         """
         Private slot to handle the Enable Autocompletion context menu entry.
@@ -4634,8 +4537,13 @@
         
         @param charNumber value of the character entered (integer)
         """
+        char = chr(charNumber)
+        # update code documentation viewer
+        if char == "(" and \
+           Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"):
+            self.vm.showEditorInfo(self)
+            
         if self.isListActive():
-            char = chr(charNumber)
             if self.__isStartChar(char):
                 self.cancelList()
                 self.autoComplete(auto=True, context=True)
@@ -4718,13 +4626,6 @@
                 .format(key))
             return
         
-        if not self.__completionListHookFunctions and \
-           not self.__completionListAsyncHookFunctions:
-            if self.autoCompletionThreshold() > 0:
-                self.setAutoCompletionThreshold(0)
-            self.SCN_CHARADDED.connect(self.__charAdded)
-            self.SCN_AUTOCCANCELLED.connect(self.__autocompletionCancelled)
-        
         if asynchroneous:
             self.__completionListAsyncHookFunctions[key] = func
         else:
@@ -4742,14 +4643,6 @@
             del self.__completionListHookFunctions[key]
         elif key in self.__completionListAsyncHookFunctions:
             del self.__completionListAsyncHookFunctions[key]
-        
-        if not self.__completionListHookFunctions and \
-           not self.__completionListAsyncHookFunctions:
-            self.SCN_CHARADDED.disconnect(self.__charAdded)
-            self.SCN_AUTOCCANCELLED.disconnect(self.__autocompletionCancelled)
-            if self.autoCompletionThreshold() == 0:
-                self.setAutoCompletionThreshold(
-                    Preferences.getEditor("AutoCompletionThreshold"))
     
     def getCompletionListHook(self, key):
         """
@@ -4771,7 +4664,7 @@
             (boolean)
         @keyparam context flag indicating to complete a context (boolean)
         """
-        if auto and self.autoCompletionThreshold() == -1:
+        if auto and not Preferences.getEditor("AutoCompletionEnabled"):
             # auto-completion is disabled
             return
         
@@ -5148,20 +5041,6 @@
     ## Methods needed by the code documentation viewer
     #################################################################
     
-    def __charAddedPermanent(self, charNumber):
-        """
-        Private slot called to handle the user entering a character.
-        
-        Note: This slot is always connected independent of the auto-completion
-        and calltips handling __charAdded() slot.
-        
-        @param charNumber value of the character entered (integer)
-        """
-        char = chr(charNumber)
-        if char == "(" and \
-           Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"):
-            self.vm.showEditorInfo(self)
-    
     def __showCodeInfo(self):
         """
         Private slot to handle the context menu action to show code info.
@@ -5203,16 +5082,15 @@
                 self.menu.popup(evt.globalPos())
         else:
             self.line = self.lineAt(evt.pos())
-            if self.__unifiedMargins:
-                self.marginMenu.popup(evt.globalPos())
-            else:
-                if self.__marginNumber(evt.x()) in [self.__bmMargin,
-                                                    self.__linenoMargin]:
-                    self.bmMarginMenu.popup(evt.globalPos())
-                elif self.__marginNumber(evt.x()) == self.__bpMargin:
-                    self.bpMarginMenu.popup(evt.globalPos())
-                elif self.__marginNumber(evt.x()) == self.__indicMargin:
-                    self.indicMarginMenu.popup(evt.globalPos())
+            if self.__marginNumber(evt.x()) in [self.__bmMargin,
+                                                self.__linenoMargin]:
+                self.bmMarginMenu.popup(evt.globalPos())
+            elif self.__marginNumber(evt.x()) == self.__bpMargin:
+                self.bpMarginMenu.popup(evt.globalPos())
+            elif self.__marginNumber(evt.x()) == self.__indicMargin:
+                self.indicMarginMenu.popup(evt.globalPos())
+            elif self.__marginNumber(evt.x()) == self.__foldMargin:
+                self.foldMarginMenu.popup(evt.globalPos())
         
     def __showContextMenu(self):
         """
@@ -5333,7 +5211,7 @@
                     (self.project.isPy3Project() or
                         self.project.isPy2Project())
         
-        # now check ourself
+        # now check ourselves
         fn = self.getFileName()
         if fn is not None:
             tfn = Utilities.getTestFileName(fn)
@@ -5382,96 +5260,86 @@
         @param menu reference to the menu to be shown
         @type QMenu
         """
-        if self.fileName and self.isPyFile():
-            self.marginMenuActs["Breakpoint"].setEnabled(True)
-            self.marginMenuActs["TempBreakpoint"].setEnabled(True)
-            if self.markersAtLine(self.line) & self.breakpointMask:
-                self.marginMenuActs["EditBreakpoint"].setEnabled(True)
-                self.marginMenuActs["EnableBreakpoint"].setEnabled(True)
-            else:
-                self.marginMenuActs["EditBreakpoint"].setEnabled(False)
-                self.marginMenuActs["EnableBreakpoint"].setEnabled(False)
-            if self.markersAtLine(self.line) & (1 << self.dbreakpoint):
-                self.marginMenuActs["EnableBreakpoint"].setText(
-                    self.tr('Enable breakpoint'))
-            else:
-                self.marginMenuActs["EnableBreakpoint"].setText(
-                    self.tr('Disable breakpoint'))
-            if self.breaks:
-                self.marginMenuActs["NextBreakpoint"].setEnabled(True)
-                self.marginMenuActs["PreviousBreakpoint"].setEnabled(True)
-                self.marginMenuActs["ClearBreakpoint"].setEnabled(True)
-            else:
-                self.marginMenuActs["NextBreakpoint"].setEnabled(False)
-                self.marginMenuActs["PreviousBreakpoint"].setEnabled(False)
-                self.marginMenuActs["ClearBreakpoint"].setEnabled(False)
-        else:
-            self.marginMenuActs["Breakpoint"].setEnabled(False)
-            self.marginMenuActs["TempBreakpoint"].setEnabled(False)
-            self.marginMenuActs["EditBreakpoint"].setEnabled(False)
-            self.marginMenuActs["EnableBreakpoint"].setEnabled(False)
-            self.marginMenuActs["NextBreakpoint"].setEnabled(False)
-            self.marginMenuActs["PreviousBreakpoint"].setEnabled(False)
-            self.marginMenuActs["ClearBreakpoint"].setEnabled(False)
+        if menu is self.bpMarginMenu:
+            supportsDebugger = bool(self.fileName and self.isPyFile())
+            hasBreakpoints = bool(self.breaks)
+            hasBreakpoint = bool(
+                self.markersAtLine(self.line) & self.breakpointMask)
             
-        if self.bookmarks:
-            self.marginMenuActs["NextBookmark"].setEnabled(True)
-            self.marginMenuActs["PreviousBookmark"].setEnabled(True)
-            self.marginMenuActs["ClearBookmark"].setEnabled(True)
-        else:
-            self.marginMenuActs["NextBookmark"].setEnabled(False)
-            self.marginMenuActs["PreviousBookmark"].setEnabled(False)
-            self.marginMenuActs["ClearBookmark"].setEnabled(False)
+            self.marginMenuActs["Breakpoint"].setEnabled(supportsDebugger)
+            self.marginMenuActs["TempBreakpoint"].setEnabled(supportsDebugger)
+            self.marginMenuActs["NextBreakpoint"].setEnabled(
+                supportsDebugger and hasBreakpoints)
+            self.marginMenuActs["PreviousBreakpoint"].setEnabled(
+                supportsDebugger and hasBreakpoints)
+            self.marginMenuActs["ClearBreakpoint"].setEnabled(
+                supportsDebugger and hasBreakpoints)
+            self.marginMenuActs["EditBreakpoint"].setEnabled(
+                supportsDebugger and hasBreakpoint)
+            self.marginMenuActs["EnableBreakpoint"].setEnabled(
+                supportsDebugger and hasBreakpoint)
+            if supportsDebugger:
+                if self.markersAtLine(self.line) & (1 << self.dbreakpoint):
+                    self.marginMenuActs["EnableBreakpoint"].setText(
+                        self.tr('Enable breakpoint'))
+                else:
+                    self.marginMenuActs["EnableBreakpoint"].setText(
+                        self.tr('Disable breakpoint'))
+        
+        if menu is self.bmMarginMenu:
+            hasBookmarks = bool(self.bookmarks)
             
-        if len(self.syntaxerrors):
-            self.marginMenuActs["GotoSyntaxError"].setEnabled(True)
-            self.marginMenuActs["ClearSyntaxError"].setEnabled(True)
-            if self.markersAtLine(self.line) & (1 << self.syntaxerror):
+            self.marginMenuActs["NextBookmark"].setEnabled(hasBookmarks)
+            self.marginMenuActs["PreviousBookmark"].setEnabled(hasBookmarks)
+            self.marginMenuActs["ClearBookmark"].setEnabled(hasBookmarks)
+        
+        if menu is self.foldMarginMenu:
+            isFoldHeader = bool(self.SendScintilla(
+                QsciScintilla.SCI_GETFOLDLEVEL, self.line) &
+                QsciScintilla.SC_FOLDLEVELHEADERFLAG)
+            
+            self.marginMenuActs["ExpandChildren"].setEnabled(isFoldHeader)
+            self.marginMenuActs["CollapseChildren"].setEnabled(isFoldHeader)
+        
+        if menu is self.indicMarginMenu:
+            hasSyntaxErrors = bool(self.syntaxerrors)
+            hasWarnings = bool(self.warnings)
+            hasNotCoveredMarkers = bool(self.notcoveredMarkers)
+            
+            self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors)
+            self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors)
+            if hasSyntaxErrors and \
+               self.markersAtLine(self.line) & (1 << self.syntaxerror):
                 self.marginMenuActs["ShowSyntaxError"].setEnabled(True)
             else:
                 self.marginMenuActs["ShowSyntaxError"].setEnabled(False)
-        else:
-            self.marginMenuActs["GotoSyntaxError"].setEnabled(False)
-            self.marginMenuActs["ClearSyntaxError"].setEnabled(False)
-            self.marginMenuActs["ShowSyntaxError"].setEnabled(False)
-        
-        if len(self.warnings):
-            self.marginMenuActs["NextWarningMarker"].setEnabled(True)
-            self.marginMenuActs["PreviousWarningMarker"].setEnabled(True)
-            self.marginMenuActs["ClearWarnings"].setEnabled(True)
-            if self.markersAtLine(self.line) & (1 << self.warning):
+            
+            self.marginMenuActs["NextWarningMarker"].setEnabled(hasWarnings)
+            self.marginMenuActs["PreviousWarningMarker"].setEnabled(
+                hasWarnings)
+            self.marginMenuActs["ClearWarnings"].setEnabled(hasWarnings)
+            if hasWarnings and \
+               self.markersAtLine(self.line) & (1 << self.warning):
                 self.marginMenuActs["ShowWarning"].setEnabled(True)
             else:
                 self.marginMenuActs["ShowWarning"].setEnabled(False)
-        else:
-            self.marginMenuActs["NextWarningMarker"].setEnabled(False)
-            self.marginMenuActs["PreviousWarningMarker"].setEnabled(False)
-            self.marginMenuActs["ClearWarnings"].setEnabled(False)
-            self.marginMenuActs["ShowWarning"].setEnabled(False)
-        
-        if self.notcoveredMarkers:
-            self.marginMenuActs["NextCoverageMarker"].setEnabled(True)
-            self.marginMenuActs["PreviousCoverageMarker"].setEnabled(True)
-        else:
-            self.marginMenuActs["NextCoverageMarker"].setEnabled(False)
-            self.marginMenuActs["PreviousCoverageMarker"].setEnabled(False)
-        
-        if self.__hasTaskMarkers:
-            self.marginMenuActs["PreviousTaskMarker"].setEnabled(True)
-            self.marginMenuActs["NextTaskMarker"].setEnabled(True)
-        else:
-            self.marginMenuActs["PreviousTaskMarker"].setEnabled(False)
-            self.marginMenuActs["NextTaskMarker"].setEnabled(False)
-        
-        if self.__hasChangeMarkers:
-            self.marginMenuActs["PreviousChangeMarker"].setEnabled(True)
-            self.marginMenuActs["NextChangeMarker"].setEnabled(True)
-            self.marginMenuActs["ClearChangeMarkers"].setEnabled(True)
+            
+            self.marginMenuActs["NextCoverageMarker"].setEnabled(
+                hasNotCoveredMarkers)
+            self.marginMenuActs["PreviousCoverageMarker"].setEnabled(
+                hasNotCoveredMarkers)
             
-        else:
-            self.marginMenuActs["PreviousChangeMarker"].setEnabled(False)
-            self.marginMenuActs["NextChangeMarker"].setEnabled(False)
-            self.marginMenuActs["ClearChangeMarkers"].setEnabled(False)
+            self.marginMenuActs["PreviousTaskMarker"].setEnabled(
+                self.__hasTaskMarkers)
+            self.marginMenuActs["NextTaskMarker"].setEnabled(
+                self.__hasTaskMarkers)
+            
+            self.marginMenuActs["PreviousChangeMarker"].setEnabled(
+                self.__hasChangeMarkers)
+            self.marginMenuActs["NextChangeMarker"].setEnabled(
+                self.__hasChangeMarkers)
+            self.marginMenuActs["ClearChangeMarkers"].setEnabled(
+                self.__hasChangeMarkers)
         
         self.showMenu.emit("Margin", menu, self)
         
@@ -5756,7 +5624,7 @@
                 if os.path.isfile(tf):
                     files.append(tf)
         
-        # now check, if there are coverage files belonging to ourself
+        # now check, if there are coverage files belonging to ourselves
         fn = self.getFileName()
         if fn is not None:
             tfn = Utilities.getTestFileName(fn)
@@ -5934,7 +5802,7 @@
                 if os.path.isfile(tf):
                     files.append(tf)
         
-        # now check, if there are profile files belonging to ourself
+        # now check, if there are profile files belonging to ourselves
         fn = self.getFileName()
         if fn is not None:
             tfn = Utilities.getTestFileName(fn)
@@ -6435,6 +6303,55 @@
                 self.__setAnnotation(line)
     
     #################################################################
+    ## Fold handling methods
+    #################################################################
+    
+    def toggleCurrentFold(self):
+        """
+        Public slot to toggle the fold containing the current line.
+        """
+        line, index = self.getCursorPosition()
+        self.foldLine(line)
+    
+    def expandFoldWithChildren(self, line=-1):
+        """
+        Public slot to expand the current fold including its children.
+        
+        @param line number of line to be expanded
+        @type int
+        """
+        if line == -1:
+            line, index = self.getCursorPosition()
+        
+        self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line,
+                           QsciScintilla.SC_FOLDACTION_EXPAND)
+    
+    def collapseFoldWithChildren(self, line=-1):
+        """
+        Public slot to collapse the current fold including its children.
+        
+        @param line number of line to be expanded
+        @type int
+        """
+        if line == -1:
+            line, index = self.getCursorPosition()
+        
+        self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line,
+                           QsciScintilla.SC_FOLDACTION_CONTRACT)
+    
+    def __contextMenuExpandFoldWithChildren(self):
+        """
+        Private slot to handle the context menu expand with children action.
+        """
+        self.expandFoldWithChildren(self.line)
+    
+    def __contextMenuCollapseFoldWithChildren(self):
+        """
+        Private slot to handle the context menu collapse with children action.
+        """
+        self.collapseFoldWithChildren(self.line)
+    
+    #################################################################
     ## Macro handling methods
     #################################################################
     

eric ide

mercurial