Search code examples
pythonpyqtpyqt4qlineeditqvalidator

Passing line-edits to a contextmanager to set validators


I am trying to pass a list of widgets into ca ontextmanager in which I am trying to set them with QDoubleValidators.

My initial code is something as follows:

validator = QtGui.QDoubleValidator()
validator.setDecimals(2)
self.ui.retailPriceLineEdit.setValidator(validator)
self.ui.discountPriceLineEdit.setValidator(validator)
self.ui.onlinePriceLineEdit.setValidator(validator)
...

Basically I have a tons of QLineEdits in which I am setting with a 2 decimal places input limit.

I am not so sure if contextmanager may helps in this case, but I am trying out something as follows:

class TestValidator:
    def __init__(self, widgets_list=None):
        self.validator = QtGui.QDoubleValidator()
        self.validator.setDecimals(2)
        self.widgets_list = widgets_list

        print widgets_list

    def __enter__(self):
        for w in self.widgets_list:
            w.setValidator(self.validator)

    def __exit__(self):
        pass

And when I tried running it as:

self.test_validator = utils.TestValidator()
my_widgets = [self.ui.retailPriceLineEdit, self.ui.discountPriceLineEdit, self.ui.onlinePriceLineEdit]

with self.test_validator(my_widgets):
    pass

I got a couple of errors such as: AttributeError: TestValidator instance has no __call__ method #

Even so, is it even a wise idea to pass widgets into a contextmanager?

(FYI, my widgets/ ui are created from qt designer)


Solution

  • A context-manager isn't the right tool for this job. Once you have the list of line-edits, all you need to do is iterate over them using a for-loop. An efficient way to generate the list is to use findChildren with a regexp. This can then be wrapped up in a local function like this:

    def __init__(self, ...):
        ...
        def set_validators(pattern):
            widgets = self.findChidren(QtGui.QLineEdit, QtCore.QRegExp(pattern))    
            for widget in widgets:
                validator = QtGui.QDoubleValidator()
                validator.setDecimals(2)
                widget.setValidator(validator)
    
        set_validators('.*PriceLineEdit$')
        set_validators('.*OtherLineEdit$')
        ...
    

    Or if you can't use a pattern, you can just pass in a list of widgets instead:

        def set_validators(widgets):
            for widget in widgets:
                validator = QtGui.QDoubleValidator()
                validator.setDecimals(2)
                widget.setValidator(validator)
    
        my_widgets = [self.ui.retailPriceLineEdit, self.ui.discountPriceLineEdit sellf.ui.onlinePriceLineEdit]
    
        set_validators(my_widgets)
        set_validators(other_widgets)
        ...