Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QLineEdit::setReadOnly(), no signal



  • I have been a bit disappointed to find that QLineEdit::setReadOnly() does not emit a signal.

    Why do I want one? All over existing code there are sundry creations of QLineEdits, and then they may call setReadOnly(False) and setReadOnly(True) dynamically at later times than construction all over the code. I decided to aid my poor confused users with a global-stylesheet-file rule:

    QLineEdit:read-only {
        background-color: #E5E7E9
    }
    

    But as we know, stylesheet rules are not re-evaluated after construction/first being shown till you explicitly force it to update by changing whatever stylesheet it has of its own (nothing to do with the global one), so for that I have defined a helper function:

    def widgetPropertyChanged(widget: QWidget):
        # Whenever a widget property is changed
        # (widget.setProperty() or something like QLineEdit.setReadOnly()) called to *alter* a property after initialisation)
        # we have to "alter" widget's stylesheet to cause Qt to refresh for the property change
        ss = widget.styleSheet()
        widget.setStyleSheet("/* */" + (ss if ss is not None else ""))
        widget.setStyleSheet(ss)
    

    Now, at least I could have hooked up existing QLineEdits with a "change read only" signal to call that. But with no signal, I either have to track down every occurrence of setReadOnly() and follow it with a call to that helper, or I have to subclass all my QLineEdits so that I can override setReadOnly() to do it and change all my instances to the derived class.

    Is that right? I suppose this would apply equally to any other widget-inbuilt-property which may have a function to alter it and as a result of which i might want to force stylesheet re-evaluation?



  • @SGaist
    Thank you, but sorry, let me be clear then:

    • From C++ QLineEdit::setReadOnly() is not an overridable, virtual function.
    • From PyQt, there is a "wrapper" around the whole of QLineEdit, and that has chosen to supply a function, which happens to also be named setReadOnly [but could have been called anything, e.g. pyqtSetReadOnly], which (in Python) is a virtual, overridable function.
    • PyQt's QLineEdit.setReadOnly() presumably calls the base C++ QLineEdit::setReadOnly() to effect its work.

    The big difference then is:

    • In the case of a genuine virtual Qt C++ function, which I have chosen to override in PyQt, if Qt code internally calls the virtual function from itself it will hit my Python override.
    • But in the case of this non-virtual QLineEdit::setReadOnly(), any internal Qt C++ calls to it will not be affected by the "override" I have defined from Python.

    Does the above sound right?

    EDIT I confirmed with the PyQt creator that this is indeed the way it works.



  • And while I am here, here is a second post for a couple of additional brief clarification requests. Though please answer the main question first!

    1. In my stylesheet I could have written either one of:
    QLineEdit:read-only { ... }
    

    or

    QLineEdit[readonly="true"] { ... }
    

    for my rule. It didn't seem to matter which, they both respond to the result (after update forcing!) of setReadOnly(). Are they indeed the same, or is there a subtle difference?

    1. Above I said a possible solution would be

    subclass all my QLineEdits so that I can override setReadOnly()

    Now, I write in Python/PyQt, not C++, for my sins. From the (C++) documentation I can reach from page http://doc.qt.io/qt-5/qlineedit.html, Public Functions, click on link void setReadOnly(bool), I get taken to http://doc.qt.io/qt-5/qlineedit.html#readOnly-prop, which describes a "Property". I did not see the definition of setReadOnly() saying virtual somewhere. So can I override it in a derived class? Is there something special about these "properties". Anything special Python/PyQt here?

    Thanks.


  • Lifetime Qt Champion

    Hi,

    You can use an event filter and listen for the ReadOnlyChange event on your QLineEdit objects.

    Hope it helps.



  • @SGaist
    Thanks, I'm changing over to use QWidget::changeEvent.

    Any comment on either of the questions in my second post above:

    1. Is QSS QLineEdit:read-only simply the same as/a shortcut for QLineEdit[readonly="true"]?

    2. Am I supposed to know from Qt C++ documentation that, e.g. QLineEdit::setReadOnly() is overridable, because I don't see virtual? My PyCharm shows it as "overridable" for me from PyQt, but I don't see where that correspond to the C++ documentation?



  • @JonB said in QLineEdit::setReadOnly(), no signal:

    @SGaist
    Thanks, I'm changing over to use QWidget::changeEvent.

    Any comment on either of the questions in my second post above:

    1. Is QSS QLineEdit:read-only simply the same as/a shortcut for QLineEdit[readonly="true"]?

    2. Am I supposed to know from Qt C++ documentation that, e.g. QLineEdit::setReadOnly() is overridable, because I don't see virtual? My PyCharm shows it as "overridable" for me from PyQt, but I don't see where that correspond to the C++ documentation?



  • @KillerSmath
    Thank you, but I'm afraid neither of your comments address my questions:

    1. The selector reference you provided is for CSS, which I know about. My questions is about Qt's QSS, which has "invented" the :read-only pseudo-state.

    2. I know all about virtual functions. My question is: is/how come http://doc.qt.io/qt-5/qlineedit.html#readOnly-prop does not show virtual anywhere, yet it is overridable at least from PyQt?


  • Lifetime Qt Champion

    Because it's not a virtual function and yes, the documentation is correct (you can check the source code)

    Python is an entirely different beast. You can modify any element of an object the way you want.



  • @SGaist
    Thank you, but sorry, let me be clear then:

    • From C++ QLineEdit::setReadOnly() is not an overridable, virtual function.
    • From PyQt, there is a "wrapper" around the whole of QLineEdit, and that has chosen to supply a function, which happens to also be named setReadOnly [but could have been called anything, e.g. pyqtSetReadOnly], which (in Python) is a virtual, overridable function.
    • PyQt's QLineEdit.setReadOnly() presumably calls the base C++ QLineEdit::setReadOnly() to effect its work.

    The big difference then is:

    • In the case of a genuine virtual Qt C++ function, which I have chosen to override in PyQt, if Qt code internally calls the virtual function from itself it will hit my Python override.
    • But in the case of this non-virtual QLineEdit::setReadOnly(), any internal Qt C++ calls to it will not be affected by the "override" I have defined from Python.

    Does the above sound right?

    EDIT I confirmed with the PyQt creator that this is indeed the way it works.


  • Lifetime Qt Champion

    Would it be possible for you to provide a small example that would confirm that ?


Log in to reply