From 5a298106bc0ac75b19d5027f013236aa5ef80ad0 Mon Sep 17 00:00:00 2001 From: gxalpha Date: Wed, 11 May 2022 21:04:49 +0200 Subject: [PATCH] UI: Add vertically expanding LineEdit Widget Meant to behave like a QLineEdit (disallowing newlines and having a maximum length), but show multiple lines. --- UI/CMakeLists.txt | 2 + UI/lineedit-autoresize.cpp | 94 ++++++++++++++++++++++++++++++++++++++ UI/lineedit-autoresize.hpp | 32 +++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 UI/lineedit-autoresize.cpp create mode 100644 UI/lineedit-autoresize.hpp diff --git a/UI/CMakeLists.txt b/UI/CMakeLists.txt index 64ad16f7f..80a85d399 100644 --- a/UI/CMakeLists.txt +++ b/UI/CMakeLists.txt @@ -188,6 +188,8 @@ target_sources( focus-list.hpp hotkey-edit.cpp hotkey-edit.hpp + lineedit-autoresize.cpp + lineedit-autoresize.hpp locked-checkbox.cpp locked-checkbox.hpp log-viewer.cpp diff --git a/UI/lineedit-autoresize.cpp b/UI/lineedit-autoresize.cpp new file mode 100644 index 000000000..30866b75f --- /dev/null +++ b/UI/lineedit-autoresize.cpp @@ -0,0 +1,94 @@ +#include "lineedit-autoresize.hpp" + +LineEditAutoResize::LineEditAutoResize() +{ + connect(this, SIGNAL(textChanged()), this, SLOT(checkTextLength())); + connect(document()->documentLayout(), + SIGNAL(documentSizeChanged(const QSizeF &)), this, + SLOT(resizeVertically(const QSizeF &))); +} + +void LineEditAutoResize::checkTextLength() +{ + QString text = toPlainText(); + if (text.length() > m_maxLength) { + setPlainText(text.left(m_maxLength)); + QTextCursor cursor = textCursor(); + cursor.setPosition(m_maxLength); + setTextCursor(cursor); + } +} + +int LineEditAutoResize::maxLength() +{ + return m_maxLength; +} + +void LineEditAutoResize::setMaxLength(int length) +{ + m_maxLength = length; +} + +void LineEditAutoResize::keyPressEvent(QKeyEvent *event) +{ + /* Always allow events with modifiers, for example to Copy content */ + Qt::KeyboardModifiers modifiers = event->modifiers(); + if (modifiers != Qt::NoModifier && modifiers != Qt::ShiftModifier) { + QTextEdit::keyPressEvent(event); + return; + } + + switch (event->key()) { + /* Always ignore the return key and send the signal instead */ + case Qt::Key_Return: + event->ignore(); + emit returnPressed(); + break; + /* Always allow navigation and deletion */ + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + case Qt::Key_Delete: + case Qt::Key_Backspace: + QTextEdit::keyPressEvent(event); + break; + /* Allow only if the content is not already at max length. + * Some keys with modifiers should still be allowed though + * (for example for Copy), and we don't want to make assumptions + * about which modifiers are okay and which aren't, so let's + * allow all. Actions that will still exceed the limit (like + * Paste) can be caught in a later step. */ + default: + if (toPlainText().length() >= m_maxLength && + event->modifiers() == Qt::NoModifier && + !textCursor().hasSelection()) + event->ignore(); + else + QTextEdit::keyPressEvent(event); + break; + } +} + +void LineEditAutoResize::resizeVertically(const QSizeF &newSize) +{ + setMaximumHeight(newSize.height() + 7); +} + +QString LineEditAutoResize::text() +{ + return toPlainText(); +} + +void LineEditAutoResize::setText(const QString &text) +{ + QMetaObject::invokeMethod(this, "SetPlainText", Qt::QueuedConnection, + Q_ARG(const QString &, text)); +} + +void LineEditAutoResize::SetPlainText(const QString &text) +{ + setPlainText(text); +} diff --git a/UI/lineedit-autoresize.hpp b/UI/lineedit-autoresize.hpp new file mode 100644 index 000000000..1d10dff1b --- /dev/null +++ b/UI/lineedit-autoresize.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +class LineEditAutoResize : public QTextEdit { + Q_OBJECT + + Q_PROPERTY(int maxLength READ maxLength WRITE setMaxLength) + +public: + LineEditAutoResize(); + int maxLength(); + void setMaxLength(int length); + QString text(); + void setText(const QString &text); + +private: + int m_maxLength; + +signals: + void returnPressed(); + +private slots: + void checkTextLength(); + void resizeVertically(const QSizeF &newSize); + void SetPlainText(const QString &text); + +protected: + virtual void keyPressEvent(QKeyEvent *event) override; +};