summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Stenger <christian.stenger@theqtcompany.com>2015-08-19 13:19:28 +0200
committerChristian Stenger <christian.stenger@theqtcompany.com>2015-09-09 13:33:18 +0300
commit292b4847dc99f0fda01395004ed317775d89ee33 (patch)
treee26600e58cfeb50a9148dd0c02365bd22c72afb7
parent0d114c602d391f4d34146efcbdfa9f714bc5bac6 (diff)
downloadqt-creator-292b4847dc99f0fda01395004ed317775d89ee33.tar.gz
Add capability to store/copy output from results pane
Change-Id: Ie32a374cac851009df3d2289f471bbb697788198 Reviewed-by: Riitta-Leena Miettinen <riitta-leena.miettinen@theqtcompany.com> Reviewed-by: David Schulz <david.schulz@theqtcompany.com> Reviewed-by: Niels Weber <niels.weber@theqtcompany.com>
-rw-r--r--plugins/autotest/testresultspane.cpp94
-rw-r--r--plugins/autotest/testresultspane.h28
2 files changed, 114 insertions, 8 deletions
diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp
index db78e24cd6..8f3d4f5b82 100644
--- a/plugins/autotest/testresultspane.cpp
+++ b/plugins/autotest/testresultspane.cpp
@@ -28,15 +28,19 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
#include <texteditor/texteditor.h>
-#include <utils/itemviews.h>
#include <utils/theme/theme.h>
+#include <QApplication>
+#include <QClipboard>
#include <QDebug>
+#include <QFileDialog>
#include <QHBoxLayout>
#include <QMenu>
+#include <QMessageBox>
#include <QScrollBar>
#include <QToolButton>
#include <QVBoxLayout>
@@ -44,11 +48,24 @@
namespace Autotest {
namespace Internal {
+ResultsTreeView::ResultsTreeView(QWidget *parent)
+ : Utils::TreeView(parent)
+{}
+
+void ResultsTreeView::keyPressEvent(QKeyEvent *event)
+{
+ if (event->matches(QKeySequence::Copy)) {
+ emit copyShortcutTriggered();
+ event->accept();
+ }
+}
+
TestResultsPane::TestResultsPane(QObject *parent) :
Core::IOutputPane(parent),
m_context(new Core::IContext(this)),
m_wasVisibleBefore(false),
- m_autoScroll(false)
+ m_autoScroll(false),
+ m_testRunning(false)
{
m_outputWidget = new QWidget;
QVBoxLayout *outputLayout = new QVBoxLayout;
@@ -74,9 +91,10 @@ TestResultsPane::TestResultsPane(QObject *parent) :
outputLayout->addWidget(m_summaryWidget);
- m_treeView = new Utils::TreeView(m_outputWidget);
+ m_treeView = new ResultsTreeView(m_outputWidget);
m_treeView->setHeaderHidden(true);
m_treeView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
m_model = new TestResultModel(this);
m_filterModel = new TestResultFilterModel(m_model, this);
m_filterModel->setDynamicSortFilter(true);
@@ -91,6 +109,11 @@ TestResultsPane::TestResultsPane(QObject *parent) :
connect(m_treeView, &Utils::TreeView::activated, this, &TestResultsPane::onItemActivated);
connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
trd, &TestResultDelegate::currentChanged);
+ connect(m_treeView, &Utils::TreeView::customContextMenuRequested,
+ this, &TestResultsPane::onCustomContextMenuRequested);
+ connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () {
+ onCopyItemTriggered(m_treeView->currentIndex());
+ });
connect(TestRunner::instance(), &TestRunner::testRunStarted,
this, &TestResultsPane::onTestRunStarted);
connect(TestRunner::instance(), &TestRunner::testRunFinished,
@@ -375,6 +398,7 @@ void TestResultsPane::filterMenuTriggered(QAction *action)
void TestResultsPane::onTestRunStarted()
{
+ m_testRunning = true;
m_stopTestRun->setEnabled(true);
m_runAll->setEnabled(false);
m_runSelected->setEnabled(false);
@@ -383,6 +407,7 @@ void TestResultsPane::onTestRunStarted()
void TestResultsPane::onTestRunFinished()
{
+ m_testRunning = false;
m_stopTestRun->setEnabled(false);
m_runAll->setEnabled(true);
m_runSelected->setEnabled(true);
@@ -406,5 +431,68 @@ void TestResultsPane::onTestTreeModelChanged()
m_runSelected->setEnabled(enable);
}
+void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const bool resultsAvailable = m_filterModel->hasResults();
+ const bool enabled = !m_testRunning && resultsAvailable;
+ const QModelIndex clicked = m_treeView->indexAt(pos);
+ QMenu menu;
+ QAction *action = new QAction(tr("Copy"), &menu);
+ action->setShortcut(QKeySequence(QKeySequence::Copy));
+ action->setEnabled(resultsAvailable);
+ connect(action, &QAction::triggered, [this, clicked] () {
+ onCopyItemTriggered(clicked);
+ });
+ menu.addAction(action);
+
+ action = new QAction(tr("Copy All"), &menu);
+ action->setEnabled(enabled);
+ connect(action, &QAction::triggered, this, &TestResultsPane::onCopyWholeTriggered);
+ menu.addAction(action);
+
+ action = new QAction(tr("Save Output to File..."), &menu);
+ action->setEnabled(enabled);
+ connect(action, &QAction::triggered, this, &TestResultsPane::onSaveWholeTriggered);
+ menu.addAction(action);
+
+ menu.exec(m_treeView->mapToGlobal(pos));
+}
+
+void TestResultsPane::onCopyItemTriggered(const QModelIndex &idx)
+{
+ const TestResult result = m_filterModel->testResult(idx);
+ QApplication::clipboard()->setText(TestResultDelegate::outputString(result, true));
+}
+
+void TestResultsPane::onCopyWholeTriggered()
+{
+ QApplication::clipboard()->setText(getWholeOutput());
+}
+
+void TestResultsPane::onSaveWholeTriggered()
+{
+ const QString fileName = QFileDialog::getSaveFileName(Core::ICore::dialogParent(),
+ tr("Save Output To..."));
+ Utils::FileSaver saver(fileName, QIODevice::Text);
+ if (!saver.write(getWholeOutput().toUtf8()) || !saver.finalize()) {
+ QMessageBox::critical(Core::ICore::dialogParent(), tr("Error"),
+ tr("Failed to write \"%1\".\n\n%2").arg(fileName)
+ .arg(saver.errorString()));
+ }
+}
+
+// helper for onCopyWholeTriggered() and onSaveWholeTriggered()
+QString TestResultsPane::getWholeOutput()
+{
+ QString output;
+ const QModelIndex invalid; // practically the invisible root item
+ for (int row = 0, count = m_model->rowCount(invalid); row < count; ++row) {
+ const TestResult result = m_model->testResult(m_model->index(row, 0, invalid));
+ output.append(TestResult::resultToString(result.result())).append(QLatin1Char('\t'));
+ output.append(TestResultDelegate::outputString(result, true)).append(QLatin1Char('\n'));
+ }
+ return output;
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h
index 37a35eece8..1bb3cddedd 100644
--- a/plugins/autotest/testresultspane.h
+++ b/plugins/autotest/testresultspane.h
@@ -22,9 +22,12 @@
#include <coreplugin/ioutputpane.h>
+#include <utils/itemviews.h>
+
QT_BEGIN_NAMESPACE
class QAction;
class QFrame;
+class QKeyEvent;
class QLabel;
class QModelIndex;
class QMenu;
@@ -35,10 +38,6 @@ namespace Core {
class IContext;
}
-namespace Utils {
-class TreeView;
-}
-
namespace Autotest {
namespace Internal {
@@ -46,6 +45,19 @@ class TestResult;
class TestResultModel;
class TestResultFilterModel;
+class ResultsTreeView : public Utils::TreeView
+{
+ Q_OBJECT
+public:
+ ResultsTreeView(QWidget *parent = 0);
+
+signals:
+ void copyShortcutTriggered();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+};
+
class TestResultsPane : public Core::IOutputPane
{
Q_OBJECT
@@ -90,11 +102,16 @@ private:
void onTestRunFinished();
void onScrollBarRangeChanged(int, int max);
void onTestTreeModelChanged();
+ void onCustomContextMenuRequested(const QPoint &pos);
+ void onCopyItemTriggered(const QModelIndex &idx);
+ void onCopyWholeTriggered();
+ void onSaveWholeTriggered();
+ QString getWholeOutput();
QWidget *m_outputWidget;
QFrame *m_summaryWidget;
QLabel *m_summaryLabel;
- Utils::TreeView *m_treeView;
+ ResultsTreeView *m_treeView;
TestResultModel *m_model;
TestResultFilterModel *m_filterModel;
Core::IContext *m_context;
@@ -106,6 +123,7 @@ private:
bool m_wasVisibleBefore;
bool m_autoScroll;
bool m_atEnd;
+ bool m_testRunning;
};
} // namespace Internal