--- a/src/eric7/QScintilla/SearchReplaceWidget.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/QScintilla/SearchReplaceWidget.py Wed Jul 13 14:55:47 2022 +0200 @@ -12,7 +12,12 @@ from PyQt6.QtCore import pyqtSignal, Qt, pyqtSlot, QEvent from PyQt6.QtWidgets import ( - QWidget, QHBoxLayout, QToolButton, QScrollArea, QSizePolicy, QFrame + QWidget, + QHBoxLayout, + QToolButton, + QScrollArea, + QSizePolicy, + QFrame, ) from .Editor import Editor @@ -28,15 +33,16 @@ class SearchReplaceWidget(QWidget): """ Class implementing the search and replace widget. - + @signal searchListChanged() emitted to indicate a change of the search list """ + searchListChanged = pyqtSignal() - + def __init__(self, replace, vm, parent=None, sliding=False): """ Constructor - + @param replace flag indicating a replace widget is called @param vm reference to the viewmanager object @param parent parent widget of this widget (QWidget) @@ -44,18 +50,19 @@ sliding widget (boolean) """ super().__init__(parent) - + self.__viewmanager = vm self.__isMiniEditor = vm is parent self.__replace = replace self.__sliding = sliding if sliding: self.__topWidget = parent - - self.findHistory = vm.getSRHistory('search') + + self.findHistory = vm.getSRHistory("search") if replace: from .Ui_ReplaceWidget import Ui_ReplaceWidget - self.replaceHistory = vm.getSRHistory('replace') + + self.replaceHistory = vm.getSRHistory("replace") self.ui = Ui_ReplaceWidget() whatsThis = self.tr( """<b>Find and Replace</b> @@ -67,6 +74,7 @@ ) else: from .Ui_SearchWidget import Ui_SearchWidget + self.ui = Ui_SearchWidget() whatsThis = self.tr( """<b>Find</b> @@ -78,7 +86,7 @@ self.ui.setupUi(self) if not replace: self.ui.wrapCheckBox.setChecked(True) - + whatsThis += self.tr( """<table border="0"> <tr><td><code>.</code></td><td>Matches any character</td></tr> @@ -127,100 +135,117 @@ """ ) self.setWhatsThis(whatsThis) - + # set icons self.ui.closeButton.setIcon(UI.PixmapCache.getIcon("close")) - self.ui.findPrevButton.setIcon( - UI.PixmapCache.getIcon("1leftarrow")) - self.ui.findNextButton.setIcon( - UI.PixmapCache.getIcon("1rightarrow")) - self.ui.extendButton.setIcon( - UI.PixmapCache.getIcon("2rightarrow")) - + self.ui.findPrevButton.setIcon(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( - UI.PixmapCache.getIcon("editReplace")) + self.ui.replaceButton.setIcon(UI.PixmapCache.getIcon("editReplace")) self.ui.replaceSearchButton.setIcon( - UI.PixmapCache.getIcon("editReplaceSearch")) - self.ui.replaceAllButton.setIcon( - UI.PixmapCache.getIcon("editReplaceAll")) - + UI.PixmapCache.getIcon("editReplaceSearch") + ) + self.ui.replaceAllButton.setIcon(UI.PixmapCache.getIcon("editReplaceAll")) + # set line edit completers self.ui.findtextCombo.setCompleter(None) self.ui.findtextCombo.lineEdit().returnPressed.connect( - self.__findByReturnPressed) + self.__findByReturnPressed + ) if replace: self.ui.replacetextCombo.setCompleter(None) self.ui.replacetextCombo.lineEdit().returnPressed.connect( - self.on_replaceButton_clicked) - + 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.__findtextComboStyleSheet = ( - self.ui.findtextCombo.styleSheet() - ) - + self.ui.caseCheckBox.toggled.connect(self.__updateQuickSearchMarkers) + self.ui.wordCheckBox.toggled.connect(self.__updateQuickSearchMarkers) + self.ui.regexpCheckBox.toggled.connect(self.__updateQuickSearchMarkers) + + self.__findtextComboStyleSheet = self.ui.findtextCombo.styleSheet() + # define actions self.findNextAct = EricAction( - self.tr('Find Next'), - self.tr('Find Next'), - 0, 0, self, 'search_widget_find_next') + self.tr("Find Next"), + self.tr("Find Next"), + 0, + 0, + self, + "search_widget_find_next", + ) self.findNextAct.triggered.connect(self.on_findNextButton_clicked) self.findNextAct.setShortcutContext( - Qt.ShortcutContext.WidgetWithChildrenShortcut) - + Qt.ShortcutContext.WidgetWithChildrenShortcut + ) + self.findPrevAct = EricAction( - self.tr('Find Prev'), - self.tr('Find Prev'), - 0, 0, self, 'search_widget_find_prev') + self.tr("Find Prev"), + self.tr("Find Prev"), + 0, + 0, + self, + "search_widget_find_prev", + ) self.findPrevAct.triggered.connect(self.on_findPrevButton_clicked) self.findPrevAct.setShortcutContext( - Qt.ShortcutContext.WidgetWithChildrenShortcut) - + Qt.ShortcutContext.WidgetWithChildrenShortcut + ) + if replace: self.replaceAndSearchAct = EricAction( self.tr("Replace and Search"), self.tr("Replace and Search"), - 0, 0, self, "replace_widget_replace_search") + 0, + 0, + self, + "replace_widget_replace_search", + ) self.replaceAndSearchAct.triggered.connect( - self.on_replaceSearchButton_clicked) + self.on_replaceSearchButton_clicked + ) self.replaceAndSearchAct.setEnabled(False) self.replaceAndSearchAct.setShortcutContext( - Qt.ShortcutContext.WidgetWithChildrenShortcut) - + Qt.ShortcutContext.WidgetWithChildrenShortcut + ) + self.replaceSelectionAct = EricAction( self.tr("Replace Occurrence"), self.tr("Replace Occurrence"), - 0, 0, self, "replace_widget_replace_occurrence") - self.replaceSelectionAct.triggered.connect( - self.on_replaceButton_clicked) + 0, + 0, + self, + "replace_widget_replace_occurrence", + ) + self.replaceSelectionAct.triggered.connect(self.on_replaceButton_clicked) self.replaceSelectionAct.setEnabled(False) self.replaceSelectionAct.setShortcutContext( - Qt.ShortcutContext.WidgetWithChildrenShortcut) - + Qt.ShortcutContext.WidgetWithChildrenShortcut + ) + self.replaceAllAct = EricAction( self.tr("Replace All"), self.tr("Replace All"), - 0, 0, self, "replace_widget_replace_all") - self.replaceAllAct.triggered.connect( - self.on_replaceAllButton_clicked) + 0, + 0, + self, + "replace_widget_replace_all", + ) + self.replaceAllAct.triggered.connect(self.on_replaceAllButton_clicked) self.replaceAllAct.setEnabled(False) self.replaceAllAct.setShortcutContext( - Qt.ShortcutContext.WidgetWithChildrenShortcut) - + Qt.ShortcutContext.WidgetWithChildrenShortcut + ) + self.addAction(self.findNextAct) self.addAction(self.findPrevAct) if replace: self.addAction(self.replaceAndSearchAct) self.addAction(self.replaceSelectionAct) self.addAction(self.replaceAllAct) - + # disable search and replace buttons and actions self.__setFindNextEnabled(False) self.__setFindPrevEnabled(False) @@ -228,97 +253,98 @@ self.__setReplaceAndSearchEnabled(False) self.__setReplaceSelectionEnabled(False) self.__setReplaceAllEnabled(False) - + self.adjustSize() - + self.havefound = False self.__pos = None self.__findBackwards = False self.__selections = [] self.__finding = False - + def __setShortcuts(self): """ Private method to set the local action's shortcuts to the same key sequences as in the view manager. """ if not self.__isMiniEditor: - self.findNextAct.setShortcuts( - self.__viewmanager.searchNextAct.shortcuts()) - self.findPrevAct.setShortcuts( - self.__viewmanager.searchPrevAct.shortcuts()) - + self.findNextAct.setShortcuts(self.__viewmanager.searchNextAct.shortcuts()) + self.findPrevAct.setShortcuts(self.__viewmanager.searchPrevAct.shortcuts()) + if self.__replace: self.replaceAndSearchAct.setShortcuts( - self.__viewmanager.replaceAndSearchAct.shortcuts()) + self.__viewmanager.replaceAndSearchAct.shortcuts() + ) self.replaceSelectionAct.setShortcuts( - self.__viewmanager.replaceSelectionAct.shortcuts()) + self.__viewmanager.replaceSelectionAct.shortcuts() + ) self.replaceAllAct.setShortcuts( - self.__viewmanager.replaceAllAct.shortcuts()) - + self.__viewmanager.replaceAllAct.shortcuts() + ) + def __setFindNextEnabled(self, enable): """ Private method to set the enabled state of "Find Next". - + @param enable flag indicating the enable state to be set @type bool """ self.ui.findNextButton.setEnabled(enable) self.findNextAct.setEnabled(enable) - + def __setFindPrevEnabled(self, enable): """ Private method to set the enabled state of "Find Prev". - + @param enable flag indicating the enable state to be set @type bool """ self.ui.findPrevButton.setEnabled(enable) self.findPrevAct.setEnabled(enable) - + def __setReplaceAndSearchEnabled(self, enable): """ Private method to set the enabled state of "Replace And Search". - + @param enable flag indicating the enable state to be set @type bool """ self.ui.replaceSearchButton.setEnabled(enable) self.replaceAndSearchAct.setEnabled(enable) - + def __setReplaceSelectionEnabled(self, enable): """ Private method to set the enabled state of "Replace Occurrence". - + @param enable flag indicating the enable state to be set @type bool """ self.ui.replaceButton.setEnabled(enable) self.replaceSelectionAct.setEnabled(enable) - + def __setReplaceAllEnabled(self, enable): """ Private method to set the enabled state of "Replace All". - + @param enable flag indicating the enable state to be set @type bool """ self.ui.replaceAllButton.setEnabled(enable) self.replaceAllAct.setEnabled(enable) - + def changeEvent(self, evt): """ Protected method handling state changes. - + @param evt event containing the state change (QEvent) """ if evt.type() == QEvent.Type.FontChange: self.adjustSize() - + 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 @@ -327,32 +353,33 @@ if selections is None: selections = self.__selections if selections: - lineNumbers = ( - [sel[0] for sel in selections] + - [sel[2] for sel in 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), ) - 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 - + @pyqtSlot(str) def on_findtextCombo_editTextChanged(self, txt): """ Private slot to enable/disable the find buttons. - + @param txt text of the find text combo @type str """ enable = bool(txt) - + self.__setFindNextEnabled(enable) self.__setFindPrevEnabled(enable) self.ui.extendButton.setEnabled(enable) @@ -360,12 +387,12 @@ 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 """ @@ -373,12 +400,16 @@ 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()) + 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(), @@ -386,55 +417,63 @@ self.ui.wordCheckBox.isChecked(), self.ui.wrapCheckBox.isChecked(), not self.__findBackwards, - lineFrom, indexFrom, + lineFrom, + indexFrom, posix=posixMode, - cxx11=cxx11Mode + cxx11=cxx11Mode, ) if ok: sline, sindex, eline, eindex = aw.getSelection() aw.showFindIndicator(sline, sindex, eline, eindex) - + if not txt: - ok = True # reset the color in case of an empty text - + 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()) + 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, + lineFrom, + indexFrom, + lineTo, + indexTo, posix=posixMode, - cxx11=cxx11Mode + 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 """ @@ -443,9 +482,8 @@ "color: #000000; background-color: #ff6666;" ) else: - self.ui.findtextCombo.setStyleSheet( - self.__findtextComboStyleSheet) - + self.ui.findtextCombo.setStyleSheet(self.__findtextComboStyleSheet) + @pyqtSlot() def on_extendButton_clicked(self): """ @@ -454,15 +492,15 @@ 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_]') + + rx = re.compile(r"[^\w_]") match = rx.search(text, index) if match: end = match.start() @@ -472,25 +510,25 @@ 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): """ Private slot to find the next occurrence of text. """ self.findNext() - + def findNext(self): """ Public slot to find the next occurrence of text. @@ -501,10 +539,10 @@ else: self.__viewmanager.showSearchWidget() return - + self.__findBackwards = False txt = self.ui.findtextCombo.currentText() - + # This moves any previous occurrence of this statement to the head # of the list and updates the combobox if txt in self.findHistory: @@ -513,7 +551,7 @@ self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) self.searchListChanged.emit() - + ok = self.__findNextPrev(txt, False) self.__setSearchEditColors(ok) if ok: @@ -522,8 +560,8 @@ self.__setReplaceAndSearchEnabled(True) else: EricMessageBox.information( - self, self.windowTitle(), - self.tr("'{0}' was not found.").format(txt)) + self, self.windowTitle(), self.tr("'{0}' was not found.").format(txt) + ) @pyqtSlot() def on_findPrevButton_clicked(self): @@ -531,7 +569,7 @@ Private slot to find the previous occurrence of text. """ self.findPrev() - + def findPrev(self): """ Public slot to find the next previous of text. @@ -539,10 +577,10 @@ if not self.havefound or not self.ui.findtextCombo.currentText(): self.show(self.__viewmanager.textForFind()) return - + self.__findBackwards = True txt = self.ui.findtextCombo.currentText() - + # This moves any previous occurrence of this statement to the head # of the list and updates the combobox if txt in self.findHistory: @@ -551,7 +589,7 @@ self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) self.searchListChanged.emit() - + ok = self.__findNextPrev(txt, True) self.__setSearchEditColors(ok) if ok: @@ -560,9 +598,9 @@ self.__setReplaceAndSearchEnabled(True) else: EricMessageBox.information( - self, self.windowTitle(), - self.tr("'{0}' was not found.").format(txt)) - + self, self.windowTitle(), self.tr("'{0}' was not found.").format(txt) + ) + def __findByReturnPressed(self): """ Private slot to handle the returnPressed signal of the findtext @@ -572,11 +610,11 @@ self.findPrev() else: self.findNext() - + def __markOccurrences(self, txt): """ Private method to mark all occurrences of the search text. - + @param txt text to search for (string) """ aw = self.__viewmanager.activeWindow() @@ -586,19 +624,28 @@ indexTo = -1 if self.ui.selectionCheckBox.isChecked(): lineFrom, indexFrom, lineTo, indexTo = self.__selectionBoundary() - posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and - self.ui.regexpCheckBox.isChecked()) - cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and - self.ui.regexpCheckBox.isChecked()) - + posixMode = ( + Preferences.getEditor("SearchRegexpMode") == 0 + and self.ui.regexpCheckBox.isChecked() + ) + cxx11Mode = ( + Preferences.getEditor("SearchRegexpMode") == 1 + and self.ui.regexpCheckBox.isChecked() + ) + aw.clearSearchIndicators() ok = aw.findFirstTarget( txt, self.ui.regexpCheckBox.isChecked(), self.ui.caseCheckBox.isChecked(), self.ui.wordCheckBox.isChecked(), - lineFrom, indexFrom, lineTo, indexTo, - posix=posixMode, cxx11=cxx11Mode) + lineFrom, + indexFrom, + lineTo, + indexTo, + posix=posixMode, + cxx11=cxx11Mode, + ) while ok: tgtPos, tgtLen = aw.getFoundTarget() if tgtLen == 0: @@ -607,11 +654,7 @@ 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] - ): + if lineFrom == sel[0] and indexFrom >= sel[1] and indexTo <= sel[3]: indicate = True break else: @@ -624,31 +667,31 @@ with contextlib.suppress(AttributeError): aw.updateMarkerMap() # ignore it for MiniEditor - + def __findNextPrev(self, txt, backwards): """ Private method to find the next occurrence of the search text. - + @param txt text to search for (string) @param backwards flag indicating a backwards search (boolean) @return flag indicating success (boolean) """ self.__finding = True - + if Preferences.getEditor("SearchMarkersEnabled"): self.__markOccurrences(txt) - + aw = self.__viewmanager.activeWindow() aw.hideFindIndicator() cline, cindex = aw.getCursorPosition() - + ok = True lineFrom, indexFrom, lineTo, indexTo = aw.getSelection() boundary = self.__selectionBoundary() if backwards: if ( - self.ui.selectionCheckBox.isChecked() and - (lineFrom, indexFrom, lineTo, indexTo) == boundary + self.ui.selectionCheckBox.isChecked() + and (lineFrom, indexFrom, lineTo, indexTo) == boundary ): # initial call line, index = boundary[2:] @@ -661,13 +704,13 @@ line = lineFrom index = indexFrom if ( - self.ui.selectionCheckBox.isChecked() and - line == boundary[0] and - index >= 0 and - index < boundary[1] + self.ui.selectionCheckBox.isChecked() + and line == boundary[0] + and index >= 0 + and index < boundary[1] ): ok = False - + if ok and index < 0: line -= 1 if self.ui.selectionCheckBox.isChecked(): @@ -689,20 +732,24 @@ index = aw.lineLength(line) else: if ( - self.ui.selectionCheckBox.isChecked() and - (lineFrom, indexFrom, lineTo, indexTo) == boundary + self.ui.selectionCheckBox.isChecked() + and (lineFrom, indexFrom, lineTo, indexTo) == boundary ): # initial call line, index = boundary[:2] else: line = lineTo index = indexTo - + if ok: - posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and - self.ui.regexpCheckBox.isChecked()) - cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and - self.ui.regexpCheckBox.isChecked()) + 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(), @@ -710,37 +757,34 @@ self.ui.wordCheckBox.isChecked(), self.ui.wrapCheckBox.isChecked(), not backwards, - line, index, + line, + index, posix=posixMode, - cxx11=cxx11Mode) - + cxx11=cxx11Mode, + ) + if ok and self.ui.selectionCheckBox.isChecked(): 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] - ): + 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]) + (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 - ((backwards and lineFrom >= boundary[0]) or - (not backwards and lineFrom <= boundary[2])) + 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]: @@ -750,15 +794,11 @@ line, index = self.__selections[ind][2:] else: if ind > 0: - line, index = ( - self.__selections[ind - 1][2:] - ) + line, index = self.__selections[ind - 1][2:] else: if after: if ind < len(self.__selections) - 1: - line, index = ( - self.__selections[ind + 1][:2] - ) + line, index = self.__selections[ind + 1][:2] else: line, index = self.__selections[ind][:2] break @@ -771,20 +811,20 @@ self.ui.wordCheckBox.isChecked(), self.ui.wrapCheckBox.isChecked(), not backwards, - line, index, + line, + index, posix=posixMode, - cxx11=cxx11Mode) + cxx11=cxx11Mode, + ) if ok: - lineFrom, indexFrom, lineTo, indexTo = ( - aw.getSelection() - ) + 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] + 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 @@ -802,59 +842,56 @@ self.ui.wordCheckBox.isChecked(), self.ui.wrapCheckBox.isChecked(), not backwards, - line, index, + line, + index, posix=posixMode, - cxx11=cxx11Mode) + cxx11=cxx11Mode, + ) if ok: - lineFrom, indexFrom, lineTo, indexTo = ( - aw.getSelection() - ) + 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] + 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]) + (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 else: ok = False - + if not ok: aw.selectAll(False) aw.setCursorPosition(cline, cindex) aw.ensureCursorVisible() - + if ok: sline, sindex, eline, eindex = aw.getSelection() aw.showFindIndicator(sline, sindex, eline, eindex) - + self.__finding = False - + return ok - def __showFind(self, text=''): + def __showFind(self, text=""): """ Private method to display this widget in find mode. - + @param text text to be shown in the findtext edit (string) """ self.__replace = False - + self.__setSearchEditColors(True) self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) @@ -862,74 +899,72 @@ self.ui.findtextCombo.lineEdit().selectAll() self.ui.findtextCombo.setFocus() self.on_findtextCombo_editTextChanged(text) - + self.ui.caseCheckBox.setChecked(False) self.ui.wordCheckBox.setChecked(False) self.ui.wrapCheckBox.setChecked(True) self.ui.regexpCheckBox.setChecked(False) - + aw = self.__viewmanager.activeWindow() self.updateSelectionCheckBox(aw) - + self.havefound = True self.__findBackwards = False - + self.__setShortcuts() - + def selectionChanged(self, editor): """ Public slot tracking changes of selected text. - + @param editor reference to the editor @type Editor """ self.updateSelectionCheckBox(editor) - + @pyqtSlot(Editor) def updateSelectionCheckBox(self, editor): """ Public slot to update the selection check box. - + @param editor reference to the editor @type Editor """ if not self.__finding and isinstance(editor, Editor): if editor.hasSelectedText(): selections = editor.getSelections() - line1, index1, line2, index2 = ( - self.__selectionBoundary(selections) - ) + line1, index1, line2, index2 = self.__selectionBoundary(selections) if line1 != line2: self.ui.selectionCheckBox.setEnabled(True) self.ui.selectionCheckBox.setChecked(True) self.__selections = selections return - + self.ui.selectionCheckBox.setEnabled(False) self.ui.selectionCheckBox.setChecked(False) self.__selections = [] - + def replace(self): """ Public method to replace the current selection. """ if self.ui.replaceButton.isEnabled(): self.__doReplace(False) - + def replaceSearch(self): """ Public method to replace the current selection and search again. """ if self.ui.replaceSearchButton.isEnabled(): self.__doReplace(True) - + @pyqtSlot() def on_replaceButton_clicked(self): """ Private slot to replace one occurrence of text. """ self.__doReplace(False) - + @pyqtSlot() def on_replaceSearchButton_clicked(self): """ @@ -937,26 +972,26 @@ one. """ self.__doReplace(True) - + def __doReplace(self, searchNext): """ Private method to replace one occurrence of text. - + @param searchNext flag indicating to search for the next occurrence (boolean). """ self.__finding = True - + # Check enabled status due to dual purpose usage of this method if ( - not self.ui.replaceButton.isEnabled() and - not self.ui.replaceSearchButton.isEnabled() + not self.ui.replaceButton.isEnabled() + and not self.ui.replaceSearchButton.isEnabled() ): return - + ftxt = self.ui.findtextCombo.currentText() rtxt = self.ui.replacetextCombo.currentText() - + # This moves any previous occurrence of this statement to the head # of the list and updates the combobox if rtxt in self.replaceHistory: @@ -964,46 +999,48 @@ self.replaceHistory.insert(0, rtxt) self.ui.replacetextCombo.clear() self.ui.replacetextCombo.addItems(self.replaceHistory) - + aw = self.__viewmanager.activeWindow() aw.hideFindIndicator() aw.replace(rtxt) - + if searchNext: ok = self.__findNextPrev(ftxt, self.__findBackwards) self.__setSearchEditColors(ok) - + if not ok: self.__setReplaceSelectionEnabled(False) self.__setReplaceAndSearchEnabled(False) EricMessageBox.information( - self, self.windowTitle(), - self.tr("'{0}' was not found.").format(ftxt)) + self, + self.windowTitle(), + self.tr("'{0}' was not found.").format(ftxt), + ) else: self.__setReplaceSelectionEnabled(False) self.__setReplaceAndSearchEnabled(False) self.__setSearchEditColors(True) - + self.__finding = False - + def replaceAll(self): """ Public method to replace all occurrences. """ if self.ui.replaceAllButton.isEnabled(): self.on_replaceAllButton_clicked() - + @pyqtSlot() def on_replaceAllButton_clicked(self): """ Private slot to replace all occurrences of text. """ self.__finding = True - + replacements = 0 ftxt = self.ui.findtextCombo.currentText() rtxt = self.ui.replacetextCombo.currentText() - + # This moves any previous occurrence of this statement to the head # of the list and updates the combobox if ftxt in self.findHistory: @@ -1011,13 +1048,13 @@ self.findHistory.insert(0, ftxt) self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) - + if rtxt in self.replaceHistory: self.replaceHistory.remove(rtxt) self.replaceHistory.insert(0, rtxt) self.ui.replacetextCombo.clear() self.ui.replacetextCombo.addItems(self.replaceHistory) - + aw = self.__viewmanager.activeWindow() aw.hideFindIndicator() cline, cindex = aw.getCursorPosition() @@ -1027,36 +1064,40 @@ else: line = 0 index = 0 - posixMode = (Preferences.getEditor("SearchRegexpMode") == 0 and - self.ui.regexpCheckBox.isChecked()) - cxx11Mode = (Preferences.getEditor("SearchRegexpMode") == 1 and - self.ui.regexpCheckBox.isChecked()) + posixMode = ( + Preferences.getEditor("SearchRegexpMode") == 0 + and self.ui.regexpCheckBox.isChecked() + ) + cxx11Mode = ( + Preferences.getEditor("SearchRegexpMode") == 1 + and self.ui.regexpCheckBox.isChecked() + ) ok = aw.findFirst( ftxt, self.ui.regexpCheckBox.isChecked(), self.ui.caseCheckBox.isChecked(), self.ui.wordCheckBox.isChecked(), - False, True, line, index, + False, + True, + line, + index, posix=posixMode, - cxx11=cxx11Mode) - + cxx11=cxx11Mode, + ) + if ok and self.ui.selectionCheckBox.isChecked(): 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] - ): + 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]) + (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: @@ -1069,9 +1110,7 @@ after = indexTo > self.__selections[ind][3] if after: if ind < len(self.__selections) - 1: - line, index = ( - self.__selections[ind + 1][:2] - ) + line, index = self.__selections[ind + 1][:2] else: line, index = self.__selections[ind][:2] break @@ -1082,31 +1121,33 @@ self.ui.regexpCheckBox.isChecked(), self.ui.caseCheckBox.isChecked(), self.ui.wordCheckBox.isChecked(), - False, True, line, index, + False, + True, + line, + index, posix=posixMode, - cxx11=cxx11Mode) + cxx11=cxx11Mode, + ) if ok: - lineFrom, indexFrom, lineTo, indexTo = ( - aw.getSelection() - ) + 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] + 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() - + found = ok - + aw.beginUndoAction() wordWrap = self.ui.wrapCheckBox.isChecked() self.ui.wrapCheckBox.setChecked(False) @@ -1120,31 +1161,33 @@ self.ui.wrapCheckBox.setChecked(True) self.__setReplaceSelectionEnabled(False) self.__setReplaceAndSearchEnabled(False) - + if found: EricMessageBox.information( - self, self.windowTitle(), - self.tr("Replaced {0} occurrences.") - .format(replacements)) + self, + self.windowTitle(), + self.tr("Replaced {0} occurrences.").format(replacements), + ) else: EricMessageBox.information( - self, self.windowTitle(), - self.tr("Nothing replaced because '{0}' was not found.") - .format(ftxt)) - + self, + self.windowTitle(), + self.tr("Nothing replaced because '{0}' was not found.").format(ftxt), + ) + aw.setCursorPosition(cline, cindex) aw.ensureCursorVisible() - + self.__finding = False - - def __showReplace(self, text=''): + + def __showReplace(self, text=""): """ Private slot to display this widget in replace mode. - + @param text text to be shown in the findtext edit """ self.__replace = True - + self.__setSearchEditColors(True) self.ui.findtextCombo.clear() self.ui.findtextCombo.addItems(self.findHistory) @@ -1152,17 +1195,17 @@ self.ui.findtextCombo.lineEdit().selectAll() self.ui.findtextCombo.setFocus() self.on_findtextCombo_editTextChanged(text) - + self.ui.replacetextCombo.clear() self.ui.replacetextCombo.addItems(self.replaceHistory) - self.ui.replacetextCombo.setEditText('') - + self.ui.replacetextCombo.setEditText("") + self.ui.caseCheckBox.setChecked(False) self.ui.wordCheckBox.setChecked(False) self.ui.regexpCheckBox.setChecked(False) - + self.havefound = True - + aw = self.__viewmanager.activeWindow() self.updateSelectionCheckBox(aw) if aw.hasSelectedText(): @@ -1170,13 +1213,13 @@ if line1 == line2: aw.setSelection(line1, index1, line1, index1) self.findNext() - + self.__setShortcuts() - def show(self, text=''): + def show(self, text=""): """ Public slot to show the widget. - + @param text text to be shown in the findtext edit (string) """ if self.__replace: @@ -1194,16 +1237,16 @@ aw = self.__viewmanager.activeWindow() if aw: aw.hideFindIndicator() - + if self.__sliding: self.__topWidget.close() else: self.close() - + def keyPressEvent(self, event): """ Protected slot to handle key press events. - + @param event reference to the key press event (QKeyEvent) """ if event.key() == Qt.Key.Key_Escape: @@ -1221,64 +1264,68 @@ class SearchReplaceSlidingWidget(QWidget): """ Class implementing the search and replace widget with sliding behavior. - + @signal searchListChanged() emitted to indicate a change of the search list """ + searchListChanged = pyqtSignal() - + def __init__(self, replace, vm, parent=None): """ Constructor - + @param replace flag indicating a replace widget is called @param vm reference to the viewmanager object @param parent parent widget of this widget (QWidget) """ super().__init__(parent) - - self.__searchReplaceWidget = SearchReplaceWidget( - replace, vm, self, True) - + + self.__searchReplaceWidget = SearchReplaceWidget(replace, vm, self, True) + self.__layout = QHBoxLayout(self) self.setLayout(self.__layout) self.__layout.setContentsMargins(0, 0, 0, 0) self.__layout.setAlignment(Qt.AlignmentFlag.AlignTop) - + self.__leftButton = QToolButton(self) self.__leftButton.setArrowType(Qt.ArrowType.LeftArrow) self.__leftButton.setSizePolicy( - QSizePolicy.Policy.Minimum, QSizePolicy.Policy.MinimumExpanding) + QSizePolicy.Policy.Minimum, QSizePolicy.Policy.MinimumExpanding + ) self.__leftButton.setAutoRepeat(True) - + self.__scroller = QScrollArea(self) self.__scroller.setWidget(self.__searchReplaceWidget) self.__scroller.setSizePolicy( - QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum + ) self.__scroller.setFrameShape(QFrame.Shape.NoFrame) self.__scroller.setVerticalScrollBarPolicy( - Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + Qt.ScrollBarPolicy.ScrollBarAlwaysOff + ) self.__scroller.setHorizontalScrollBarPolicy( - Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + Qt.ScrollBarPolicy.ScrollBarAlwaysOff + ) self.__scroller.setWidgetResizable(False) - + self.__rightButton = QToolButton(self) self.__rightButton.setArrowType(Qt.ArrowType.RightArrow) self.__rightButton.setSizePolicy( - QSizePolicy.Policy.Minimum, QSizePolicy.Policy.MinimumExpanding) + QSizePolicy.Policy.Minimum, QSizePolicy.Policy.MinimumExpanding + ) self.__rightButton.setAutoRepeat(True) - + self.__layout.addWidget(self.__leftButton) self.__layout.addWidget(self.__scroller) self.__layout.addWidget(self.__rightButton) - + self.setMaximumHeight(self.__searchReplaceWidget.sizeHint().height()) self.adjustSize() - - self.__searchReplaceWidget.searchListChanged.connect( - self.searchListChanged) + + self.__searchReplaceWidget.searchListChanged.connect(self.searchListChanged) self.__leftButton.clicked.connect(self.__slideLeft) self.__rightButton.clicked.connect(self.__slideRight) - + def changeEvent(self, evt): """ Protected method handling state changes. @@ -1286,86 +1333,85 @@ @param evt event containing the state change (QEvent) """ if evt.type() == QEvent.Type.FontChange: - self.setMaximumHeight( - self.__searchReplaceWidget.sizeHint().height()) + self.setMaximumHeight(self.__searchReplaceWidget.sizeHint().height()) self.adjustSize() - + def findNext(self): """ Public slot to find the next occurrence of text. """ self.__searchReplaceWidget.findNext() - + def findPrev(self): """ Public slot to find the next previous of text. """ self.__searchReplaceWidget.findPrev() - + def replace(self): """ Public method to replace the current selection. """ self.__searchReplaceWidget.replace() - + def replaceSearch(self): """ Public method to replace the current selection and search again. """ self.__searchReplaceWidget.replaceSearch() - + def replaceAll(self): """ Public method to replace all occurrences. """ self.__searchReplaceWidget.replaceAll() - + def selectionChanged(self, editor): """ Public slot tracking changes of selected text. - + @param editor reference to the editor @type Editor """ self.__searchReplaceWidget.updateSelectionCheckBox(editor) - + @pyqtSlot(Editor) def updateSelectionCheckBox(self, editor): """ Public slot to update the selection check box. - + @param editor reference to the editor (Editor) """ self.__searchReplaceWidget.updateSelectionCheckBox(editor) - def show(self, text=''): + def show(self, text=""): """ Public slot to show the widget. - + @param text text to be shown in the findtext edit (string) """ self.__searchReplaceWidget.show(text) super().show() self.__enableScrollerButtons() - + def __slideLeft(self): """ Private slot to move the widget to the left, i.e. show contents to the right. """ self.__slide(True) - + def __slideRight(self): """ Private slot to move the widget to the right, i.e. show contents to the left. """ self.__slide(False) - + def __slide(self, toLeft): """ Private method to move the sliding widget. - + @param toLeft flag indicating to move to the left (boolean) """ scrollBar = self.__scroller.horizontalScrollBar() @@ -1379,7 +1425,7 @@ newValue = scrollBar.maximum() scrollBar.setValue(newValue) self.__enableScrollerButtons() - + def __enableScrollerButtons(self): """ Private method to set the enabled state of the scroll buttons. @@ -1387,13 +1433,13 @@ scrollBar = self.__scroller.horizontalScrollBar() self.__leftButton.setEnabled(scrollBar.value() > 0) self.__rightButton.setEnabled(scrollBar.value() < scrollBar.maximum()) - + def resizeEvent(self, evt): """ Protected method to handle resize events. - + @param evt reference to the resize event (QResizeEvent) """ self.__enableScrollerButtons() - + super().resizeEvent(evt)