--- a/eric6/QScintilla/SearchReplaceWidget.py Mon Feb 22 19:15:06 2021 +0100 +++ b/eric6/QScintilla/SearchReplaceWidget.py Mon Feb 22 19:30:16 2021 +0100 @@ -7,7 +7,10 @@ Module implementing the search and replace widget. """ +import re + from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot, QEvent +from PyQt5.QtGui import QColor, QPalette from PyQt5.QtWidgets import ( QWidget, QHBoxLayout, QToolButton, QScrollArea, QSizePolicy, QFrame ) @@ -131,6 +134,8 @@ UI.PixmapCache.getIcon("1leftarrow")) self.ui.findNextButton.setIcon( UI.PixmapCache.getIcon("1rightarrow")) + self.ui.extendButton.setIcon( + UI.PixmapCache.getIcon("2rightarrow")) if replace: self.ui.replaceButton.setIcon( @@ -149,6 +154,16 @@ self.ui.replacetextCombo.lineEdit().returnPressed.connect( self.on_replaceButton_clicked) + self.ui.findtextCombo.lineEdit().textEdited.connect(self.__quickSearch) + self.ui.caseCheckBox.toggled.connect( + self.__updateQuickSearchMarkers) + self.ui.wordCheckBox.toggled.connect( + self.__updateQuickSearchMarkers) + self.ui.regexpCheckBox.toggled.connect( + self.__updateQuickSearchMarkers) + self.ui.selectionCheckBox.toggled.connect( + self.__updateQuickSearchMarkers) + # define actions self.findNextAct = E5Action( self.tr('Find Next'), @@ -324,27 +339,154 @@ return startLine, startIndex, endLine, endIndex + @pyqtSlot(str) def on_findtextCombo_editTextChanged(self, txt): """ Private slot to enable/disable the find buttons. - @param txt text of the find text combo (string) + @param txt text of the find text combo + @type str + """ + enable = bool(txt) + + self.__setFindNextEnabled(enable) + self.__setFindPrevEnabled(enable) + self.ui.extendButton.setEnabled(enable) + if self.__replace: + self.__setReplaceSelectionEnabled(False) + self.__setReplaceAndSearchEnabled(False) + self.__setReplaceAllEnabled(enable) + + @pyqtSlot(str) + def __quickSearch(self, txt): + """ + Private slot to search for the entered text while typing. + + @param txt text of the search edit + @type str """ + aw = self.__viewmanager.activeWindow() + aw.hideFindIndicator() + if Preferences.getEditor("QuickSearchMarkersEnabled"): + self.__quickSearchMarkOccurrences(txt) + + lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() + posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and + self.ui.regexpCheckBox.isChecked()) + cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and + self.ui.regexpCheckBox.isChecked()) + ok = aw.findFirst( + txt, + self.ui.regexpCheckBox.isChecked(), + self.ui.caseCheckBox.isChecked(), + self.ui.wordCheckBox.isChecked(), + self.ui.wrapCheckBox.isChecked(), + not self.__findBackwards, + lineFrom, indexFrom, + posix=posixMode, + cxx11=cxx11Mode + ) + if ok: + sline, sindex, eline, eindex = aw.getSelection() + aw.showFindIndicator(sline, sindex, eline, eindex) + if not txt: - self.__setFindNextEnabled(False) - self.__setFindPrevEnabled(False) - if self.__replace: - self.__setReplaceSelectionEnabled(False) - self.__setReplaceAndSearchEnabled(False) - self.__setReplaceAllEnabled(False) + ok = True # reset the color in case of an empty text + + self.__setSearchEditColors(ok) + + def __quickSearchMarkOccurrences(self, txt): + """ + Private method to mark all occurrences of the search text. + + @param txt text to search for (string) + """ + aw = self.__viewmanager.activeWindow() + + lineFrom = 0 + indexFrom = 0 + lineTo = -1 + indexTo = -1 + + aw.clearSearchIndicators() + posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and + self.ui.regexpCheckBox.isChecked()) + cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and + self.ui.regexpCheckBox.isChecked()) + ok = aw.findFirstTarget( + txt, + self.ui.regexpCheckBox.isChecked(), + self.ui.caseCheckBox.isChecked(), + self.ui.wordCheckBox.isChecked(), + lineFrom, indexFrom, lineTo, indexTo, + posix=posixMode, + cxx11=cxx11Mode + ) + while ok: + tgtPos, tgtLen = aw.getFoundTarget() + aw.setSearchIndicator(tgtPos, tgtLen) + ok = aw.findNextTarget() + + def __setSearchEditColors(self, ok): + """ + Private method to set the search edit colors. + + @param ok flag indicating a match + @type bool + """ + if not ok: + palette = self.ui.findtextCombo.lineEdit().palette() + palette.setColor(QPalette.Base, QColor("red")) + palette.setColor(QPalette.Text, QColor("white")) + self.ui.findtextCombo.lineEdit().setPalette(palette) else: - self.__setFindNextEnabled(True) - self.__setFindPrevEnabled(True) - if self.__replace: - self.__setReplaceSelectionEnabled(False) - self.__setReplaceAndSearchEnabled(False) - self.__setReplaceAllEnabled(True) - + palette = self.ui.findtextCombo.lineEdit().palette() + palette.setColor( + QPalette.Base, + self.ui.findtextCombo.palette().color(QPalette.Base)) + palette.setColor( + QPalette.Text, + self.ui.findtextCombo.palette().color(QPalette.Text)) + self.ui.findtextCombo.lineEdit().setPalette(palette) + + @pyqtSlot() + def on_extendButton_clicked(self): + """ + Private slot to handle the quicksearch extend action. + """ + aw = self.__viewmanager.activeWindow() + if aw is None: + return + + txt = self.ui.findtextCombo.currentText() + if not txt: + return + + line, index = aw.getCursorPosition() + text = aw.text(line) + + rx = re.compile(r'[^\w_]') + match = rx.search(text, index) + if match: + end = match.start() + if end > index: + ext = text[index:end] + txt += ext + self.ui.findtextCombo.setEditText(txt) + self.ui.findtextCombo.lineEdit().selectAll() + self.__quickSearch(txt) + + @pyqtSlot(bool) + def __updateQuickSearchMarkers(self, on): + """ + Private slot to handle the selection of the various check boxes. + + @param on status of the check box (ignored) + @type bool + """ + txt = self.ui.findtextCombo.currentText() + self.__quickSearch(txt) + @pyqtSlot() def on_findNextButton_clicked(self): """ @@ -376,6 +518,7 @@ self.searchListChanged.emit() ok = self.__findNextPrev(txt, False) + self.__setSearchEditColors(ok) if ok: if self.__replace: self.__setReplaceSelectionEnabled(True) @@ -413,6 +556,7 @@ self.searchListChanged.emit() ok = self.__findNextPrev(txt, True) + self.__setSearchEditColors(ok) if ok: if self.__replace: self.__setReplaceSelectionEnabled(True) @@ -716,6 +860,7 @@ """ self.__replace = False + self.__setSearchEditColors(True) self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) self.ui.findtextCombo.setEditText(text) @@ -831,6 +976,7 @@ if searchNext: ok = self.__findNextPrev(ftxt, self.__findBackwards) + self.__setSearchEditColors(ok) if not ok: self.__setReplaceSelectionEnabled(False) @@ -841,6 +987,7 @@ else: self.__setReplaceSelectionEnabled(False) self.__setReplaceAndSearchEnabled(False) + self.__setSearchEditColors(True) self.__finding = False @@ -1003,6 +1150,7 @@ """ self.__replace = True + self.__setSearchEditColors(True) self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) self.ui.findtextCombo.setEditText(text)