From a0598727b8e4f061cab479eef023329d37aebadb Mon Sep 17 00:00:00 2001
From: dt <qtc-committer@nokia.com>
Date: Wed, 28 Jul 2010 13:46:12 +0200
Subject: [PATCH] Fix QtOutputFormatter to work with chunked application output

Reviewed-By: Erik Verbruggen
---
 .../projectexplorer/outputformatter.cpp       |   8 ++
 src/plugins/projectexplorer/outputformatter.h |   1 +
 .../qt4projectmanager/qtoutputformatter.cpp   | 125 +++++++++++++-----
 .../qt4projectmanager/qtoutputformatter.h     |  15 ++-
 4 files changed, 117 insertions(+), 32 deletions(-)

diff --git a/src/plugins/projectexplorer/outputformatter.cpp b/src/plugins/projectexplorer/outputformatter.cpp
index d566e008260..230565eb8d4 100644
--- a/src/plugins/projectexplorer/outputformatter.cpp
+++ b/src/plugins/projectexplorer/outputformatter.cpp
@@ -83,6 +83,14 @@ void OutputFormatter::append(const QString &text, const QTextCharFormat &format)
     cursor.insertText(text, format);
 }
 
+void OutputFormatter::clearLastLine()
+{
+    QTextCursor cursor(m_plainTextEdit->document());
+    cursor.movePosition(QTextCursor::End);
+    cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
+    cursor.removeSelectedText();
+}
+
 static QColor mix_colors(QColor a, QColor b)
 {
     return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
diff --git a/src/plugins/projectexplorer/outputformatter.h b/src/plugins/projectexplorer/outputformatter.h
index 71737a9e7c1..88e3a012230 100644
--- a/src/plugins/projectexplorer/outputformatter.h
+++ b/src/plugins/projectexplorer/outputformatter.h
@@ -70,6 +70,7 @@ protected:
     void initFormats();
     void append(const QString &text, Format format);
     void append(const QString &text, const QTextCharFormat &format);
+    void clearLastLine();
 
 private:
     QPlainTextEdit *m_plainTextEdit;
diff --git a/src/plugins/qt4projectmanager/qtoutputformatter.cpp b/src/plugins/qt4projectmanager/qtoutputformatter.cpp
index 1360e6c2a9b..5f53407bf8b 100644
--- a/src/plugins/qt4projectmanager/qtoutputformatter.cpp
+++ b/src/plugins/qt4projectmanager/qtoutputformatter.cpp
@@ -48,39 +48,102 @@ QtOutputFormatter::QtOutputFormatter(Qt4Project *project)
 
 }
 
-void QtOutputFormatter::appendApplicationOutput(const QString &text, bool onStdErr)
+LinkResult QtOutputFormatter::matchLine(const QString &line) const
 {
-    QTextCharFormat linkFormat;
-    linkFormat.setForeground(plainTextEdit()->palette().link().color());
-    linkFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
-    linkFormat.setAnchor(true);
-
-    // Create links from QML errors (anything of the form "file:///...:[line]:[column]:")
-    if (m_qmlError.indexIn(text) != -1) {
-        const int matchPos = m_qmlError.pos(1);
-        const QString leader = text.left(matchPos);
-        append(leader, onStdErr ? StdErrFormat : StdOutFormat);
-
-        const QString matched = m_qmlError.cap(1);
-        linkFormat.setAnchorHref(matched);
-        append(matched, linkFormat);
-
-        int index = matchPos + m_qmlError.matchedLength() - 1;
-        append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
-    } else if (m_qtError.indexIn(text) != -1) {
-        const int matchPos = m_qtError.pos(1);
-        const QString leader = text.left(matchPos);
-        append(leader, onStdErr ? StdErrFormat : StdOutFormat);
-
-        const QString matched = m_qtError.cap(1);
-        linkFormat.setAnchorHref(m_qtError.cap(1));
-        append(matched, linkFormat);
-
-        int index = matchPos + m_qtError.matchedLength() - 1;
-        append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
-    } else {
-        append(text, onStdErr ? StdErrFormat : StdOutFormat);
+    LinkResult lr;
+    lr.start = -1;
+    lr.end = -1;
+    if (m_qmlError.indexIn(line) != -1) {
+        lr.href = m_qmlError.cap(1);
+        lr.start = m_qmlError.pos(1);
+        lr.end = lr.start + lr.href.length();
+    } else if (m_qtError.indexIn(line) != -1) {
+        lr.href = m_qtError.cap(1);
+        lr.start = m_qtError.pos(1);
+        lr.end = lr.start + lr.href.length();
     }
+    return lr;
+}
+
+void QtOutputFormatter::appendApplicationOutput(const QString &txt, bool onStdErr)
+{
+    // Do the initialization lazily, as we don't have a plaintext edit
+    // in the ctor
+    if (!m_linkFormat.isValid()) {
+        m_linkFormat.setForeground(plainTextEdit()->palette().link().color());
+        m_linkFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+        m_linkFormat.setAnchor(true);
+    }
+
+    QString text = txt;
+    text.remove(QLatin1Char('\r'));
+
+    int start = 0;
+    int pos = txt.indexOf(QLatin1Char('\n'));
+    while (pos != -1) {
+        // Line identified
+        if (!m_lastLine.isEmpty()) {
+            // Line continuation
+            const QString newPart = txt.mid(start, pos - start + 1);
+            const QString line = m_lastLine + newPart;
+            LinkResult lr = matchLine(line);
+            if (!lr.href.isEmpty()) {
+                // Found something && line continuation
+                clearLastLine();
+                appendLine(lr, line, onStdErr);
+            } else {
+                // Found nothing, just emit the new part
+                append(newPart, onStdErr ? StdErrFormat : StdOutFormat);
+            }
+            // Handled line continuation
+            m_lastLine.clear();
+        } else {
+            const QString line = txt.mid(start, pos - start + 1);
+            LinkResult lr = matchLine(line);
+            if (!lr.href.isEmpty()) {
+                appendLine(lr, line, onStdErr);
+            } else {
+                append(line, onStdErr ? StdErrFormat : StdOutFormat);
+            }
+
+        }
+        start = pos + 1;
+        pos = txt.indexOf(QLatin1Char('\n'), start);
+    }
+
+    // Handle left over stuff
+    if (start < txt.length()) {
+        if (!m_lastLine.isEmpty()) {
+            // Line continuation
+            const QString newPart = txt.mid(start);
+            m_lastLine.append(newPart);
+            LinkResult lr = matchLine(m_lastLine);
+            if (!lr.href.isEmpty()) {
+                // Found something && line continuation
+                clearLastLine();
+                appendLine(lr, m_lastLine, onStdErr);
+            } else {
+                // Found nothing, just emit the new part
+                append(newPart, onStdErr ? StdErrFormat : StdOutFormat);
+            }
+        } else {
+            m_lastLine = txt.mid(start);
+            LinkResult lr = matchLine(m_lastLine);
+            if (!lr.href.isEmpty()) {
+                appendLine(lr, m_lastLine, onStdErr);
+            } else {
+                append(m_lastLine, onStdErr ? StdErrFormat : StdOutFormat);
+            }
+        }
+    }
+}
+
+void QtOutputFormatter::appendLine(LinkResult lr, const QString &line, bool onStdErr)
+{
+    append(line.left(lr.start), onStdErr ? StdErrFormat : StdOutFormat);
+    m_linkFormat.setAnchorHref(lr.href);
+    append(line.mid(lr.start, lr.end - lr.start), m_linkFormat);
+    append(line.mid(lr.end), onStdErr ? StdErrFormat : StdOutFormat);
 }
 
 void QtOutputFormatter::handleLink(const QString &href)
diff --git a/src/plugins/qt4projectmanager/qtoutputformatter.h b/src/plugins/qt4projectmanager/qtoutputformatter.h
index 9a039581db6..23b386d86f1 100644
--- a/src/plugins/qt4projectmanager/qtoutputformatter.h
+++ b/src/plugins/qt4projectmanager/qtoutputformatter.h
@@ -32,12 +32,20 @@
 
 #include <projectexplorer/outputformatter.h>
 #include <QtCore/QRegExp>
-#include <QSharedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QTextCharFormat>
 
 namespace Qt4ProjectManager
 {
 class Qt4Project;
 
+struct LinkResult
+{
+    int start;
+    int end;
+    QString href;
+};
+
 class QtOutputFormatter: public ProjectExplorer::OutputFormatter
 {
 public:
@@ -48,9 +56,14 @@ public:
     virtual void handleLink(const QString &href);
 
 private:
+    LinkResult matchLine(const QString &line) const;
+    void appendLine(LinkResult lr, const QString &line, bool onStdError);
+
     QRegExp m_qmlError;
     QRegExp m_qtError;
     QWeakPointer<Qt4Project> m_project;
+    QTextCharFormat m_linkFormat;
+    QString m_lastLine;
 };
 
 
-- 
GitLab