diff --git a/src/libs/utils/ansiescapecodehandler.cpp b/src/libs/utils/ansiescapecodehandler.cpp index 190093767f1..14d5dd8f8e1 100644 --- a/src/libs/utils/ansiescapecodehandler.cpp +++ b/src/libs/utils/ansiescapecodehandler.cpp @@ -100,12 +100,18 @@ QList AnsiEscapeCodeHandler::parseText(const FormattedText &input const QChar semicolon = QLatin1Char(';'); const QChar colorTerminator = QLatin1Char('m'); + const QChar eraseToEol = QLatin1Char('K'); // strippedText always starts with "\e[" QString strippedText = input.text.mid(escapePos); while (!strippedText.isEmpty()) { while (strippedText.startsWith(escape)) { strippedText.remove(0, 2); + // \e[K is not supported. Just strip it. + if (strippedText.startsWith(eraseToEol)) { + strippedText.remove(0, 1); + continue; + } // get the number QString strNumber; QStringList numbers; diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index 419f2e2a151..74b69ee9df7 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -39,6 +39,7 @@ OutputFormatter::OutputFormatter() , m_plainTextEdit(0) , m_formats(0) , m_escapeCodeHandler(new AnsiEscapeCodeHandler) + , m_overwriteOutput(false) { } @@ -67,7 +68,15 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format) foreach (const FormattedText &output, m_escapeCodeHandler->parseText(FormattedText(text, m_formats[format]))) { - cursor.insertText(output.text, output.format); + int startPos = 0; + int crPos = -1; + while ((crPos = output.text.indexOf(QLatin1Char('\r'), startPos)) >= 0) { + append(cursor, output.text.mid(startPos, crPos - startPos), output.format); + startPos = crPos + 1; + m_overwriteOutput = true; + } + if (startPos < output.text.count()) + append(cursor, output.text.mid(startPos), output.format); } } @@ -76,6 +85,17 @@ QTextCharFormat OutputFormatter::charFormat(OutputFormat format) const return m_formats[format]; } +void OutputFormatter::append(QTextCursor &cursor, const QString &text, + const QTextCharFormat &format) +{ + if (m_overwriteOutput) { + cursor.clearSelection(); + cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); + m_overwriteOutput = false; + } + cursor.insertText(text, format); +} + void OutputFormatter::clearLastLine() { QTextCursor cursor(m_plainTextEdit->document()); diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h index b18e17ff059..7fa6cc1639d 100644 --- a/src/libs/utils/outputformatter.h +++ b/src/libs/utils/outputformatter.h @@ -37,9 +37,10 @@ #include QT_BEGIN_NAMESPACE +class QColor; class QPlainTextEdit; class QTextCharFormat; -class QColor; +class QTextCursor; QT_END_NAMESPACE namespace Utils { @@ -68,6 +69,7 @@ protected: void initFormats(); virtual void clearLastLine(); QTextCharFormat charFormat(OutputFormat format) const; + void append(QTextCursor &cursor, const QString &text, const QTextCharFormat &format); static QColor mixColors(const QColor &a, const QColor &b); @@ -76,6 +78,7 @@ private: QTextCharFormat *m_formats; QFont m_font; AnsiEscapeCodeHandler *m_escapeCodeHandler; + bool m_overwriteOutput; }; } // namespace Utils diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp index cd47f9e2dcb..7bbda50d8aa 100644 --- a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp +++ b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp @@ -31,6 +31,7 @@ #include "command.h" #include "vcsbaseplugin.h" +#include #include #include @@ -61,7 +62,9 @@ CheckoutProgressWizardPage::CheckoutProgressWizardPage(QWidget *parent) : resize(264, 200); QVBoxLayout *verticalLayout = new QVBoxLayout(this); m_logPlainTextEdit = new QPlainTextEdit; + m_formatter = new Utils::OutputFormatter; m_logPlainTextEdit->setReadOnly(true); + m_formatter->setPlainTextEdit(m_logPlainTextEdit); verticalLayout->addWidget(m_logPlainTextEdit); @@ -74,6 +77,7 @@ CheckoutProgressWizardPage::~CheckoutProgressWizardPage() { if (m_state == Running) // Paranoia! QApplication::restoreOverrideCursor(); + delete m_formatter; } void CheckoutProgressWizardPage::setStartedStatus(const QString &startedStatus) @@ -131,20 +135,7 @@ void CheckoutProgressWizardPage::slotFinished(bool ok, int exitCode, const QVari void CheckoutProgressWizardPage::slotOutput(const QString &text) { - int startPos = 0; - int crPos = -1; - const QString ansiEraseToEol = QLatin1String("\x1b[K"); - while ((crPos = text.indexOf(QLatin1Char('\r'), startPos)) >= 0) { - QString part = text.mid(startPos, crPos - startPos); - // Discard ANSI erase-to-eol - if (part.endsWith(ansiEraseToEol)) - part.chop(ansiEraseToEol.length()); - outputText(part); - startPos = crPos + 1; - m_overwriteOutput = true; - } - if (startPos < text.count()) - outputText(text.mid(startPos)); + m_formatter->appendMessage(text, Utils::StdOutFormat); } void CheckoutProgressWizardPage::slotError(const QString &text) @@ -152,18 +143,6 @@ void CheckoutProgressWizardPage::slotError(const QString &text) m_error.append(text); } -void CheckoutProgressWizardPage::outputText(const QString &text) -{ - if (m_overwriteOutput) { - QTextCursor cursor = m_logPlainTextEdit->textCursor(); - cursor.clearSelection(); - cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); - m_logPlainTextEdit->setTextCursor(cursor); - m_overwriteOutput = false; - } - m_logPlainTextEdit->insertPlainText(text); -} - void CheckoutProgressWizardPage::terminate() { if (m_command) diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.h b/src/plugins/vcsbase/checkoutprogresswizardpage.h index b87b017af80..e5c6cfbd843 100644 --- a/src/plugins/vcsbase/checkoutprogresswizardpage.h +++ b/src/plugins/vcsbase/checkoutprogresswizardpage.h @@ -38,6 +38,8 @@ class QPlainTextEdit; class QLabel; QT_END_NAMESPACE +namespace Utils { class OutputFormatter; } + namespace VcsBase { class Command; @@ -70,9 +72,8 @@ private slots: void slotError(const QString &text); private: - void outputText(const QString &text); - QPlainTextEdit *m_logPlainTextEdit; + Utils::OutputFormatter *m_formatter; QLabel *m_statusLabel; Command *m_command;