QScintilla/SearchReplaceWidget.py

changeset 2660
5b834d76f617
parent 2650
1b495c651868
child 2661
0fd6f92ab2dd
equal deleted inserted replaced
2659:7f46c5a7ed73 2660:5b834d76f617
142 self.ui.findtextCombo.addAction(self.findPrevAct) 142 self.ui.findtextCombo.addAction(self.findPrevAct)
143 143
144 self.havefound = False 144 self.havefound = False
145 self.__pos = None 145 self.__pos = None
146 self.__findBackwards = False 146 self.__findBackwards = False
147 self.__selection = None 147 self.__selections = []
148 self.__finding = False 148 self.__finding = False
149 149
150 def __selectionBoundary(self, selections=None):
151 """
152 Private method to calculate the current selection boundary.
153
154 @param selections optional parameter giving the selections to
155 calculate the boundary for (list of tuples of four integer)
156 @return tuple of start line and index and end line and index
157 (tuple of four integer)
158 """
159 if selections is None:
160 selections = self.__selections
161 if selections:
162 lineNumbers = [sel[0] for sel in selections] + \
163 [sel[2] for sel in selections]
164 indexNumbers = [sel[1] for sel in selections] + \
165 [sel[3] for sel in selections]
166 startLine, startIndex, endLine, endIndex = (
167 min(lineNumbers), min(indexNumbers),
168 max(lineNumbers), max(indexNumbers))
169 else:
170 startLine, startIndex, endLine, endIndex = -1, -1, -1, -1
171
172 return startLine, startIndex, endLine, endIndex
173
150 def on_findtextCombo_editTextChanged(self, txt): 174 def on_findtextCombo_editTextChanged(self, txt):
151 """ 175 """
152 Private slot to enable/disable the find buttons. 176 Private slot to enable/disable the find buttons.
153 """ 177 """
154 if not txt: 178 if not txt:
261 lineFrom = 0 285 lineFrom = 0
262 indexFrom = 0 286 indexFrom = 0
263 lineTo = -1 287 lineTo = -1
264 indexTo = -1 288 indexTo = -1
265 if self.ui.selectionCheckBox.isChecked(): 289 if self.ui.selectionCheckBox.isChecked():
266 lineFrom = self.__selection[0] 290 lineFrom, indexFrom, lineTo, indexTo = self.__selectionBoundary()
267 indexFrom = self.__selection[1]
268 lineTo = self.__selection[2]
269 indexTo = self.__selection[3]
270 291
271 aw.clearSearchIndicators() 292 aw.clearSearchIndicators()
272 ok = aw.findFirstTarget(txt, 293 ok = aw.findFirstTarget(txt,
273 self.ui.regexpCheckBox.isChecked(), 294 self.ui.regexpCheckBox.isChecked(),
274 self.ui.caseCheckBox.isChecked(), 295 self.ui.caseCheckBox.isChecked(),
276 lineFrom, indexFrom, lineTo, indexTo) 297 lineFrom, indexFrom, lineTo, indexTo)
277 while ok: 298 while ok:
278 tgtPos, tgtLen = aw.getFoundTarget() 299 tgtPos, tgtLen = aw.getFoundTarget()
279 if tgtLen == 0: 300 if tgtLen == 0:
280 break 301 break
281 aw.setSearchIndicator(tgtPos, tgtLen) 302 if len(self.__selections) > 1:
303 lineFrom, indexFrom = aw.lineIndexFromPosition(tgtPos)
304 lineTo, indexTo = aw.lineIndexFromPosition(tgtPos + tgtLen)
305 for sel in self.__selections:
306 if lineFrom == sel[0] and \
307 indexFrom >= sel[1] and \
308 indexTo <= sel[3]:
309 indicate = True
310 break
311 else:
312 indicate = False
313 else:
314 indicate = True
315 if indicate:
316 aw.setSearchIndicator(tgtPos, tgtLen)
282 ok = aw.findNextTarget() 317 ok = aw.findNextTarget()
283 318
284 def __findNextPrev(self, txt, backwards): 319 def __findNextPrev(self, txt, backwards):
285 """ 320 """
286 Private method to find the next occurrence of the search text. 321 Private method to find the next occurrence of the search text.
297 aw = self.viewmanager.activeWindow() 332 aw = self.viewmanager.activeWindow()
298 cline, cindex = aw.getCursorPosition() 333 cline, cindex = aw.getCursorPosition()
299 334
300 ok = True 335 ok = True
301 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() 336 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
337 boundary = self.__selectionBoundary()
302 if backwards: 338 if backwards:
303 if self.ui.selectionCheckBox.isChecked() and \ 339 if self.ui.selectionCheckBox.isChecked() and \
304 (lineFrom, indexFrom, lineTo, indexTo) == self.__selection: 340 (lineFrom, indexFrom, lineTo, indexTo) == boundary:
305 # initial call 341 # initial call
306 line = self.__selection[2] 342 line, index = boundary[2:]
307 index = self.__selection[3]
308 else: 343 else:
309 if (lineFrom, indexFrom) == (-1, -1): 344 if (lineFrom, indexFrom) == (-1, -1):
310 # no selection present 345 # no selection present
311 line = cline 346 line = cline
312 index = cindex 347 index = cindex
313 else: 348 else:
314 line = lineFrom 349 line = lineFrom
315 index = indexFrom - 1 350 index = indexFrom - 1
316 if self.ui.selectionCheckBox.isChecked() and \ 351 if self.ui.selectionCheckBox.isChecked() and \
317 line == self.__selection[0] and \ 352 line == boundary[0] and \
318 index >= 0 and \ 353 index >= 0 and \
319 index < self.__selection[1]: 354 index < boundary[1]:
320 ok = False 355 ok = False
321 356
322 if ok and index < 0: 357 if ok and index < 0:
323 line -= 1 358 line -= 1
324 if self.ui.selectionCheckBox.isChecked(): 359 if self.ui.selectionCheckBox.isChecked():
325 if line < self.__selection[0]: 360 if line < boundary[0]:
326 if self.ui.wrapCheckBox.isChecked(): 361 if self.ui.wrapCheckBox.isChecked():
327 line = self.__selection[2] 362 line, index = boundary[2:]
328 index = self.__selection[3]
329 else: 363 else:
330 ok = False 364 ok = False
331 else: 365 else:
332 index = aw.lineLength(line) 366 index = aw.lineLength(line)
333 else: 367 else:
339 ok = False 373 ok = False
340 else: 374 else:
341 index = aw.lineLength(line) 375 index = aw.lineLength(line)
342 else: 376 else:
343 if self.ui.selectionCheckBox.isChecked() and \ 377 if self.ui.selectionCheckBox.isChecked() and \
344 (lineFrom, indexFrom, lineTo, indexTo) == self.__selection: 378 (lineFrom, indexFrom, lineTo, indexTo) == boundary:
345 # initial call 379 # initial call
346 line = self.__selection[0] 380 line, index = boundary[:2]
347 index = self.__selection[1]
348 else: 381 else:
349 line = lineTo 382 line = lineTo
350 index = indexTo 383 index = indexTo
351 384
352 if ok: 385 if ok:
358 not backwards, 391 not backwards,
359 line, index) 392 line, index)
360 393
361 if ok and self.ui.selectionCheckBox.isChecked(): 394 if ok and self.ui.selectionCheckBox.isChecked():
362 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() 395 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
363 if (lineFrom == self.__selection[0] and indexFrom >= self.__selection[1]) or \ 396 if len(self.__selections) > 1:
364 (lineFrom > self.__selection[0] and lineFrom < self.__selection[2]) or \ 397 for sel in self.__selections:
365 (lineFrom == self.__selection[2] and indexFrom <= self.__selection[3]): 398 if lineFrom == sel[0] and \
399 indexFrom >= sel[1] and \
400 indexTo <= sel[3]:
401 ok = True
402 break
403 else:
404 ok = False
405 elif (lineFrom == boundary[0] and indexFrom >= boundary[1]) or \
406 (lineFrom > boundary[0] and lineFrom < boundary[2]) or \
407 (lineFrom == boundary[2] and indexFrom <= boundary[3]):
366 ok = True 408 ok = True
367 else: 409 else:
368 if self.ui.wrapCheckBox.isChecked(): 410 ok = False
369 # try it again 411 if not ok and len(self.__selections) > 1:
370 if backwards: 412 # try again
371 line = self.__selection[2] 413 while not ok and \
372 index = self.__selection[3] 414 ((backwards and lineFrom >= boundary[0]) or \
415 (not backwards and lineFrom <= boundary[2])):
416 for ind in range(len(self.__selections)):
417 if lineFrom == self.__selections[ind][0]:
418 after = indexTo > self.__selections[ind][3]
419 if backwards:
420 if after:
421 line, index = self.__selections[ind][2:]
422 else:
423 if ind > 0:
424 line, index = self.__selections[ind - 1][2:]
425 else:
426 if after:
427 if ind < len(self.__selections) - 1:
428 line, index = self.__selections[ind + 1][:2]
429 else:
430 line, index = self.__selections[ind][:2]
431 break
373 else: 432 else:
374 line = self.__selection[0] 433 break
375 index = self.__selection[1]
376 ok = aw.findFirst(txt, 434 ok = aw.findFirst(txt,
377 self.ui.regexpCheckBox.isChecked(), 435 self.ui.regexpCheckBox.isChecked(),
378 self.ui.caseCheckBox.isChecked(), 436 self.ui.caseCheckBox.isChecked(),
379 self.ui.wordCheckBox.isChecked(), 437 self.ui.wordCheckBox.isChecked(),
380 self.ui.wrapCheckBox.isChecked(), 438 self.ui.wrapCheckBox.isChecked(),
381 not backwards, 439 not backwards,
382 line, index) 440 line, index)
383 if ok: 441 if ok:
384 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() 442 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
385 if (lineFrom == self.__selection[0] and \ 443 if lineFrom < boundary[0] or lineFrom > boundary[2] or \
386 indexFrom >= self.__selection[1]) or \ 444 indexFrom < boundary[1] or indexFrom > boundary[3] or \
387 (lineFrom > self.__selection[0] and \ 445 indexTo < boundary[1] or indexTo > boundary[3]:
388 lineFrom < self.__selection[2]) or \ 446 ok = False
389 (lineFrom == self.__selection[2] \ 447 break
390 and indexFrom <= self.__selection[3]): 448 if not ok:
449 if self.ui.wrapCheckBox.isChecked():
450 # try it again
451 if backwards:
452 line, index = boundary[2:]
453 else:
454 line, index = boundary[:2]
455 ok = aw.findFirst(txt,
456 self.ui.regexpCheckBox.isChecked(),
457 self.ui.caseCheckBox.isChecked(),
458 self.ui.wordCheckBox.isChecked(),
459 self.ui.wrapCheckBox.isChecked(),
460 not backwards,
461 line, index)
462 if ok:
463 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
464 if len(self.__selections) > 1:
465 for sel in self.__selections:
466 if lineFrom == sel[0] and \
467 indexFrom >= sel[1] and \
468 indexTo <= sel[3]:
469 ok = True
470 break
471 else:
472 ok = False
473 elif (lineFrom == boundary[0] and \
474 indexFrom >= boundary[1]) or \
475 (lineFrom > boundary[0] and \
476 lineFrom < boundary[2]) or \
477 (lineFrom == boundary[2] \
478 and indexFrom <= boundary[3]):
391 ok = True 479 ok = True
392 else: 480 else:
393 ok = False 481 ok = False
394 aw.selectAll(False)
395 aw.setCursorPosition(cline, cindex)
396 aw.ensureCursorVisible()
397 else: 482 else:
398 ok = False 483 ok = False
399 aw.selectAll(False) 484
400 aw.setCursorPosition(cline, cindex) 485 if not ok:
401 aw.ensureCursorVisible() 486 aw.selectAll(False)
487 aw.setCursorPosition(cline, cindex)
488 aw.ensureCursorVisible()
402 489
403 self.__finding = False 490 self.__finding = False
404 491
405 return ok 492 return ok
406 493
452 Public slot to update the selection check box. 539 Public slot to update the selection check box.
453 540
454 @param editor reference to the editor (Editor) 541 @param editor reference to the editor (Editor)
455 """ 542 """
456 if not self.__finding: 543 if not self.__finding:
457 if editor.hasSelectedText() and not editor.selectionIsRectangle(): 544 if editor.hasSelectedText():
458 line1, index1, line2, index2 = editor.getSelection() 545 selections = editor.getSelections()
546 line1, index1, line2, index2 = self.__selectionBoundary(selections)
459 if line1 != line2: 547 if line1 != line2:
460 self.ui.selectionCheckBox.setEnabled(True) 548 self.ui.selectionCheckBox.setEnabled(True)
461 self.ui.selectionCheckBox.setChecked(True) 549 self.ui.selectionCheckBox.setChecked(True)
462 self.__selection = (line1, index1, line2, index2) 550 self.__selections = selections
463 return 551 return
464 552
465 self.ui.selectionCheckBox.setEnabled(False) 553 self.ui.selectionCheckBox.setEnabled(False)
466 self.ui.selectionCheckBox.setChecked(False) 554 self.ui.selectionCheckBox.setChecked(False)
467 self.__selection = None 555 self.__selections = []
468 556
469 @pyqtSlot() 557 @pyqtSlot()
470 def on_replaceButton_clicked(self): 558 def on_replaceButton_clicked(self):
471 """ 559 """
472 Private slot to replace one occurrence of text. 560 Private slot to replace one occurrence of text.
546 self.ui.replacetextCombo.clear() 634 self.ui.replacetextCombo.clear()
547 self.ui.replacetextCombo.addItems(self.replaceHistory) 635 self.ui.replacetextCombo.addItems(self.replaceHistory)
548 636
549 aw = self.viewmanager.activeWindow() 637 aw = self.viewmanager.activeWindow()
550 cline, cindex = aw.getCursorPosition() 638 cline, cindex = aw.getCursorPosition()
639 boundary = self.__selectionBoundary()
551 if self.ui.selectionCheckBox.isChecked(): 640 if self.ui.selectionCheckBox.isChecked():
552 line = self.__selection[0] 641 line, index = boundary[:2]
553 index = self.__selection[1]
554 else: 642 else:
555 line = 0 643 line = 0
556 index = 0 644 index = 0
557 ok = aw.findFirst(ftxt, 645 ok = aw.findFirst(ftxt,
558 self.ui.regexpCheckBox.isChecked(), 646 self.ui.regexpCheckBox.isChecked(),
560 self.ui.wordCheckBox.isChecked(), 648 self.ui.wordCheckBox.isChecked(),
561 False, True, line, index) 649 False, True, line, index)
562 650
563 if ok and self.ui.selectionCheckBox.isChecked(): 651 if ok and self.ui.selectionCheckBox.isChecked():
564 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() 652 lineFrom, indexFrom, lineTo, indexTo = aw.getSelection()
565 if (lineFrom == self.__selection[0] and indexFrom >= self.__selection[1]) or \ 653 if (lineFrom == boundary[0] and indexFrom >= boundary[1]) or \
566 (lineFrom > self.__selection[0] and lineFrom < self.__selection[2]) or \ 654 (lineFrom > boundary[0] and lineFrom < boundary[2]) or \
567 (lineFrom == self.__selection[2] and indexFrom <= self.__selection[3]): 655 (lineFrom == boundary[2] and indexFrom <= boundary[3]):
568 ok = True 656 ok = True
569 else: 657 else:
570 ok = False 658 ok = False
571 aw.selectAll(False) 659 aw.selectAll(False)
572 aw.setCursorPosition(cline, cindex) 660 aw.setCursorPosition(cline, cindex)

eric ide

mercurial