Search code examples
pythoncssstylingpyforms

pyforms - dynamic styling based on variable value


I am devloping a pyform control which only accept urls as input.

To achieve this I derivated my class from ControlText and added an keypress event handler which tests the current value against a regular expression.

Now i want to somehow change the controls appearance based on a variable like shown in style.css.


Controls.py

import pyforms
from   pyforms.Controls import ControlText
import re

class ControlUrl(ControlText):

    def __init__(self, label="", default=None, helptext=None, regex="^((https?:)?\/\/)?(\w+(:\w+)?@)?(((([a-zA-Z\d]{1,2}|[a-zA-Z\d][\w\-]{0,62}[a-zA-Z\d])\.){1,}[\w\-]{2,6})|(\d{1,3}(\.\d{1,3}){3})|([\d:]{2,39}))(:\d{2,6})?(\/[\w.~!+,*:@%-]+)*\/?(\?([\w.~!+%,*:@-]+(=[\w.~!+%,*:@-]+)?)(&[\w.~!+%,*:@-]+(=[\w.~!+%,*:@-]+)?)*)?(#[\w.~!+%,*:@-])?$"):
        self._regex = regex
        super(ControlUrl, self).__init__(label, default, helptext)

    def init_form(self):
        self._pattern = re.compile(self._regex)
        self.key_pressed_event = self.__key_pressed
        super(ControlUrl, self).init_form()

    def __key_pressed(self, event):
        is_url = self._pattern.search(self.value) != None
        self.valid = is_url

style.css

#_urlinput[valid="true"] {
    background-color: red;
}

I would prefer solving it with css but every solution is appreciated.


Solution

  • Dynamic styling is based on QPropertys which can be set with setProperty and the css selector looks like [propertyname=propertyvalue]


    Code:

    import sys
    import pyforms
    from   pyforms.Controls import ControlText
    import re
    
    
    class ControlUrl(ControlText):
    
        def __init__(self, *args, regex="^((https?:)?\/\/)?(\w+(:\w+)?@)?(((([a-zA-Z\d]{1,2}|[a-zA-Z\d][\w\-]{0,62}[a-zA-Z\d])\.){1,}[\w\-]{2,6})|(\d{1,3}(\.\d{1,3}){3})|([\d:]{2,39}))(:\d{2,6})?(\/[\w.~!+,*:@%-]+)*\/?(\?([\w.~!+%,*:@-]+(=[\w.~!+%,*:@-]+)?)(&[\w.~!+%,*:@-]+(=[\w.~!+%,*:@-]+)?)*)?(#[\w.~!+%,*:@-])?$", **kwargs):
            self._regex = regex
            super(ControlUrl, self).__init__(*args, **kwargs)
    
        def init_form(self):
            self._pattern = re.compile(self._regex)
            self.key_pressed_event = self.__key_pressed
            super(ControlUrl, self).init_form()
    
        def __key_pressed(self, event):
            self._valid = self._pattern.search(self.value) != None
            base = self.form.lineEdit
            base.setProperty("valid", self._valid)
    
            #without these lines the style is not applied
            base.style().unpolish(base)
            base.style().polish(base)
    

    Css:

    QLineEdit[valid=false] {
        border: 1px solid #991903;
        border-radius: 4px;
    }
    QLineEdit[valid=false]:focus {
        border-color: #db391c;
    }
    

    More Information: