Exemplo n.º 1
0
class FindReplace(QWidget):
    """
    Find replace widget bar
    """
    NbReplaced = pyqtSignal(int)

    def __init__(self, parent=None):
        """
        This class provides an graphical interface to find and replace text

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.editor = None
        self.styleEdit = {
            False: "background-color:rgb(255, 175, 90);",
            True: ""
        }

        self.createButton()
        self.createWidgets()
        self.createConnections()

    def showEnhanced(self, textSelected=''):
        """
        Show enhanced (focus and text selected)
        """
        self.show()
        if len(textSelected): self.edit.setEditText(textSelected)
        self.edit.setFocus()
        self.edit.lineEdit().selectAll()

    def createButton(self):
        """
        create qt buttons
        Buttons defined:
         * Previous
         * Next
         * Replace
        """
        self.previousButton = QtHelper.createButton(
            self,
            text=self.tr("Find Previous"),
            triggered=self.findPrevious,
            icon=QIcon(":/find_previous.png"))
        self.nextButton = QtHelper.createButton(self,
                                                text=self.tr("Find Next"),
                                                triggered=self.findNext,
                                                icon=QIcon(":/find_next.png"))
        self.replaceButton = QtHelper.createButton(self,
                                                   text=self.tr("Replace..."),
                                                   triggered=self.replaceFind,
                                                   icon=QIcon(":/replace.png"))

    def createWidgets(self):
        """
        QtWidgets creation

        QHBoxLayout
         -------------------------------------------.....
        | QLabel: QLineEdit QButton QButton QCheckBox |
         -------------------------------------------.....

        ....--------------------------------------
             QLabel: QLineEdit QButton QCheckBox |
        ....--------------------------------------
        """
        glayout = QGridLayout()

        self.edit = QLineEditMore(parent=self)
        self.edit.setEditable(1)
        self.edit.setMaxCount(10)
        self.edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.edit.lineEdit().setPlaceholderText("Search text in your test?")
        self.edit.setMinimumWidth(200)

        self.replaceEdit = QComboBox(self)
        self.replaceEdit.setEditable(1)
        self.replaceEdit.setMaxCount(10)
        self.replaceEdit.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.replaceEdit.lineEdit().setPlaceholderText(
            "Replace the text with?")
        self.replaceEdit.setMinimumWidth(200)

        self.caseCheck = QCheckBox(self.tr("Case Sensitive"))
        self.caseCheck.setChecked(
            QtHelper.str2bool(Settings.instance().readValue(
                key='Editor/find-case-sensitive')))
        self.caseWordCheck = QCheckBox(self.tr("Whole word only"))
        self.caseWordCheck.setChecked(
            QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/find-whole-word')))
        self.allCheck = QCheckBox(self.tr("All occurences"))
        self.allCheck.setChecked(
            QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/replace-all')))
        self.caseRegexpCheck = QCheckBox(self.tr("Regular expression"))
        self.caseRegexpCheck.setChecked(
            QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/find-regexp')))
        self.caseWrapCheck = QCheckBox(self.tr("Wrap at the end"))
        self.caseWrapCheck.setChecked(
            QtHelper.str2bool(
                Settings.instance().readValue(key='Editor/find-wrap')))

        glayout.addWidget(self.edit, 0, 1)
        glayout.addWidget(self.nextButton, 0, 3)
        glayout.addWidget(self.previousButton, 0, 2)
        glayout.addWidget(self.caseCheck, 2, 2)
        glayout.addWidget(self.caseWrapCheck, 2, 3)
        glayout.addWidget(self.caseWordCheck, 3, 2)
        glayout.addWidget(self.caseRegexpCheck, 3, 3)

        glayout.addWidget(self.replaceEdit, 1, 1)
        glayout.addWidget(self.replaceButton, 1, 2)
        glayout.addWidget(self.allCheck, 1, 3)

        self.previousButton.setDisabled(True)
        self.nextButton.setDisabled(True)

        self.setLayout(glayout)

        flags = Qt.WindowFlags()
        flags |= Qt.Window
        flags |= Qt.WindowTitleHint
        flags |= Qt.WindowCloseButtonHint
        flags |= Qt.MSWindowsFixedSizeDialogHint
        self.setWindowFlags(flags)

        self.setWindowIcon(QIcon(":/main.png"))
        self.setWindowTitle("Find And Replace")

    def createConnections(self):
        """
        create qt connection
        """
        self.edit.editTextChanged.connect(self.textHasChanged)
        self.edit.EnterPressed.connect(self.returnPressed)
        self.caseCheck.stateChanged.connect(self.find)

    def returnPressed(self):
        """
        Return key pressed
        Find next in this case
        """
        self.findNext()

    def setEditor(self, editor):
        """
        Set the target to find the text

        @param editor: 
        @type editor:   
        """
        self.editor = editor

    def textHasChanged(self, txt):
        """
        Find text has changed
        """
        text = self.edit.currentText()
        if len(text) > 0:
            self.previousButton.setEnabled(True)
            self.nextButton.setEnabled(True)
            self.find(changed=True, forward=True)
        else:
            self.previousButton.setDisabled(True)
            self.nextButton.setDisabled(True)

    def updateComboBox(self):
        """
        Update combobox
        """
        comboUpdated = False
        for i in range(self.edit.count()):
            if self.edit.itemText(i) == self.edit.currentText():
                comboUpdated = True
        if not comboUpdated:
            self.edit.addItem(self.edit.currentText())

        comboUpdated = False
        for i in range(self.replaceEdit.count()):
            if self.replaceEdit.itemText(i) == self.replaceEdit.currentText():
                comboUpdated = True
        if not comboUpdated:
            self.replaceEdit.addItem(self.replaceEdit.currentText())

    def clearText(self):
        """
        Clear all QlineEdit
        """
        self.edit.setStyleSheet("")

        self.edit.clearEditText()

        self.replaceEdit.clearEditText()

    def findPrevious(self):
        """
        Find previous occurence
        """
        # update combobox
        self.updateComboBox()

        # find previous
        self.find(changed=False, forward=False)

    def findNext(self, line=-1, index=-1):
        """
        Find next occurence
        """
        # update combobox
        self.updateComboBox()

        return self.find(changed=False, forward=True, line=line, index=index)

    def find(self, changed=True, forward=True, line=-1, index=-1):
        """
        Call the find function

        @param changed: 
        @type changed: boolean  

        @param forward: 
        @type forward: boolean      
        """
        text = self.edit.currentText()
        if len(text) == 0:
            self.edit.setStyleSheet("")
            return None
        else:
            found = self.editor.findText(
                text,
                changed,
                forward,
                case=self.caseCheck.isChecked(),
                words=self.caseWordCheck.isChecked(),
                regexp=self.caseRegexpCheck.isChecked(),
                wraps=self.caseWrapCheck.isChecked(),
                line=line,
                index=index)
            self.edit.setStyleSheet(self.styleEdit[found])
            return found

    def replaceFind(self):
        """
        Replace and find
        """
        if (self.editor is None): return

        replaceText = self.replaceEdit.currentText()
        searchText = self.edit.currentText()
        if not self.caseCheck.isChecked(): searchText = searchText.lower()
        current = -1
        nbReplaced = 0

        # find the first occurence from the beginning of the doc or not
        if not self.allCheck.isChecked():
            detected = self.findNext()
        else:
            detected = self.findNext(line=0, index=0)
        (line, _) = self.editor.getCursorPosition()

        while detected:
            previous = current
            selectedText = self.editor.selectedText()

            # normalize the text in lower case if the case sensitive is not activated
            if not self.caseCheck.isChecked():
                selectedText = selectedText.lower()

            # replace the selection
            if self.editor.hasSelectedText() and selectedText == searchText:
                self.editor.replace(replaceText)
                nbReplaced += 1

            # find the next occurence of the word
            detected = self.findNext()
            (current, _) = self.editor.getCursorPosition()

            # all doc readed ? break the loop
            if previous > current: break
            if current == line and previous != -1: break

            # just execute one replace
            if not self.allCheck.isChecked(): break

        self.allCheck.setCheckState(Qt.Unchecked)
        self.NbReplaced.emit(nbReplaced)