QLineEdit: How to show a processed text



  • Hi :-)

    A QLineEdit can show dots or stars instead of the entered text when one sets it to password mode. Is it also possible to display a custom processed text?

    My specific use case would be to show a small dot (or similar) instead of spaces so that they are visualized.

    As far as I can grasp it, one can only read the displayed text, but not set it and one can only set an echo mode from an existing enum. Apparently, the generation of the displayed text happens in non-public parts of the class, so I also can't override it.

    Is it possible to implement a custom echo mode? Thanks for all hints!


  • Lifetime Qt Champion

    Hi,

    If I understand correctly you can do that using a proxy style:

    class ProxyStyle : public QProxyStyle
    {
        int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
        {
            if (hint == QStyle::SH_LineEdit_PasswordCharacter) {
                return QChar('$').unicode();
            }
            return QProxyStyle::styleHint(hint, option, widget, returnData);
        }
    };
    

    Set it on your QLineEdit and the echo char used will be a $ but you can change it to your liking.



  • @SGaist Thanks for the hint with QProxyStyle, but I don't think this is what I need … this will only change the displayed character for the password display, won't it?

    I want e. g. to enter some text with spaces in between and what the QLineEdit should display would e. g. be some·text·with·spaces·in·between, simply the space characters replaced with some visible characters. But when requesting text(), I want to have the actually entered text, not the displayed one.



  • The Qt Linguist does this exact thing for the translation line edits … but I didn't find how they do it yet …


  • Lifetime Qt Champion



  • Apparently, they don't use a QLineEdit, but a QTextEdit that is configured to edit just one line. Maybe they do it for a reason ;-)


  • Lifetime Qt Champion

    Hi
    For the fun of it i tried the obvious thing.

    class NoSpaceLineEdit : public QLineEdit
    {
        Q_OBJECT
    public:
        explicit NoSpaceLineEdit(QWidget *parent = nullptr) : QLineEdit(parent){}
    protected:
        virtual void paintEvent(QPaintEvent *e) override
        {
            setText(text().replace(' ', '*'));
            QLineEdit::paintEvent(e);
        }
    };
    
    

    which does display * for space but also kills selection as setText resets it, so
    its a no go.



  • I ended up with the following (a bit hacky ;-) solution (I used QPlainTextEdit anyway in my project, so I chose this one):

    Edit: One also has to process pasted data so that no newline can be added

    SpacesLineEdit.h:

    #include <QPlainTextEdit>
    
    class SpacesLineEdit : public QPlainTextEdit
    {
        Q_OBJECT
    
    public:
        explicit SpacesLineEdit(QWidget *parent = nullptr);
    
    protected:
        virtual void keyPressEvent(QKeyEvent *event) override;
        virtual QSize sizeHint() const override;
        virtual QSize minimumSizeHint() const override;
        virtual void insertFromMimeData(const QMimeData *source) override;
    
    private:
        QSize m_sizeHint;
    
    };
    

    SpacesLineEdit.cpp:

    #include "SpacesLineEdit.h"
    #include <QLineEdit>
    
    SpacesLineEdit::SpacesLineEdit(QWidget *parent) : QPlainTextEdit(parent)
    {
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setLineWrapMode(QPlainTextEdit::NoWrap);
        setTabChangesFocus(true);
    
        QTextOption option = document()->defaultTextOption();
        option.setFlags(option.flags() | QTextOption::ShowTabsAndSpaces);
        document()->setDefaultTextOption(option);
    
        // Stealing the sizeHint from a plain QLineEdit will do for now :-P
        QLineEdit lineEdit;
        m_sizeHint = lineEdit.sizeHint();
    }
    
    QSize SpacesLineEdit::minimumSizeHint() const
    {
        return m_sizeHint;
    }
    
    QSize SpacesLineEdit::sizeHint() const
    {
        return m_sizeHint;
    }
    
    void SpacesLineEdit::keyPressEvent(QKeyEvent *event)
    {
        if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
            event->ignore();
            return;
        }
        QPlainTextEdit::keyPressEvent(event);
    }
    
    void SpacesLineEdit::insertFromMimeData(const QMimeData *source)
    {
        QString text = source->text();
        text.replace(QLatin1String("\r\n"), QLatin1String(" "));
        text.replace(QLatin1Char('\n'), QLatin1String(" "));
        text.replace(QLatin1Char('\r'), QLatin1String(" "));
    
        QMimeData processedSource;
        processedSource.setText(text);
        QPlainTextEdit::insertFromMimeData(&processedSource);
    }
    

    Works fine … only question would be how to implement the sizeHint and minimalSizeHint in a "correct" way ;-) I couldn't adapt the implementation from Linguist … also, I couldn't take the functions from QLineEdit, as they access d pointer private stuff …


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.