aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/outputformatter.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2020-03-19 16:00:37 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2020-03-20 13:48:15 +0000
commit04a99c1de16e1d04bcc1908fec7464d15b421702 (patch)
tree1f298306aae0ae288bac75b0691c8968e6c72e6b /src/libs/utils/outputformatter.cpp
parent7158e676121767f43ac542cc3c958d8ed1279436 (diff)
Remove the limitation that output formatters have to be exclusive
Introduce an aggregating output formatter that forwards its input to a sub-formatter that feels responsible for it, or otherwise lets the base class handle it. Our output panes now use such an aggregating formatter. In particular, this means that in the future, we won't have to stuff all run control output formatting into the Qt output formatter anymore. Change-Id: I5498f200a61db10ccff3ec8974c6825da7f7072d Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/libs/utils/outputformatter.cpp')
-rw-r--r--src/libs/utils/outputformatter.cpp86
1 files changed, 82 insertions, 4 deletions
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index ea40ddadee..a1a98a1fbe 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -25,8 +25,10 @@
#include "ansiescapecodehandler.h"
#include "outputformatter.h"
+#include "qtcassert.h"
#include "synchronousprocess.h"
#include "theme/theme.h"
+#include "utils/optional.h"
#include <QPair>
#include <QPlainTextEdit>
@@ -44,6 +46,7 @@ public:
QTextCursor cursor;
AnsiEscapeCodeHandler escapeCodeHandler;
QPair<QString, OutputFormat> incompleteLine;
+ optional<QTextCharFormat> formatOverride;
bool boldFontEnabled = true;
bool prependCarriageReturn = false;
};
@@ -75,9 +78,15 @@ void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format)
{
- if (!d->cursor.atEnd() && text.startsWith('\n'))
- d->cursor.movePosition(QTextCursor::End);
- doAppendMessage(text, d->formats[format]);
+ if (handleMessage(text, format) == Status::NotHandled)
+ appendMessageDefault(text, format);
+}
+
+OutputFormatter::Status OutputFormatter::handleMessage(const QString &text, OutputFormat format)
+{
+ Q_UNUSED(text);
+ Q_UNUSED(format);
+ return Status::NotHandled;
}
void OutputFormatter::doAppendMessage(const QString &text, const QTextCharFormat &format)
@@ -118,6 +127,16 @@ QTextCharFormat OutputFormatter::linkFormat(const QTextCharFormat &inputFormat,
return result;
}
+void OutputFormatter::overrideTextCharFormat(const QTextCharFormat &fmt)
+{
+ d->formatOverride = fmt;
+}
+
+void OutputFormatter::appendMessageDefault(const QString &text, OutputFormat format)
+{
+ doAppendMessage(text, d->formatOverride ? d->formatOverride.value() : d->formats[format]);
+}
+
void OutputFormatter::clearLastLine()
{
// Note that this approach will fail if the text edit is not read-only and users
@@ -158,9 +177,10 @@ void OutputFormatter::dumpIncompleteLine(const QString &line, OutputFormat forma
d->incompleteLine.second = format;
}
-void OutputFormatter::handleLink(const QString &href)
+bool OutputFormatter::handleLink(const QString &href)
{
Q_UNUSED(href)
+ return false;
}
void OutputFormatter::clear()
@@ -236,4 +256,62 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
}
}
+class AggregatingOutputFormatter::Private
+{
+public:
+ QList<OutputFormatter *> formatters;
+ OutputFormatter *nextFormatter = nullptr;
+};
+
+AggregatingOutputFormatter::AggregatingOutputFormatter() : d(new Private) {}
+AggregatingOutputFormatter::~AggregatingOutputFormatter() { delete d; }
+
+void AggregatingOutputFormatter::setFormatters(const QList<OutputFormatter *> &formatters)
+{
+ for (OutputFormatter * const f : formatters)
+ f->setPlainTextEdit(plainTextEdit());
+ d->formatters = formatters;
+ d->nextFormatter = nullptr;
+}
+
+OutputFormatter::Status AggregatingOutputFormatter::handleMessage(const QString &text,
+ OutputFormat format)
+{
+ if (d->nextFormatter) {
+ switch (d->nextFormatter->handleMessage(text, format)) {
+ case Status::Done:
+ d->nextFormatter = nullptr;
+ return Status::Done;
+ case Status::InProgress:
+ return Status::InProgress;
+ case Status::NotHandled:
+ QTC_CHECK(false);
+ d->nextFormatter = nullptr;
+ return Status::NotHandled;
+ }
+ }
+ QTC_CHECK(!d->nextFormatter);
+ for (OutputFormatter * const formatter : qAsConst(d->formatters)) {
+ switch (formatter->handleMessage(text, format)) {
+ case Status::Done:
+ return Status::Done;
+ case Status::InProgress:
+ d->nextFormatter = formatter;
+ return Status::InProgress;
+ case Status::NotHandled:
+ break;
+ }
+ }
+ return Status::NotHandled;
+}
+
+bool AggregatingOutputFormatter::handleLink(const QString &href)
+{
+ for (OutputFormatter * const f : qAsConst(d->formatters)) {
+ if (f->handleLink(href))
+ return true;
+ }
+ return false;
+}
+
} // namespace Utils