### Added code to limit the search function of the editor to rectangular selections as well.

Sun, 19 May 2013 20:54:04 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 19 May 2013 20:54:04 +0200
changeset 2660
5b834d76f617
parent 2659
7f46c5a7ed73
child 2661
0fd6f92ab2dd

Added code to limit the search function of the editor to rectangular selections as well.

```--- a/QScintilla/SearchReplaceWidget.py	Sun May 19 15:39:12 2013 +0200
+++ b/QScintilla/SearchReplaceWidget.py	Sun May 19 20:54:04 2013 +0200
@@ -144,9 +144,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.
@@ -263,10 +287,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,
@@ -278,7 +299,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):
@@ -299,12 +334,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,18 +349,17 @@
line = lineFrom
index = indexFrom - 1
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:
@@ -341,10 +375,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
@@ -360,19 +393,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(),
@@ -382,23 +440,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

@@ -454,17 +541,18 @@
@param editor reference to the editor (Editor)
"""
if not self.__finding:
-            if editor.hasSelectedText() and not editor.selectionIsRectangle():
-                line1, index1, line2, index2 = editor.getSelection()
+            if editor.hasSelectedText():
+                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):
@@ -548,9 +636,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
@@ -562,9 +650,9 @@

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 (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```