QScintilla/SearchReplaceWidget.py

branch
Py2 comp.
changeset 2677
3d4277929fb3
parent 2525
8b507a9a2d40
parent 2663
37b3ec77f2c4
child 2791
a9577f248f04
--- a/QScintilla/SearchReplaceWidget.py	Fri May 24 18:39:58 2013 +0200
+++ b/QScintilla/SearchReplaceWidget.py	Tue May 28 20:52:12 2013 +0200
@@ -146,9 +146,33 @@
         self.havefound = False
         self.__pos = None
         self.__findBackwards = False
-        self.__selection = None
+        self.__selections = []
         self.__finding = False
-
+    
+    def __selectionBoundary(self, selections=None):
+        """
+        Private method to calculate the current selection boundary.
+        
+        @param selections optional parameter giving the selections to
+            calculate the boundary for (list of tuples of four integer)
+        @return tuple of start line and index and end line and index
+            (tuple of four integer)
+        """
+        if selections is None:
+            selections = self.__selections
+        if selections:
+            lineNumbers = [sel[0] for sel in selections] + \
+                          [sel[2] for sel in selections]
+            indexNumbers = [sel[1] for sel in selections] + \
+                           [sel[3] for sel in selections]
+            startLine, startIndex, endLine, endIndex = (
+                min(lineNumbers), min(indexNumbers),
+                max(lineNumbers), max(indexNumbers))
+        else:
+            startLine, startIndex, endLine, endIndex = -1, -1, -1, -1
+        
+        return startLine, startIndex, endLine, endIndex
+    
     def on_findtextCombo_editTextChanged(self, txt):
         """
         Private slot to enable/disable the find buttons.
@@ -265,10 +289,7 @@
         lineTo = -1
         indexTo = -1
         if self.ui.selectionCheckBox.isChecked():
-            lineFrom = self.__selection[0]
-            indexFrom = self.__selection[1]
-            lineTo = self.__selection[2]
-            indexTo = self.__selection[3]
+            lineFrom, indexFrom, lineTo, indexTo = self.__selectionBoundary()
         
         aw.clearSearchIndicators()
         ok = aw.findFirstTarget(txt,
@@ -280,7 +301,21 @@
             tgtPos, tgtLen = aw.getFoundTarget()
             if tgtLen == 0:
                 break
-            aw.setSearchIndicator(tgtPos, tgtLen)
+            if len(self.__selections) > 1:
+                lineFrom, indexFrom = aw.lineIndexFromPosition(tgtPos)
+                lineTo, indexTo = aw.lineIndexFromPosition(tgtPos + tgtLen)
+                for sel in self.__selections:
+                    if lineFrom == sel[0] and \
+                       indexFrom >= sel[1] and \
+                       indexTo <= sel[3]:
+                        indicate = True
+                        break
+                else:
+                    indicate = False
+            else:
+                indicate = True
+            if indicate:
+                aw.setSearchIndicator(tgtPos, tgtLen)
             ok = aw.findNextTarget()
     
     def __findNextPrev(self, txt, backwards):
@@ -301,12 +336,12 @@
         
         ok = True
         lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
+        boundary = self.__selectionBoundary()
         if backwards:
             if self.ui.selectionCheckBox.isChecked() and \
-               (lineFrom, indexFrom, lineTo, indexTo) == self.__selection:
+               (lineFrom, indexFrom, lineTo, indexTo) == boundary:
                 # initial call
-                line = self.__selection[2]
-                index = self.__selection[3]
+                line, index = boundary[2:]
             else:
                 if (lineFrom, indexFrom) == (-1, -1):
                     # no selection present
@@ -314,20 +349,19 @@
                     index = cindex
                 else:
                     line = lineFrom
-                    index = indexFrom - 1
+                    index = indexFrom
             if self.ui.selectionCheckBox.isChecked() and \
-               line == self.__selection[0] and \
+               line == boundary[0] and \
                index >= 0 and \
-               index < self.__selection[1]:
+               index < boundary[1]:
                 ok = False
             
             if ok and index < 0:
                 line -= 1
                 if self.ui.selectionCheckBox.isChecked():
-                    if line < self.__selection[0]:
+                    if line < boundary[0]:
                         if self.ui.wrapCheckBox.isChecked():
-                            line = self.__selection[2]
-                            index = self.__selection[3]
+                            line, index = boundary[2:]
                         else:
                             ok = False
                     else:
@@ -343,10 +377,9 @@
                         index = aw.lineLength(line)
         else:
             if self.ui.selectionCheckBox.isChecked() and \
-               (lineFrom, indexFrom, lineTo, indexTo) == self.__selection:
+               (lineFrom, indexFrom, lineTo, indexTo) == boundary:
                 # initial call
-                line = self.__selection[0]
-                index = self.__selection[1]
+                line, index = boundary[:2]
             else:
                 line = lineTo
                 index = indexTo
@@ -362,19 +395,44 @@
         
         if ok and self.ui.selectionCheckBox.isChecked():
             lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
-            if (lineFrom == self.__selection[0] and indexFrom >= self.__selection[1]) or \
-               (lineFrom > self.__selection[0] and lineFrom < self.__selection[2]) or \
-               (lineFrom == self.__selection[2] and indexFrom <= self.__selection[3]):
+            if len(self.__selections) > 1:
+                for sel in self.__selections:
+                    if lineFrom == sel[0] and \
+                       indexFrom >= sel[1] and \
+                       indexTo <= sel[3]:
+                        ok = True
+                        break
+                else:
+                    ok = False
+            elif (lineFrom == boundary[0] and indexFrom >= boundary[1]) or \
+               (lineFrom > boundary[0] and lineFrom < boundary[2]) or \
+               (lineFrom == boundary[2] and indexFrom <= boundary[3]):
                 ok = True
             else:
-                if self.ui.wrapCheckBox.isChecked():
-                    # try it again
-                    if backwards:
-                        line = self.__selection[2]
-                        index = self.__selection[3]
+                ok = False
+            if not ok and len(self.__selections) > 1:
+                # try again
+                while not ok and \
+                      ((backwards and lineFrom >= boundary[0]) or \
+                       (not backwards and lineFrom <= boundary[2])):
+                    for ind in range(len(self.__selections)):
+                        if lineFrom == self.__selections[ind][0]:
+                            after = indexTo > self.__selections[ind][3]
+                            if backwards:
+                                if after:
+                                    line, index = self.__selections[ind][2:]
+                                else:
+                                    if ind > 0:
+                                        line, index = self.__selections[ind - 1][2:]
+                            else:
+                                if after:
+                                    if ind < len(self.__selections) - 1:
+                                        line, index = self.__selections[ind + 1][:2]
+                                else:
+                                    line, index = self.__selections[ind][:2]
+                            break
                     else:
-                        line = self.__selection[0]
-                        index = self.__selection[1]
+                        break
                     ok = aw.findFirst(txt,
                         self.ui.regexpCheckBox.isChecked(),
                         self.ui.caseCheckBox.isChecked(),
@@ -384,23 +442,52 @@
                         line, index)
                     if ok:
                         lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
-                        if (lineFrom == self.__selection[0] and \
-                            indexFrom >= self.__selection[1]) or \
-                           (lineFrom > self.__selection[0] and \
-                            lineFrom < self.__selection[2]) or \
-                           (lineFrom == self.__selection[2] \
-                            and indexFrom <= self.__selection[3]):
+                        if lineFrom < boundary[0] or lineFrom > boundary[2] or \
+                           indexFrom < boundary[1] or indexFrom > boundary[3] or \
+                           indexTo < boundary[1] or indexTo > boundary[3]:
+                            ok = False
+                            break
+            if not ok:
+                if self.ui.wrapCheckBox.isChecked():
+                    # try it again
+                    if backwards:
+                        line, index = boundary[2:]
+                    else:
+                        line, index = boundary[:2]
+                    ok = aw.findFirst(txt,
+                        self.ui.regexpCheckBox.isChecked(),
+                        self.ui.caseCheckBox.isChecked(),
+                        self.ui.wordCheckBox.isChecked(),
+                        self.ui.wrapCheckBox.isChecked(),
+                        not backwards,
+                        line, index)
+                    if ok:
+                        lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
+                        if len(self.__selections) > 1:
+                            for sel in self.__selections:
+                                if lineFrom == sel[0] and \
+                                   indexFrom >= sel[1] and \
+                                   indexTo <= sel[3]:
+                                    ok = True
+                                    break
+                            else:
+                                ok = False
+                        elif (lineFrom == boundary[0] and \
+                            indexFrom >= boundary[1]) or \
+                           (lineFrom > boundary[0] and \
+                            lineFrom < boundary[2]) or \
+                           (lineFrom == boundary[2] \
+                            and indexFrom <= boundary[3]):
                             ok = True
                         else:
                             ok = False
-                            aw.selectAll(False)
-                            aw.setCursorPosition(cline, cindex)
-                            aw.ensureCursorVisible()
                 else:
                     ok = False
-                    aw.selectAll(False)
-                    aw.setCursorPosition(cline, cindex)
-                    aw.ensureCursorVisible()
+            
+            if not ok:
+                aw.selectAll(False)
+                aw.setCursorPosition(cline, cindex)
+                aw.ensureCursorVisible()
         
         self.__finding = False
         
@@ -457,16 +544,17 @@
         """
         if not self.__finding:
             if editor.hasSelectedText():
-                line1, index1, line2, index2 = editor.getSelection()
+                selections = editor.getSelections()
+                line1, index1, line2, index2 = self.__selectionBoundary(selections)
                 if line1 != line2:
                     self.ui.selectionCheckBox.setEnabled(True)
                     self.ui.selectionCheckBox.setChecked(True)
-                    self.__selection = (line1, index1, line2, index2)
+                    self.__selections = selections
                     return
             
             self.ui.selectionCheckBox.setEnabled(False)
             self.ui.selectionCheckBox.setChecked(False)
-            self.__selection = None
+            self.__selections = []
 
     @pyqtSlot()
     def on_replaceButton_clicked(self):
@@ -550,9 +638,9 @@
         
         aw = self.viewmanager.activeWindow()
         cline, cindex = aw.getCursorPosition()
+        boundary = self.__selectionBoundary()
         if self.ui.selectionCheckBox.isChecked():
-            line = self.__selection[0]
-            index = self.__selection[1]
+            line, index = boundary[:2]
         else:
             line = 0
             index = 0
@@ -564,12 +652,49 @@
         
         if ok and self.ui.selectionCheckBox.isChecked():
             lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
-            if (lineFrom == self.__selection[0] and indexFrom >= self.__selection[1]) or \
-               (lineFrom > self.__selection[0] and lineFrom < self.__selection[2]) or \
-               (lineFrom == self.__selection[2] and indexFrom <= self.__selection[3]):
+            if len(self.__selections) > 1:
+                for sel in self.__selections:
+                    if lineFrom == sel[0] and \
+                       indexFrom >= sel[1] and \
+                       indexTo <= sel[3]:
+                        ok = True
+                        break
+                else:
+                    ok = False
+            elif (lineFrom == boundary[0] and indexFrom >= boundary[1]) or \
+               (lineFrom > boundary[0] and lineFrom < boundary[2]) or \
+               (lineFrom == boundary[2] and indexFrom <= boundary[3]):
                 ok = True
             else:
                 ok = False
+            if not ok and len(self.__selections) > 1:
+                # try again
+                while not ok and lineFrom <= boundary[2]:
+                    for ind in range(len(self.__selections)):
+                        if lineFrom == self.__selections[ind][0]:
+                            after = indexTo > self.__selections[ind][3]
+                            if after:
+                                if ind < len(self.__selections) - 1:
+                                    line, index = self.__selections[ind + 1][:2]
+                            else:
+                                line, index = self.__selections[ind][:2]
+                        break
+                    else:
+                        break
+                    ok = aw.findFirst(ftxt,
+                            self.ui.regexpCheckBox.isChecked(),
+                            self.ui.caseCheckBox.isChecked(),
+                            self.ui.wordCheckBox.isChecked(),
+                            False, True, line, index)
+                    if ok:
+                        lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
+                        if lineFrom < boundary[0] or lineFrom > boundary[2] or \
+                           indexFrom < boundary[1] or indexFrom > boundary[3] or \
+                           indexTo < boundary[1] or indexTo > boundary[3]:
+                            ok = False
+                            break
+            
+            if not ok:
                 aw.selectAll(False)
                 aw.setCursorPosition(cline, cindex)
                 aw.ensureCursorVisible()

eric ide

mercurial