class ReplaceWidget(FindReplaceBase): """ Find and replace in the current file widget """ def __init__(self, editorsManager, parent=None): FindReplaceBase.__init__(self, editorsManager, parent) self._skip = True prj = GlobalData().project self.findHistory = prj.findHistory self.replaceHistory = prj.replaceHistory # Additional UI elements self.replaceLabel = QLabel(self) self.replaceLabel.setText("Replace:") self.replaceCombo = ComboBoxNoUndo(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.replaceCombo.sizePolicy().hasHeightForWidth()) self.replaceCombo.setSizePolicy(sizePolicy) self.replaceCombo.setEditable(True) self.replaceCombo.setInsertPolicy(QComboBox.InsertAtTop) self.replaceCombo.setAutoCompletion(False) self.replaceCombo.setDuplicatesEnabled(False) self.replaceCombo.setEnabled(False) self.replaceButton = QToolButton(self) self.replaceButton.setToolTip("Replace current occurrence") self.replaceButton.setIcon(PixmapCache().getIcon("replace.png")) self.replaceButton.setEnabled(False) self.replaceButton.clicked.connect(self.__onReplace) self.replaceButton.setIconSize(QSize(24, 16)) self.replaceAllButton = QToolButton(self) self.replaceAllButton.setToolTip("Replace all occurrences") self.replaceAllButton.setIcon(PixmapCache().getIcon("replace-all.png")) self.replaceAllButton.setIconSize(QSize(24, 16)) self.replaceAllButton.setEnabled(False) self.replaceAllButton.clicked.connect(self.__onReplaceAll) self.replaceAndMoveButton = QToolButton(self) self.replaceAndMoveButton.setToolTip( "Replace current occurrence and move to the next match") self.replaceAndMoveButton.setIcon( PixmapCache().getIcon("replace-move.png")) self.replaceAndMoveButton.setIconSize(QSize(24, 16)) self.replaceAndMoveButton.setEnabled(False) self.replaceAndMoveButton.clicked.connect(self.__onReplaceAndMove) self.gridLayout = QGridLayout(self) self.gridLayout.setMargin(0) self.gridLayout.addWidget(self.closeButton, 0, 0, 1, 1) self.gridLayout.addWidget(self.findLabel, 0, 1, 1, 1) self.gridLayout.addWidget(self.findtextCombo, 0, 2, 1, 1) self.gridLayout.addWidget(self.findPrevButton, 0, 3, 1, 1) self.gridLayout.addWidget(self.findNextButton, 0, 4, 1, 1) self.gridLayout.addWidget(self.caseCheckBox, 0, 5, 1, 1) self.gridLayout.addWidget(self.wordCheckBox, 0, 6, 1, 1) self.gridLayout.addWidget(self.regexpCheckBox, 0, 7, 1, 1) self.gridLayout.addWidget(self.replaceLabel, 1, 1, 1, 1) self.gridLayout.addWidget(self.replaceCombo, 1, 2, 1, 1) self.gridLayout.addWidget(self.replaceButton, 1, 3, 1, 1) self.gridLayout.addWidget(self.replaceAndMoveButton, 1, 4, 1, 1) self.gridLayout.addWidget(self.replaceAllButton, 1, 5, 1, 1) self.setTabOrder(self.findtextCombo, self.replaceCombo) self.setTabOrder(self.replaceCombo, self.caseCheckBox) self.setTabOrder(self.caseCheckBox, self.wordCheckBox) self.setTabOrder(self.wordCheckBox, self.regexpCheckBox) self.setTabOrder(self.regexpCheckBox, self.findNextButton) self.setTabOrder(self.findNextButton, self.findPrevButton) self.setTabOrder(self.findPrevButton, self.replaceAndMoveButton) self.setTabOrder(self.replaceButton, self.replaceAllButton) self.setTabOrder(self.replaceAndMoveButton, self.replaceAllButton) self.setTabOrder(self.replaceAllButton, self.closeButton) GlobalData().project.projectChanged.connect(self.__onProjectChanged) self.findNextButton.clicked.connect(self.onNext) self.findPrevButton.clicked.connect(self.onPrev) self.incSearchDone.connect(self.__onSearchDone) self.replaceCombo.editTextChanged.connect(self.__onReplaceTextChanged) self.replaceCombo.lineEdit().returnPressed.connect( self.__onReplaceAndMove) self.__connected = False self.__replaceCouldBeEnabled = False self._skip = False return def updateStatus(self): " Triggered when the current tab is changed " FindReplaceBase.updateStatus(self) if self._currentWidget.getType( ) == MainWindowTabWidgetBase.VCSAnnotateViewer: self.findtextCombo.setEnabled(False) self.findPrevButton.setEnabled(False) self.findNextButton.setEnabled(False) self.caseCheckBox.setEnabled(False) self.wordCheckBox.setEnabled(False) self.regexpCheckBox.setEnabled(False) self.replaceCombo.setEnabled(False) self.replaceAllButton.setEnabled(False) self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) return self.__updateReplaceAllButtonStatus() if self._isTextEditor: self.__cursorPositionChanged(self._currentWidget.getLine(), self._currentWidget.getPos()) else: self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) self.__replaceCouldBeEnabled = False if self.__connected: self.__unsubscribeFromCursorChange() self.__subscribeToCursorChangePos() return def __updateReplaceAllButtonStatus(self): " Updates the replace all button status " self.replaceCombo.setEnabled(self._isTextEditor) textAvailable = self.findtextCombo.currentText() != "" self.replaceAllButton.setEnabled(self._isTextEditor and textAvailable) return def show(self, text=''): " Overriden show method " self._skip = True self.replaceCombo.clear() self.replaceCombo.addItems(self.replaceHistory) self.replaceCombo.setEditText('') self._skip = False FindReplaceBase.show(self, text) self.__subscribeToCursorChangePos() return def hide(self): " Overriden hide method " if self.__connected: self.__unsubscribeFromCursorChange() FindReplaceBase.hide(self) return def __onProjectChanged(self, what): " Triggered when a project is changed " if what == CodimensionProject.CompleteProject: prj = GlobalData().project self._skip = True self.findHistory = prj.findHistory self.findtextCombo.clear() self.findtextCombo.setEditText('') self.findtextCombo.addItems(self.findHistory) self.replaceHistory = prj.replaceHistory self.replaceCombo.clear() self.replaceCombo.setEditText('') self.replaceCombo.addItems(self.replaceHistory) self._skip = False return def __onSearchDone(self, found): " Triggered when incremental search is done " self.replaceButton.setEnabled(found) self.replaceAndMoveButton.setEnabled(found) self.replaceAllButton.setEnabled(found) self.__replaceCouldBeEnabled = True return def __onReplaceTextChanged(self, text): " Triggered when replace with text is changed " self.__updateReplaceAllButtonStatus() self.replaceButton.setEnabled(self.__replaceCouldBeEnabled) self.replaceAndMoveButton.setEnabled(self.__replaceCouldBeEnabled) return def __subscribeToCursorChangePos(self): " Subscribes for the cursor position notification " if self._editor is not None: self._editor.cursorPositionChanged.connect( self.__cursorPositionChanged) self.__connected = True return def __unsubscribeFromCursorChange(self): " Unsubscribes from the cursor position notification " if self._editor is not None: try: self._editor.cursorPositionChanged.disconnect( self.__cursorPositionChanged) except: pass self.__connected = False return def __cursorPositionChanged(self, line, pos): " Triggered when the cursor position is changed " if self._searchSupport.hasEditor(self._editorUUID): searchAttributes = self._searchSupport.get(self._editorUUID) enable = line == searchAttributes.match[ 0 ] and \ pos == searchAttributes.match[ 1 ] else: enable = False self.replaceButton.setEnabled(enable) self.replaceAndMoveButton.setEnabled(enable) self.__replaceCouldBeEnabled = enable return def __onReplaceAll(self): " Triggered when replace all button is clicked " text = self.findtextCombo.currentText() isRegexp = self.regexpCheckBox.isChecked() isCase = self.caseCheckBox.isChecked() isWord = self.wordCheckBox.isChecked() replaceText = self.replaceCombo.currentText() self.__updateReplaceHistory(text, replaceText) # Check that there is at least one target to replace found = self._editor.findFirstTarget(text, isRegexp, isCase, isWord, 0, 0) if not found: GlobalData().mainWindow.showStatusBarMessage( "No occurrences of '" + text + "' found. Nothing is replaced.", 0) return # There is something matching count = 0 self._editor.beginUndoAction() while found: self._editor.replaceTarget(str(replaceText)) count += 1 found = self._editor.findNextTarget() self._editor.endUndoAction() self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) self.__replaceCouldBeEnabled = False suffix = "" if count > 1: suffix = "s" GlobalData().mainWindow.showStatusBarMessage( str(count) + " occurrence" + suffix + " replaced.", 0) GlobalData().mainWindow.clearStatusBarMessage(1) return def __onReplace(self): " Triggered when replace current occurrence button is clicked " replaceText = self.replaceCombo.currentText() text = self.findtextCombo.currentText() isRegexp = self.regexpCheckBox.isChecked() isCase = self.caseCheckBox.isChecked() isWord = self.wordCheckBox.isChecked() searchAttributes = self._searchSupport.get(self._editorUUID) self.__updateReplaceHistory(text, replaceText) found = self._editor.findFirstTarget(text, isRegexp, isCase, isWord, searchAttributes.match[0], searchAttributes.match[1]) if found: if self._editor.replaceTarget(str(replaceText)): GlobalData().mainWindow.showStatusBarMessage( "1 occurrence " "replaced.", 0) GlobalData().mainWindow.clearStatusBarMessage(1) # Positioning cursor to the end of the replaced text helps # to avoid problems of replacing 'text' with 'prefix_text' searchAttributes.match[1] += len(replaceText) self._editor.setCursorPosition(searchAttributes.match[0], searchAttributes.match[1]) self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) else: GlobalData().mainWindow.showStatusBarMessage( "No occurrences " "replaced.", 0) # This will prevent highlighting the improper editor positions searchAttributes.match = [-1, -1, -1] return def __onReplaceAndMove(self): " Triggered when replace-and-move button is clicked " buttonFocused = self.replaceAndMoveButton.hasFocus() self.__onReplace() self.onNext(False) if buttonFocused: self.replaceAndMoveButton.setFocus() return def __updateReplaceHistory(self, text, replaceText): " Updates the history in the project and in the combo boxes " changedWhat = self._addToHistory(self.findtextCombo, self.findHistory, text) changedReplace = self._addToHistory(self.replaceCombo, self.replaceHistory, replaceText) if changedWhat or changedReplace: prj = GlobalData().project prj.setReplaceHistory(self.findHistory, self.replaceHistory) return def onNext(self, clearSBMessage=True): " Triggered when the find next button is clicked " oldLine = self._currentWidget.getLine() oldPos = self._currentWidget.getPos() FindReplaceBase.onNext(self, clearSBMessage) if oldLine == self._currentWidget.getLine() and \ oldPos == self._currentWidget.getPos(): FindReplaceBase.onNext(self, clearSBMessage) self.__updateReplaceHistory(self.findtextCombo.currentText(), self.replaceCombo.currentText()) return def onPrev(self): " Triggered when the find previous button is clicked " FindReplaceBase.onPrev(self) self.__updateReplaceHistory(self.findtextCombo.currentText(), self.replaceCombo.currentText()) return
class ReplaceWidget(FindReplaceBase): """ Find and replace in the current file widget """ def __init__(self, editorsManager, parent=None): FindReplaceBase.__init__(self, editorsManager, parent) self._skip = True prj = GlobalData().project self.findHistory = prj.findHistory self.replaceHistory = prj.replaceHistory # Additional UI elements self.replaceLabel = QLabel(self) self.replaceLabel.setText("Replace:") self.replaceCombo = ComboBoxNoUndo(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.replaceCombo.sizePolicy().hasHeightForWidth()) self.replaceCombo.setSizePolicy(sizePolicy) self.replaceCombo.setEditable(True) self.replaceCombo.setInsertPolicy(QComboBox.InsertAtTop) self.replaceCombo.setAutoCompletion(False) self.replaceCombo.setDuplicatesEnabled(False) self.replaceCombo.setEnabled(False) self.replaceButton = QToolButton(self) self.replaceButton.setToolTip("Replace current occurrence") self.replaceButton.setIcon(PixmapCache().getIcon("replace.png")) self.replaceButton.setEnabled(False) self.replaceButton.clicked.connect(self.__onReplace) self.replaceButton.setIconSize(QSize(24, 16)) self.replaceAllButton = QToolButton(self) self.replaceAllButton.setToolTip("Replace all occurrences") self.replaceAllButton.setIcon(PixmapCache().getIcon("replace-all.png")) self.replaceAllButton.setIconSize(QSize(24, 16)) self.replaceAllButton.setEnabled(False) self.replaceAllButton.clicked.connect(self.__onReplaceAll) self.replaceAndMoveButton = QToolButton(self) self.replaceAndMoveButton.setToolTip("Replace current occurrence and move to the next match") self.replaceAndMoveButton.setIcon(PixmapCache().getIcon("replace-move.png")) self.replaceAndMoveButton.setIconSize(QSize(24, 16)) self.replaceAndMoveButton.setEnabled(False) self.replaceAndMoveButton.clicked.connect(self.__onReplaceAndMove) self.gridLayout = QGridLayout(self) self.gridLayout.setMargin(0) self.gridLayout.addWidget(self.closeButton, 0, 0, 1, 1) self.gridLayout.addWidget(self.findLabel, 0, 1, 1, 1) self.gridLayout.addWidget(self.findtextCombo, 0, 2, 1, 1) self.gridLayout.addWidget(self.findPrevButton, 0, 3, 1, 1) self.gridLayout.addWidget(self.findNextButton, 0, 4, 1, 1) self.gridLayout.addWidget(self.caseCheckBox, 0, 5, 1, 1) self.gridLayout.addWidget(self.wordCheckBox, 0, 6, 1, 1) self.gridLayout.addWidget(self.regexpCheckBox, 0, 7, 1, 1) self.gridLayout.addWidget(self.replaceLabel, 1, 1, 1, 1) self.gridLayout.addWidget(self.replaceCombo, 1, 2, 1, 1) self.gridLayout.addWidget(self.replaceButton, 1, 3, 1, 1) self.gridLayout.addWidget(self.replaceAndMoveButton, 1, 4, 1, 1) self.gridLayout.addWidget(self.replaceAllButton, 1, 5, 1, 1) self.setTabOrder(self.findtextCombo, self.replaceCombo) self.setTabOrder(self.replaceCombo, self.caseCheckBox) self.setTabOrder(self.caseCheckBox, self.wordCheckBox) self.setTabOrder(self.wordCheckBox, self.regexpCheckBox) self.setTabOrder(self.regexpCheckBox, self.findNextButton) self.setTabOrder(self.findNextButton, self.findPrevButton) self.setTabOrder(self.findPrevButton, self.replaceAndMoveButton) self.setTabOrder(self.replaceButton, self.replaceAllButton) self.setTabOrder(self.replaceAndMoveButton, self.replaceAllButton) self.setTabOrder(self.replaceAllButton, self.closeButton) GlobalData().project.projectChanged.connect(self.__onProjectChanged) self.findNextButton.clicked.connect(self.onNext) self.findPrevButton.clicked.connect(self.onPrev) self.incSearchDone.connect(self.__onSearchDone) self.replaceCombo.editTextChanged.connect(self.__onReplaceTextChanged) self.replaceCombo.lineEdit().returnPressed.connect(self.__onReplaceAndMove) self.__connected = False self.__replaceCouldBeEnabled = False self._skip = False return def updateStatus(self): " Triggered when the current tab is changed " FindReplaceBase.updateStatus(self) if self._currentWidget.getType() == MainWindowTabWidgetBase.VCSAnnotateViewer: self.findtextCombo.setEnabled(False) self.findPrevButton.setEnabled(False) self.findNextButton.setEnabled(False) self.caseCheckBox.setEnabled(False) self.wordCheckBox.setEnabled(False) self.regexpCheckBox.setEnabled(False) self.replaceCombo.setEnabled(False) self.replaceAllButton.setEnabled(False) self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) return self.__updateReplaceAllButtonStatus() if self._isTextEditor: self.__cursorPositionChanged(self._currentWidget.getLine(), self._currentWidget.getPos()) else: self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) self.__replaceCouldBeEnabled = False if self.__connected: self.__unsubscribeFromCursorChange() self.__subscribeToCursorChangePos() return def __updateReplaceAllButtonStatus(self): " Updates the replace all button status " self.replaceCombo.setEnabled(self._isTextEditor) textAvailable = self.findtextCombo.currentText() != "" self.replaceAllButton.setEnabled(self._isTextEditor and textAvailable) return def show(self, text=""): " Overriden show method " self._skip = True self.replaceCombo.clear() self.replaceCombo.addItems(self.replaceHistory) self.replaceCombo.setEditText("") self._skip = False FindReplaceBase.show(self, text) self.__subscribeToCursorChangePos() return def hide(self): " Overriden hide method " if self.__connected: self.__unsubscribeFromCursorChange() FindReplaceBase.hide(self) return def __onProjectChanged(self, what): " Triggered when a project is changed " if what == CodimensionProject.CompleteProject: prj = GlobalData().project self._skip = True self.findHistory = prj.findHistory self.findtextCombo.clear() self.findtextCombo.setEditText("") self.findtextCombo.addItems(self.findHistory) self.replaceHistory = prj.replaceHistory self.replaceCombo.clear() self.replaceCombo.setEditText("") self.replaceCombo.addItems(self.replaceHistory) self._skip = False return def __onSearchDone(self, found): " Triggered when incremental search is done " self.replaceButton.setEnabled(found) self.replaceAndMoveButton.setEnabled(found) self.replaceAllButton.setEnabled(found) self.__replaceCouldBeEnabled = True return def __onReplaceTextChanged(self, text): " Triggered when replace with text is changed " self.__updateReplaceAllButtonStatus() self.replaceButton.setEnabled(self.__replaceCouldBeEnabled) self.replaceAndMoveButton.setEnabled(self.__replaceCouldBeEnabled) return def __subscribeToCursorChangePos(self): " Subscribes for the cursor position notification " if self._editor is not None: self._editor.cursorPositionChanged.connect(self.__cursorPositionChanged) self.__connected = True return def __unsubscribeFromCursorChange(self): " Unsubscribes from the cursor position notification " if self._editor is not None: try: self._editor.cursorPositionChanged.disconnect(self.__cursorPositionChanged) except: pass self.__connected = False return def __cursorPositionChanged(self, line, pos): " Triggered when the cursor position is changed " if self._searchSupport.hasEditor(self._editorUUID): searchAttributes = self._searchSupport.get(self._editorUUID) enable = line == searchAttributes.match[0] and pos == searchAttributes.match[1] else: enable = False self.replaceButton.setEnabled(enable) self.replaceAndMoveButton.setEnabled(enable) self.__replaceCouldBeEnabled = enable return def __onReplaceAll(self): " Triggered when replace all button is clicked " text = self.findtextCombo.currentText() isRegexp = self.regexpCheckBox.isChecked() isCase = self.caseCheckBox.isChecked() isWord = self.wordCheckBox.isChecked() replaceText = self.replaceCombo.currentText() self.__updateReplaceHistory(text, replaceText) # Check that there is at least one target to replace found = self._editor.findFirstTarget(text, isRegexp, isCase, isWord, 0, 0) if not found: GlobalData().mainWindow.showStatusBarMessage( "No occurrences of '" + text + "' found. Nothing is replaced.", 0 ) return # There is something matching count = 0 self._editor.beginUndoAction() while found: self._editor.replaceTarget(str(replaceText)) count += 1 found = self._editor.findNextTarget() self._editor.endUndoAction() self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) self.__replaceCouldBeEnabled = False suffix = "" if count > 1: suffix = "s" GlobalData().mainWindow.showStatusBarMessage(str(count) + " occurrence" + suffix + " replaced.", 0) GlobalData().mainWindow.clearStatusBarMessage(1) return def __onReplace(self): " Triggered when replace current occurrence button is clicked " replaceText = self.replaceCombo.currentText() text = self.findtextCombo.currentText() isRegexp = self.regexpCheckBox.isChecked() isCase = self.caseCheckBox.isChecked() isWord = self.wordCheckBox.isChecked() searchAttributes = self._searchSupport.get(self._editorUUID) self.__updateReplaceHistory(text, replaceText) found = self._editor.findFirstTarget( text, isRegexp, isCase, isWord, searchAttributes.match[0], searchAttributes.match[1] ) if found: if self._editor.replaceTarget(str(replaceText)): GlobalData().mainWindow.showStatusBarMessage("1 occurrence " "replaced.", 0) GlobalData().mainWindow.clearStatusBarMessage(1) # Positioning cursor to the end of the replaced text helps # to avoid problems of replacing 'text' with 'prefix_text' searchAttributes.match[1] += len(replaceText) self._editor.setCursorPosition(searchAttributes.match[0], searchAttributes.match[1]) self.replaceButton.setEnabled(False) self.replaceAndMoveButton.setEnabled(False) else: GlobalData().mainWindow.showStatusBarMessage("No occurrences " "replaced.", 0) # This will prevent highlighting the improper editor positions searchAttributes.match = [-1, -1, -1] return def __onReplaceAndMove(self): " Triggered when replace-and-move button is clicked " buttonFocused = self.replaceAndMoveButton.hasFocus() self.__onReplace() self.onNext(False) if buttonFocused: self.replaceAndMoveButton.setFocus() return def __updateReplaceHistory(self, text, replaceText): " Updates the history in the project and in the combo boxes " changedWhat = self._addToHistory(self.findtextCombo, self.findHistory, text) changedReplace = self._addToHistory(self.replaceCombo, self.replaceHistory, replaceText) if changedWhat or changedReplace: prj = GlobalData().project prj.setReplaceHistory(self.findHistory, self.replaceHistory) return def onNext(self, clearSBMessage=True): " Triggered when the find next button is clicked " oldLine = self._currentWidget.getLine() oldPos = self._currentWidget.getPos() FindReplaceBase.onNext(self, clearSBMessage) if oldLine == self._currentWidget.getLine() and oldPos == self._currentWidget.getPos(): FindReplaceBase.onNext(self, clearSBMessage) self.__updateReplaceHistory(self.findtextCombo.currentText(), self.replaceCombo.currentText()) return def onPrev(self): " Triggered when the find previous button is clicked " FindReplaceBase.onPrev(self) self.__updateReplaceHistory(self.findtextCombo.currentText(), self.replaceCombo.currentText()) return