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