QLineEdit in extension UI: Cursor jumping to end of line (bug?)

Hi,

I’ve been writing some Slicer extensions using the Extension Wizard & Qt Designer, and it’s been mostly working very well. But I’m seeing a funny behavior, which I think is a bug.

I have extensions which use simple text fields – defined as a QLineEdit using the Qt Designer, and connected to the parameter node using the SlicerParameterName dynamic property (on the widget), which is handled by the @parameterNodeWrapper decorator on the Parameter Node class. I’ve compared my extension’s setup code with one created fresh by the Wizard, and AFAICT I’m not doing anything special, and not dropping any important initialization.

But the text lines behave as described here – whenever a user types a character in the middle of the field, the cursor jumps to the end.

I suspect this is caused by not-careful-enough code in the GUI connection – it looks like the callback created for updating parameters from the GUI (in parameterNodeWrapper.wrapper._makeGuiToParamCallback() updates the parameter node, but then this updates the GUI back. I suppose this is useful in some cases. But if this is done for text fields, we probably need to restore the cursor position as described in the answers to the StackOverflow question cited above.

Have others also run into this?

[Edit: Related, of course, Parameter node wrapper GUI connectors are missing for many widgets · Issue #7308 · Slicer/Slicer · GitHub – but that lists QLineEdit as “supported”, which it mostly is]

Yes, probably the text is being set again as part of the update. Saving and restoring the cursor position makes sense, or it could check if the value of the text is the same as what it’s trying to set and skip the update. It would make sense to add this to the wrapper code.

What about this signal?

HIH

I’ve been able to find some cases where it does work as intended, so there’s probably something a bit more involved going on. I will report more as I find out more.

No, scratch that. Those other cases were in an extension-in-development which had a broken field, and that field broke the connection to the parameter – so the cursor wasn’t jumping because the parameter wasn’t updated.

I see I am able to fix the bug by changing, in class QLineEditToStrConnector,

    def write(self, value: str) -> None:
        self._widget.text = value

to

    def write(self, value: str) -> None:
        # Writing the text of a QLineEdit moves the cursor to the end
        # We tolerate that if the value is actually changing
        if value != self._widget.text:
            self._widget.text = value

(this is one of the options suggested by @pieper IIUC)

I will post an issue and a PR for this. Thanks for your help!

Yes, that looks good :+1:

Just for closure, GitHub · Where software is built and BUG: Avoid cursor jump on edit in extension LineEdit by shai-ikko · Pull Request #8621 · Slicer/Slicer · GitHub

Thanks again!