c++qtqt5qlineedit

QLineEdit: Show a processed text, not the entered one, but keep it (custom echo mode)


I want a QLineEdit not to display the entered text, but a processed version, while keeping the original text and returning it when it's requested via text(). Like with the password echo mode, but I don't want each character to be masked. I want to visualize spaces:

E. g. when some text with spaces in between is entered, some·text·with·spaces·in·between should be shown so that one can see the spaces. Just like when e. g. you activate that ¶ symbol in LibreOffice.

There's QLineEdit::displayText(), but it can't be set, only read. Also, the echoMode can only be set via an enum, and with EchoMode::Password set, the processing seems to happen in private functions of QLineEdit, so that I also can't override some processing function.

Is this possible?


Solution

  • IMHO, it will be hard to do that with a QLineEdit.

    But, it's quite easy with a QTextEdit by configuring its QTextDocument:

    class TextEdit : public QTextEdit
    {
        Q_OBJECT
    public:
            explicit TextEdit(QWidget* parent=nullptr): QTextEdit (parent)
            {
                    QTextDocument* doc = new QTextDocument(this);
                    setDocument(doc);
                    QTextOption option;
                    option.setFlags(QTextOption::ShowLineAndParagraphSeparators | QTextOption::ShowTabsAndSpaces);
                    doc->setDefaultTextOption(option);
            }
    };
    

    Then, you have to configure the TextEdit to get the same behavior than a QLineEdit (i.e. one line, no scrollbar, etc.).

    A quick example as a good start:

    class OneLineTextEdit : public QTextEdit
    {
        Q_OBJECT
    public:
            explicit OneLineTextEdit(QWidget* parent=nullptr): QTextEdit (parent)
            {
                    setTabChangesFocus(true);
                    setWordWrapMode(QTextOption::NoWrap);
                    // No scrollbars
                    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    
                    // One line only
                    setFixedHeight(sizeHint().height());
    
                    // Show the space/tabs/return
                    QTextDocument* doc = new QTextDocument(this);
                    setDocument(doc);
                    QTextOption option;
                    option.setFlags(QTextOption::ShowLineAndParagraphSeparators | QTextOption::ShowTabsAndSpaces);
                    doc->setDefaultTextOption(option);
            }
    
        // We don't want to write more than one line
        void keyPressEvent(QKeyEvent *event)
        {
            if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
                    return event->ignore();
            return QTextEdit::keyPressEvent(event);
        }
    
        // Don't display more than one line
        QSize sizeHint() const
        {
            QFontMetrics const fm(font());
            int const h = qMax(fm.height(), 14) + 4;
            int const w = fm.width(QLatin1Char('x')) * 17 + 4;
            QStyleOption opt;
            opt.initFrom(this);
            // Use the current app style to find the size of a real QLineEdit
            return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
                    expandedTo(QApplication::globalStrut()), this));
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        OneLineTextEdit *editor = new OneLineTextEdit();
        editor->show();
    
        return app.exec();
    };