From b819fa39f3053f047f5389456570d00020051688 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Mon, 17 Aug 2009 22:54:38 +0200 Subject: [PATCH] Improve inputline behavior * Don't show scrollbars in single line mode * Don't update geometry more often than necessary * Allow selecting text with shift + up/down --- src/qtui/bufferwidget.cpp | 11 ++- src/qtui/inputwidget.cpp | 2 +- src/uisupport/multilineedit.cpp | 123 +++++++++++++++++--------------- src/uisupport/multilineedit.h | 9 +-- 4 files changed, 78 insertions(+), 67 deletions(-) diff --git a/src/qtui/bufferwidget.cpp b/src/qtui/bufferwidget.cpp index a58723da..c514ab81 100644 --- a/src/qtui/bufferwidget.cpp +++ b/src/qtui/bufferwidget.cpp @@ -161,11 +161,12 @@ bool BufferWidget::eventFilter(QObject *watched, QEvent *event) { QKeyEvent *keyEvent = static_cast(event); + MultiLineEdit *inputLine = qobject_cast(watched); + if(!inputLine) + return false; + // Intercept copy key presses if(keyEvent == QKeySequence::Copy) { - MultiLineEdit *inputLine = qobject_cast(watched); - if(!inputLine) - return false; if(inputLine->hasSelectedText()) return false; ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); @@ -174,6 +175,10 @@ bool BufferWidget::eventFilter(QObject *watched, QEvent *event) { return true; } + // We don't want to steal cursor movement keys if the input line is in multiline mode + if(!inputLine->isSingleLine()) + return false; + switch(keyEvent->key()) { case Qt::Key_Up: case Qt::Key_Down: diff --git a/src/qtui/inputwidget.cpp b/src/qtui/inputwidget.cpp index 13833192..dc8b6a6a 100644 --- a/src/qtui/inputwidget.cpp +++ b/src/qtui/inputwidget.cpp @@ -146,7 +146,7 @@ void InputWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int void InputWidget::updateEnabledState() { QModelIndex currentIndex = selectionModel()->currentIndex(); - + const Network *net = Client::networkModel()->networkByIndex(currentIndex); bool enabled = false; if(net) { diff --git a/src/uisupport/multilineedit.cpp b/src/uisupport/multilineedit.cpp index 7bc6c235..5b81ab32 100644 --- a/src/uisupport/multilineedit.cpp +++ b/src/uisupport/multilineedit.cpp @@ -39,8 +39,7 @@ MultiLineEdit::MultiLineEdit(QWidget *parent) #endif idx(0), _mode(SingleLine), - _wrapMode(QTextOption::NoWrap), - _numLines(1), + _singleLine(true), _minHeight(1), _maxHeight(5), _scrollBarsEnabled(true), @@ -51,16 +50,11 @@ MultiLineEdit::MultiLineEdit(QWidget *parent) #endif setAcceptRichText(false); - setWordWrapMode(QTextOption::NoWrap); #ifdef HAVE_KDE enableFindReplace(false); #endif - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setMode(SingleLine); - reset(); connect(this, SIGNAL(textChanged()), this, SLOT(on_textChanged())); @@ -71,7 +65,7 @@ MultiLineEdit::~MultiLineEdit() { void MultiLineEdit::setCustomFont(const QFont &font) { setFont(font); - updateGeometry(); + computeSizeHint(); } void MultiLineEdit::setMode(Mode mode) { @@ -81,20 +75,12 @@ void MultiLineEdit::setMode(Mode mode) { _mode = mode; } -void MultiLineEdit::setWrapMode(QTextOption::WrapMode wrapMode) { - if(_wrapMode == wrapMode) - return; - - _wrapMode = wrapMode; - setWordWrapMode(wrapMode); -} - void MultiLineEdit::setMinHeight(int lines) { if(lines == _minHeight) return; _minHeight = lines; - updateGeometry(); + computeSizeHint(); } void MultiLineEdit::setMaxHeight(int lines) { @@ -102,7 +88,7 @@ void MultiLineEdit::setMaxHeight(int lines) { return; _maxHeight = lines; - updateGeometry(); + computeSizeHint(); } void MultiLineEdit::enableScrollBars(bool enable) { @@ -110,13 +96,6 @@ void MultiLineEdit::enableScrollBars(bool enable) { return; _scrollBarsEnabled = enable; - if(enable && numLines() > 1) { - // the vertical scrollbar must be enabled/disabled manually; - // ScrollBarAsNeeded leads to flicker because of the dynamic widget resize - setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - } else { - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - } updateScrollBars(); } @@ -127,6 +106,11 @@ void MultiLineEdit::updateScrollBars() { setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); else setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + if(!_scrollBarsEnabled || isSingleLine()) + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + else + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); } void MultiLineEdit::resizeEvent(QResizeEvent *event) { @@ -134,13 +118,14 @@ void MultiLineEdit::resizeEvent(QResizeEvent *event) { QTextEdit::resizeEvent(event); } -QSize MultiLineEdit::sizeHint() const { +void MultiLineEdit::computeSizeHint() { QFontMetrics fm(font()); - int _minPixelHeight = fm.lineSpacing() * _minHeight; - int _maxPixelHeight = fm.lineSpacing() * _maxHeight; + int minPixelHeight = fm.lineSpacing() * _minHeight; + int maxPixelHeight = fm.lineSpacing() * _maxHeight; + int scrollBarHeight = horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0; // use the style to determine a decent size - int h = qMin(qMax((int)document()->size().height(), _minPixelHeight), _maxPixelHeight) + 2 * frameWidth(); + int h = qMin(qMax((int)document()->size().height() + scrollBarHeight, minPixelHeight), maxPixelHeight) + 2 * frameWidth(); QStyleOptionFrameV2 opt; opt.initFrom(this); opt.rect = QRect(0, 0, 100, h); @@ -148,7 +133,18 @@ QSize MultiLineEdit::sizeHint() const { opt.midLineWidth = midLineWidth(); opt.state |= QStyle::State_Sunken; QSize s = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(100, h).expandedTo(QApplication::globalStrut()), this); - return s; + if(s != _sizeHint) { + _sizeHint = s; + updateGeometry(); + } +} + +QSize MultiLineEdit::sizeHint() const { + if(!_sizeHint.isValid()) { + MultiLineEdit *that = const_cast(this); + that->computeSizeHint(); + } + return _sizeHint; } QSize MultiLineEdit::minimumSizeHint() const { @@ -224,49 +220,58 @@ void MultiLineEdit::keyPressEvent(QKeyEvent *event) { } switch(event->key()) { - case Qt::Key_Up: { - event->accept(); - if(!(event->modifiers() & Qt::ControlModifier)) { - int pos = textCursor().position(); - moveCursor(QTextCursor::Up); - if(pos == textCursor().position()) // already on top line -> history + case Qt::Key_Up: + if(event->modifiers() & Qt::ShiftModifier) + break; + { + event->accept(); + if(!(event->modifiers() & Qt::ControlModifier)) { + int pos = textCursor().position(); + moveCursor(QTextCursor::Up); + if(pos == textCursor().position()) // already on top line -> history + historyMoveBack(); + } else historyMoveBack(); - } else - historyMoveBack(); - break; - } + return; + } - case Qt::Key_Down: { - event->accept(); - if(!(event->modifiers() & Qt::ControlModifier)) { - int pos = textCursor().position(); - moveCursor(QTextCursor::Down); - if(pos == textCursor().position()) // already on bottom line -> history + case Qt::Key_Down: + if(event->modifiers() & Qt::ShiftModifier) + break; + { + event->accept(); + if(!(event->modifiers() & Qt::ControlModifier)) { + int pos = textCursor().position(); + moveCursor(QTextCursor::Down); + if(pos == textCursor().position()) // already on bottom line -> history + historyMoveForward(); + } else historyMoveForward(); - } else - historyMoveForward(); - break; - } + return; + } case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Select: event->accept(); on_returnPressed(); - break; + return; - // We don't want to have the tab key react if no completer is installed + // We don't want to have the tab key react even if no completer is installed case Qt::Key_Tab: event->accept(); - break; + return; default: + ; + } + + #ifdef HAVE_KDE - KTextEdit::keyPressEvent(event); + KTextEdit::keyPressEvent(event); #else - QTextEdit::keyPressEvent(event); + QTextEdit::keyPressEvent(event); #endif - } } void MultiLineEdit::on_returnPressed() { @@ -289,11 +294,13 @@ void MultiLineEdit::on_textChanged() { if(_mode == SingleLine) newText.replace('\n', ' '); + _singleLine = (newText.indexOf('\n') < 0); + if(document()->size().height() != _lastDocumentHeight) { _lastDocumentHeight = document()->size().height(); on_documentHeightChanged(_lastDocumentHeight); } - updateGeometry(); + computeSizeHint(); } void MultiLineEdit::on_documentHeightChanged(qreal) { @@ -307,6 +314,7 @@ void MultiLineEdit::reset() { QTextBlockFormat format = textCursor().blockFormat(); format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents textCursor().setBlockFormat(format); + updateScrollBars(); } void MultiLineEdit::showHistoryEntry() { @@ -318,4 +326,5 @@ void MultiLineEdit::showHistoryEntry() { cursor.setBlockFormat(format); cursor.movePosition(QTextCursor::End); setTextCursor(cursor); + updateScrollBars(); } diff --git a/src/uisupport/multilineedit.h b/src/uisupport/multilineedit.h index 13485924..4a578fa6 100644 --- a/src/uisupport/multilineedit.h +++ b/src/uisupport/multilineedit.h @@ -58,13 +58,13 @@ public: inline void insert(const QString &newText) { insertPlainText(newText); } inline void backspace() { keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier)); } inline bool hasSelectedText() { return textCursor().hasSelection(); } + inline bool isSingleLine() const { return _singleLine; } virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; public slots: void setMode(Mode mode); - void setWrapMode(QTextOption::WrapMode = QTextOption::NoWrap); void setMinHeight(int numLines); void setMaxHeight(int numLines); void enableScrollBars(bool enable = true); @@ -90,8 +90,7 @@ private: QHash tempHistory; qint32 idx; Mode _mode; - QTextOption::WrapMode _wrapMode; - int _numLines; + bool _singleLine; int _minHeight; int _maxHeight; bool _scrollBarsEnabled; @@ -102,9 +101,7 @@ private: void reset(); void showHistoryEntry(); void updateScrollBars(); - - inline int numLines() const { return _numLines; } - void setNumLines(int); + void computeSizeHint(); }; #endif -- 2.20.1