Customizing Regex for Validator in Python
Question: Just came across a line of code that enforces an user's text input into the
dialog's field. Regardless of the input only IP format will be allowed at the
end such as :

**123.456.789.100**

    
    
    regexIP=QtCore.QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
    

I would like to write a regex for lineedit validator that would automatically
replace all the white spaces, commas, periods, dashes, minuses, dollar signs
(everything except letters and number) with underscores. I also would like to
capitalize the first three letters and then insert an underscore right after
them regardless of what the user types.

For instance, if an user types:

    
    
    this is a beautiful day 77
    

the regex validator would automatically change it to:

    
    
    THI_Sis_a_beatiful_day_77
    

Her is how PyQt portion of the code looks like:

    
    
    my_regex = QtCore.QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
    
    my_QLineEdit = QtGui.QLineEdit()
    
    my_validator = QtGui.QRegExpValidator(my_regex, my_QLineEdit)
    
    my_QLineEdit.setValidator( my_validator )
    

Once again, the code above is just an example. What I want is to write a regex
expression to put it inside the brackets:

my_regex = QtCore.QRegExp(**my_regex_expression_goes_here**)

This my_regex expression would enforce that user never enters a white_space,
period, comma, dollar sign into the text field (lineedit). Ideally I would
like to capitalize first three letters and then put an underscore. But that is
not a big deal any longer. Let's focus on how to achieve some basic regex
expression so the user is not able to put white spaces, minus, dollar signs
and etc. Only letters and numbers are allowed....


Answer: The `QRegExpValidator` class isn't really suitable for your use-case.

Instead, you should subclass `QValidator` and re-implement its
[validate](https://qt-project.org/doc/qt-4.8/qvalidator.html#validate) method
to get the behaviour you want.

The script below provides a basic demo. It automatically uppercases the first
three letters and inserts an underscore (if necessary). Also, all non-
alphanumeric characters are automatically replaced with an underscore. If you
want runs of non-alphanumeric characters replaced with a single underscore,
add a "+" to the end of the regexp. Pasted text will also be automatically
converted.

    
    
    import sip, re
    sip.setapi('QString', 2)
    from PyQt4 import QtCore, QtGui
    
    class Validator(QtGui.QValidator):
        def __init__(self, parent=None):
            super(Validator, self).__init__(parent)
            self._replace = re.compile(r'[^A-Za-z0-9]').sub
    
        def validate(self, string, pos):
            string = self._replace('_', string)
            prefix = string[:3].upper()
            if len(string) > 3 and not string[3] == '_':
                prefix += '_'
                pos += 1
            string = prefix + string[3:]
            return QtGui.QValidator.Acceptable, string, pos
    
    class Window(QtGui.QWidget):
        def __init__(self):
            QtGui.QWidget.__init__(self)
            self.edit = QtGui.QLineEdit(self)
            self.validator = Validator(self)
            self.edit.setValidator(self.validator)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.edit)
    
    if __name__ == '__main__':
    
        import sys
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.setGeometry(500, 300, 500, 100)
        window.show()
        sys.exit(app.exec_())
    

