diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc
index 6bd7eac6d79..a62ab49d8fb 100644
--- a/src/plugins/autotest/autotest.qrc
+++ b/src/plugins/autotest/autotest.qrc
@@ -11,5 +11,9 @@
images/runselected_tickmarks.png
images/runselected_tickmarks@2x.png
images/data.png
+ images/text.png
+ images/text@2x.png
+ images/visual.png
+ images/visual@2x.png
diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h
index cb557b5390e..b278509dbbc 100644
--- a/src/plugins/autotest/autotesticons.h
+++ b/src/plugins/autotest/autotesticons.h
@@ -71,6 +71,8 @@ const Utils::Icon RESULT_MESSAGEWARN({
const Utils::Icon RESULT_MESSAGEFATAL({
{":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFatalTextColor}},
Utils::Icon::Tint);
+const Utils::Icon VISUAL_DISPLAY({{":/images/visual.png", Utils::Theme::IconsBaseColor}});
+const Utils::Icon TEXT_DISPLAY({{":/images/text.png", Utils::Theme::IconsBaseColor}});
} // namespace Icons
} // namespace Autotest
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp
index 2eba52e7537..96382f5f896 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.cpp
+++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp
@@ -56,20 +56,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
static QRegExp errorLocation("^(.*)\\((\\d+)\\): error:.*$");
static QRegExp iterations("^Repeating all tests \\(iteration (\\d+)\\) \\. \\. \\.$");
- QByteArray read = outputLine;
- if (!m_unprocessed.isEmpty()) {
- read = m_unprocessed + read;
- m_unprocessed.clear();
- }
- if (!read.endsWith('\n')) {
- m_unprocessed = read;
- return;
- }
- read.chop(1); // remove the newline from the output
- if (read.endsWith('\r'))
- read.chop(1);
-
- const QString line = QString::fromLatin1(read);
+ const QString line = QString::fromLatin1(outputLine);
if (line.trimmed().isEmpty())
return;
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h
index 42031cd4d67..0ed2bf878cb 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.h
+++ b/src/plugins/autotest/gtest/gtestoutputreader.h
@@ -50,7 +50,6 @@ private:
QString m_currentTestName;
QString m_currentTestSet;
QString m_description;
- QByteArray m_unprocessed;
int m_iteration = 1;
};
diff --git a/src/plugins/autotest/images/text.png b/src/plugins/autotest/images/text.png
new file mode 100644
index 00000000000..b43b92e09a1
Binary files /dev/null and b/src/plugins/autotest/images/text.png differ
diff --git a/src/plugins/autotest/images/text@2x.png b/src/plugins/autotest/images/text@2x.png
new file mode 100644
index 00000000000..c93133a2d77
Binary files /dev/null and b/src/plugins/autotest/images/text@2x.png differ
diff --git a/src/plugins/autotest/images/visual.png b/src/plugins/autotest/images/visual.png
new file mode 100644
index 00000000000..092367618c0
Binary files /dev/null and b/src/plugins/autotest/images/visual.png differ
diff --git a/src/plugins/autotest/images/visual@2x.png b/src/plugins/autotest/images/visual@2x.png
new file mode 100644
index 00000000000..1426597449f
Binary files /dev/null and b/src/plugins/autotest/images/visual@2x.png differ
diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp
index b7cf59f1d58..fea9237717d 100644
--- a/src/plugins/autotest/testoutputreader.cpp
+++ b/src/plugins/autotest/testoutputreader.cpp
@@ -25,6 +25,7 @@
#include "testoutputreader.h"
#include "testresult.h"
+#include "testresultspane.h"
#include
#include
@@ -41,12 +42,21 @@ TestOutputReader::TestOutputReader(const QFutureInterface &future
if (m_testApplication) {
connect(m_testApplication, &QProcess::readyRead,
this, [this] () {
- while (m_testApplication->canReadLine())
- processOutput(m_testApplication->readLine());
+ while (m_testApplication->canReadLine()) {
+ QByteArray output = m_testApplication->readLine();
+ output.chop(1); // remove the newline from the output
+ if (output.endsWith('\r'))
+ output.chop(1);
+
+ emit newOutputAvailable(output);
+ processOutput(output);
+ }
});
connect(m_testApplication, &QProcess::readyReadStandardError,
this, [this] () {
- processStdError(m_testApplication->readAllStandardError());
+ const QByteArray output = m_testApplication->readAllStandardError();
+ emit newOutputAvailable(output);
+ processStdError(output);
});
}
}
diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h
index 237f23c6aca..ff04d8f4ce6 100644
--- a/src/plugins/autotest/testoutputreader.h
+++ b/src/plugins/autotest/testoutputreader.h
@@ -45,6 +45,8 @@ public:
virtual void processOutput(const QByteArray &outputLine) = 0;
virtual void processStdError(const QByteArray &output);
+signals:
+ void newOutputAvailable(const QByteArray &output);
protected:
QFutureInterface m_futureInterface;
QProcess *m_testApplication; // not owned
diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp
index 48402bbb05a..b4fbab97859 100644
--- a/src/plugins/autotest/testresultspane.cpp
+++ b/src/plugins/autotest/testresultspane.cpp
@@ -33,16 +33,15 @@
#include "testtreemodel.h"
#include "testcodeparser.h"
+#include
#include
#include
+#include
#include
#include
#include
-
#include
-
#include
-
#include
#include
@@ -54,6 +53,7 @@
#include
#include
#include
+#include
#include
#include
@@ -79,11 +79,13 @@ TestResultsPane::TestResultsPane(QObject *parent) :
Core::IOutputPane(parent),
m_context(new Core::IContext(this))
{
- m_outputWidget = new QWidget;
+ m_outputWidget = new QStackedWidget;
+ QWidget *visualOutputWidget = new QWidget;
+ m_outputWidget->addWidget(visualOutputWidget);
QVBoxLayout *outputLayout = new QVBoxLayout;
outputLayout->setMargin(0);
outputLayout->setSpacing(0);
- m_outputWidget->setLayout(outputLayout);
+ visualOutputWidget->setLayout(outputLayout);
QPalette pal;
pal.setColor(QPalette::Window,
@@ -103,7 +105,7 @@ TestResultsPane::TestResultsPane(QObject *parent) :
outputLayout->addWidget(m_summaryWidget);
- m_treeView = new ResultsTreeView(m_outputWidget);
+ m_treeView = new ResultsTreeView(visualOutputWidget);
m_treeView->setHeaderHidden(true);
m_treeView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -119,6 +121,19 @@ TestResultsPane::TestResultsPane(QObject *parent) :
outputLayout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_treeView));
+ m_textOutput = new QPlainTextEdit;
+ m_textOutput->setPalette(pal);
+ QFont font("monospace");
+ font.setStyleHint(QFont::TypeWriter);
+ m_textOutput->setFont(font);
+ m_textOutput->setWordWrapMode(QTextOption::WordWrap);
+ m_textOutput->setReadOnly(true);
+ m_outputWidget->addWidget(m_textOutput);
+
+ auto agg = new Aggregation::Aggregate;
+ agg->add(m_textOutput);
+ agg->add(new Core::BaseTextFind(m_textOutput));
+
createToolButtons();
connect(m_treeView, &Utils::TreeView::activated, this, &TestResultsPane::onItemActivated);
@@ -188,6 +203,11 @@ void TestResultsPane::createToolButtons()
initializeFilterMenu();
connect(m_filterMenu, &QMenu::triggered, this, &TestResultsPane::filterMenuTriggered);
m_filterButton->setMenu(m_filterMenu);
+ m_outputToggleButton = new QToolButton(m_treeView);
+ m_outputToggleButton->setIcon(Icons::TEXT_DISPLAY.icon());
+ m_outputToggleButton->setToolTip(tr("Switch Between Visual and Text Display"));
+ m_outputToggleButton->setEnabled(true);
+ connect(m_outputToggleButton, &QToolButton::clicked, this, &TestResultsPane::toggleOutputStyle);
}
static TestResultsPane *s_instance = nullptr;
@@ -202,6 +222,8 @@ TestResultsPane *TestResultsPane::instance()
TestResultsPane::~TestResultsPane()
{
delete m_treeView;
+ if (!m_outputWidget->parent())
+ delete m_outputWidget;
s_instance = nullptr;
}
@@ -217,6 +239,11 @@ void TestResultsPane::addTestResult(const TestResultPtr &result)
navigateStateChanged();
}
+void TestResultsPane::addOutput(const QByteArray &output)
+{
+ m_textOutput->appendPlainText(QString::fromLatin1(output));
+}
+
QWidget *TestResultsPane::outputWidget(QWidget *parent)
{
if (m_outputWidget) {
@@ -229,7 +256,8 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent)
QList TestResultsPane::toolBarWidgets() const
{
- return {m_expandCollapse, m_runAll, m_runSelected, m_stopTestRun, m_filterButton};
+ return {m_expandCollapse, m_runAll, m_runSelected, m_stopTestRun, m_outputToggleButton,
+ m_filterButton};
}
QString TestResultsPane::displayName() const
@@ -251,6 +279,7 @@ void TestResultsPane::clearContents()
m_autoScroll = AutotestPlugin::instance()->settings()->autoScroll;
connect(m_treeView->verticalScrollBar(), &QScrollBar::rangeChanged,
this, &TestResultsPane::onScrollBarRangeChanged, Qt::UniqueConnection);
+ m_textOutput->clear();
}
void TestResultsPane::visibilityChanged(bool visible)
@@ -574,6 +603,14 @@ void TestResultsPane::onSaveWholeTriggered()
}
}
+void TestResultsPane::toggleOutputStyle()
+{
+ const bool displayText = m_outputWidget->currentIndex() == 0;
+ m_outputWidget->setCurrentIndex(displayText ? 1 : 0);
+ m_outputToggleButton->setIcon(displayText ? Icons::VISUAL_DISPLAY.icon()
+ : Icons::TEXT_DISPLAY.icon());
+}
+
// helper for onCopyWholeTriggered() and onSaveWholeTriggered()
QString TestResultsPane::getWholeOutput(const QModelIndex &parent)
{
diff --git a/src/plugins/autotest/testresultspane.h b/src/plugins/autotest/testresultspane.h
index 9c5af8f50cf..6b837055672 100644
--- a/src/plugins/autotest/testresultspane.h
+++ b/src/plugins/autotest/testresultspane.h
@@ -38,6 +38,8 @@ class QKeyEvent;
class QLabel;
class QModelIndex;
class QMenu;
+class QPlainTextEdit;
+class QStackedWidget;
class QToolButton;
QT_END_NAMESPACE
@@ -88,6 +90,7 @@ public:
void goToPrev() override;
void addTestResult(const TestResultPtr &result);
+ void addOutput(const QByteArray &output);
private:
explicit TestResultsPane(QObject *parent = 0);
@@ -109,9 +112,10 @@ private:
void onCopyItemTriggered(const QModelIndex &idx);
void onCopyWholeTriggered();
void onSaveWholeTriggered();
+ void toggleOutputStyle();
QString getWholeOutput(const QModelIndex &parent = QModelIndex());
- QWidget *m_outputWidget;
+ QStackedWidget *m_outputWidget;
QFrame *m_summaryWidget;
QLabel *m_summaryLabel;
ResultsTreeView *m_treeView;
@@ -123,6 +127,8 @@ private:
QToolButton *m_runSelected;
QToolButton *m_stopTestRun;
QToolButton *m_filterButton;
+ QToolButton *m_outputToggleButton;
+ QPlainTextEdit *m_textOutput;
QMenu *m_filterMenu;
bool m_wasVisibleBefore = false;
bool m_autoScroll = false;
diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp
index ea83e1728c1..846a3f81220 100644
--- a/src/plugins/autotest/testrunner.cpp
+++ b/src/plugins/autotest/testrunner.cpp
@@ -157,6 +157,8 @@ static void performTestRun(QFutureInterface &futureInterface,
QScopedPointer outputReader;
outputReader.reset(testConfiguration->outputReader(futureInterface, &testProcess));
QTC_ASSERT(outputReader, continue);
+ TestRunner::connect(outputReader.data(), &TestOutputReader::newOutputAvailable,
+ TestResultsPane::instance(), &TestResultsPane::addOutput);
if (futureInterface.isCanceled())
break;
@@ -364,7 +366,8 @@ void TestRunner::debugTests()
if (useOutputProcessor) {
TestOutputReader *outputreader = config->outputReader(*futureInterface, 0);
-
+ connect(outputreader, &TestOutputReader::newOutputAvailable,
+ TestResultsPane::instance(), &TestResultsPane::addOutput);
connect(runControl, &ProjectExplorer::RunControl::appendMessageRequested,
this, [this, outputreader]
(ProjectExplorer::RunControl *, const QString &msg, Utils::OutputFormat format) {