From 0f3145862479c770ef40b608dc54fd27923e1572 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 26 Nov 2020 13:42:02 +0100 Subject: [PATCH] Core::OutputWindow: Make auto-scrolling more robust We relied on the scrollbar position as an invariant, which breaks if the formatter writes into the text editor directly. Instead, we update the "auto scroll" flag only if the user actively moves the scrollbar, which is what the intention was anyway. Task-number: QTCREATORBUG-24728 Change-Id: Ic747391b3206d6a5ba8eaf4e3cac9a70fed6dfbc Reviewed-by: Orgad Shaneh --- src/plugins/coreplugin/outputwindow.cpp | 22 +++++++++++++--------- src/plugins/coreplugin/outputwindow.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 4c9b162667c..8766305885e 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -153,6 +153,9 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget EditorManager::openEditorAt(fp.toString(), line, column); }); + connect(verticalScrollBar(), &QAbstractSlider::sliderMoved, + this, &OutputWindow::updateAutoScroll); + undoAction->setEnabled(false); redoAction->setEnabled(false); cutAction->setEnabled(false); @@ -219,9 +222,8 @@ void OutputWindow::resizeEvent(QResizeEvent *e) { //Keep scrollbar at bottom of window while resizing, to ensure we keep scrolling //This can happen if window is resized while building, or if the horizontal scrollbar appears - bool atBottom = isScrollbarAtBottom(); QPlainTextEdit::resizeEvent(e); - if (atBottom) + if (d->scrollToBottom) scrollToBottom(); } @@ -252,7 +254,6 @@ void OutputWindow::showEvent(QShowEvent *e) QPlainTextEdit::showEvent(e); if (d->scrollToBottom) verticalScrollBar()->setValue(verticalScrollBar()->maximum()); - d->scrollToBottom = false; } void OutputWindow::wheelEvent(QWheelEvent *e) @@ -272,6 +273,7 @@ void OutputWindow::wheelEvent(QWheelEvent *e) } } QAbstractScrollArea::wheelEvent(e); + updateAutoScroll(); updateMicroFocus(); } @@ -348,8 +350,6 @@ void OutputWindow::updateFilterProperties( void OutputWindow::filterNewContent() { - bool atBottom = isScrollbarAtBottom(); - QTextBlock lastBlock = document()->findBlockByNumber(d->lastFilteredBlockNumber); if (!lastBlock.isValid()) lastBlock = document()->begin(); @@ -381,7 +381,7 @@ void OutputWindow::filterNewContent() // FIXME: Why on earth is this necessary? We should probably do something else instead... setDocument(document()); - if (atBottom) + if (d->scrollToBottom) scrollToBottom(); } @@ -432,11 +432,9 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format) } } - const bool atBottom = isScrollbarAtBottom() || d->scrollTimer.isActive(); - d->scrollToBottom = true; d->formatter.appendMessage(out, format); - if (atBottom) { + if (d->scrollToBottom) { if (d->lastMessage.elapsed() < 5) { d->scrollTimer.start(); } else { @@ -449,6 +447,11 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format) enableUndoRedo(); } +void OutputWindow::updateAutoScroll() +{ + d->scrollToBottom = isScrollbarAtBottom(); +} + void OutputWindow::setMaxCharCount(int count) { d->maxCharCount = count; @@ -505,6 +508,7 @@ QMimeData *OutputWindow::createMimeDataFromSelection() const void OutputWindow::clear() { d->formatter.clear(); + d->scrollToBottom = true; } void OutputWindow::flush() diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h index c29d1a5a07c..de951ded952 100644 --- a/src/plugins/coreplugin/outputwindow.h +++ b/src/plugins/coreplugin/outputwindow.h @@ -109,6 +109,7 @@ private: void filterNewContent(); void handleNextOutputChunk(); void handleOutputChunk(const QString &output, Utils::OutputFormat format); + void updateAutoScroll(); Internal::OutputWindowPrivate *d = nullptr; };