ProjectExplorer: Generalize issues -> output pane linking

This feature was specific to the compile output pane, but we want
to have it in other panes too.

Change-Id: I110b27af7d0aa23acbc5623d1c0405816250df19
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2021-11-25 12:31:14 +01:00
parent 857ca05ac3
commit 08a86169db
11 changed files with 82 additions and 62 deletions

View File

@@ -324,7 +324,7 @@ void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format)
if (d->postPrintAction) if (d->postPrintAction)
d->postPrintAction(p); d->postPrintAction(p);
else else
p->runPostPrintActions(); p->runPostPrintActions(plainTextEdit());
} }
} }
@@ -591,7 +591,7 @@ void OutputFormatter::flush()
for (OutputLineParser * const p : qAsConst(d->lineParsers)) for (OutputLineParser * const p : qAsConst(d->lineParsers))
p->flush(); p->flush();
if (d->nextParser) if (d->nextParser)
d->nextParser->runPostPrintActions(); d->nextParser->runPostPrintActions(plainTextEdit());
} }
bool OutputFormatter::hasFatalErrors() const bool OutputFormatter::hasFatalErrors() const

View File

@@ -91,7 +91,7 @@ public:
virtual bool handleLink(const QString &href) { Q_UNUSED(href); return false; } virtual bool handleLink(const QString &href) { Q_UNUSED(href); return false; }
virtual bool hasFatalErrors() const { return false; } virtual bool hasFatalErrors() const { return false; }
virtual void flush() {} virtual void flush() {}
virtual void runPostPrintActions() {} virtual void runPostPrintActions(QPlainTextEdit *) {}
void setRedirectionDetector(const OutputLineParser *detector); void setRedirectionDetector(const OutputLineParser *detector);
bool needsRedirection() const; bool needsRedirection() const;

View File

@@ -42,6 +42,7 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class CommandButton; class CommandButton;
class IContext; class IContext;
class OutputWindow;
class CORE_EXPORT IOutputPane : public QObject class CORE_EXPORT IOutputPane : public QObject
{ {
@@ -54,6 +55,7 @@ public:
virtual QWidget *outputWidget(QWidget *parent) = 0; virtual QWidget *outputWidget(QWidget *parent) = 0;
virtual QList<QWidget *> toolBarWidgets() const; virtual QList<QWidget *> toolBarWidgets() const;
virtual QString displayName() const = 0; virtual QString displayName() const = 0;
virtual const QList<OutputWindow *> outputWindows() const { return {}; }
virtual int priorityInStatusBar() const = 0; virtual int priorityInStatusBar() const = 0;

View File

@@ -39,7 +39,9 @@
#include <QAction> #include <QAction>
#include <QCursor> #include <QCursor>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QHash>
#include <QMimeData> #include <QMimeData>
#include <QPair>
#include <QPointer> #include <QPointer>
#include <QRegularExpression> #include <QRegularExpression>
#include <QScrollBar> #include <QScrollBar>
@@ -88,6 +90,7 @@ public:
OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default; OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default;
QTimer scrollTimer; QTimer scrollTimer;
QElapsedTimer lastMessage; QElapsedTimer lastMessage;
QHash<unsigned int, QPair<int, int>> taskPositions;
}; };
} // namespace Internal } // namespace Internal
@@ -491,6 +494,42 @@ void OutputWindow::appendMessage(const QString &output, OutputFormat format)
d->queueTimer.start(); d->queueTimer.start();
} }
void OutputWindow::registerPositionOf(unsigned taskId, int linkedOutputLines, int skipLines,
int offset)
{
if (linkedOutputLines <= 0)
return;
const int blocknumber = document()->blockCount() - offset;
const int firstLine = blocknumber - linkedOutputLines - skipLines;
const int lastLine = firstLine + linkedOutputLines - 1;
d->taskPositions.insert(taskId, qMakePair(firstLine, lastLine));
}
bool OutputWindow::knowsPositionOf(unsigned taskId) const
{
return d->taskPositions.contains(taskId);
}
void OutputWindow::showPositionOf(unsigned taskId)
{
QPair<int, int> position = d->taskPositions.value(taskId);
QTextCursor newCursor(document()->findBlockByNumber(position.second));
// Move cursor to end of last line of interest:
newCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::MoveAnchor);
setTextCursor(newCursor);
// Move cursor and select lines:
newCursor.setPosition(document()->findBlockByNumber(position.first).position(),
QTextCursor::KeepAnchor);
setTextCursor(newCursor);
// Center cursor now:
centerCursor();
}
QMimeData *OutputWindow::createMimeDataFromSelection() const QMimeData *OutputWindow::createMimeDataFromSelection() const
{ {
const auto mimeData = new QMimeData; const auto mimeData = new QMimeData;
@@ -522,6 +561,7 @@ void OutputWindow::clear()
{ {
d->formatter.clear(); d->formatter.clear();
d->scrollToBottom = true; d->scrollToBottom = true;
d->taskPositions.clear();
} }
void OutputWindow::flush() void OutputWindow::flush()

View File

@@ -62,6 +62,10 @@ public:
void appendMessage(const QString &out, Utils::OutputFormat format); void appendMessage(const QString &out, Utils::OutputFormat format);
void registerPositionOf(unsigned taskId, int linkedOutputLines, int skipLines, int offset = 0);
bool knowsPositionOf(unsigned taskId) const;
void showPositionOf(unsigned taskId);
void grayOutOldContent(); void grayOutOldContent();
void clear(); void clear();
void flush(); void flush();

View File

@@ -81,17 +81,6 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_outputWindow->setUndoRedoEnabled(false); m_outputWindow->setUndoRedoEnabled(false);
m_outputWindow->setMaxCharCount(Core::Constants::DEFAULT_MAX_CHAR_COUNT); m_outputWindow->setMaxCharCount(Core::Constants::DEFAULT_MAX_CHAR_COUNT);
outputFormatter()->overridePostPrintAction([this](Utils::OutputLineParser *parser) {
if (const auto taskParser = qobject_cast<OutputTaskParser *>(parser)) {
int offset = 0;
Utils::reverseForeach(taskParser->taskInfo(), [this, &offset](const OutputTaskParser::TaskInfo &ti) {
registerPositionOf(ti.task, ti.linkedLines, ti.skippedLines, offset);
offset += ti.linkedLines;
});
}
parser->runPostPrintActions();
});
Utils::ProxyAction *cancelBuildProxyButton = Utils::ProxyAction *cancelBuildProxyButton =
Utils::ProxyAction::proxyActionWithIcon(cancelBuildAction, Utils::ProxyAction::proxyActionWithIcon(cancelBuildAction,
Utils::Icons::STOP_SMALL_TOOLBAR.icon()); Utils::Icons::STOP_SMALL_TOOLBAR.icon());
@@ -198,7 +187,6 @@ void CompileOutputWindow::appendText(const QString &text, BuildStep::OutputForma
void CompileOutputWindow::clearContents() void CompileOutputWindow::clearContents()
{ {
m_outputWindow->clear(); m_outputWindow->clear();
m_taskPositions.clear();
} }
int CompileOutputWindow::priorityInStatusBar() const int CompileOutputWindow::priorityInStatusBar() const
@@ -230,37 +218,7 @@ bool CompileOutputWindow::canNavigate() const
void CompileOutputWindow::registerPositionOf(const Task &task, int linkedOutputLines, int skipLines, void CompileOutputWindow::registerPositionOf(const Task &task, int linkedOutputLines, int skipLines,
int offset) int offset)
{ {
if (linkedOutputLines <= 0) m_outputWindow->registerPositionOf(task.taskId, linkedOutputLines, skipLines, offset);
return;
const int blocknumber = m_outputWindow->document()->blockCount() - offset;
const int firstLine = blocknumber - linkedOutputLines - skipLines;
const int lastLine = firstLine + linkedOutputLines - 1;
m_taskPositions.insert(task.taskId, qMakePair(firstLine, lastLine));
}
bool CompileOutputWindow::knowsPositionOf(const Task &task)
{
return (m_taskPositions.contains(task.taskId));
}
void CompileOutputWindow::showPositionOf(const Task &task)
{
QPair<int, int> position = m_taskPositions.value(task.taskId);
QTextCursor newCursor(m_outputWindow->document()->findBlockByNumber(position.second));
// Move cursor to end of last line of interest:
newCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::MoveAnchor);
m_outputWindow->setTextCursor(newCursor);
// Move cursor and select lines:
newCursor.setPosition(m_outputWindow->document()->findBlockByNumber(position.first).position(),
QTextCursor::KeepAnchor);
m_outputWindow->setTextCursor(newCursor);
// Center cursor now:
m_outputWindow->centerCursor();
} }
void CompileOutputWindow::flush() void CompileOutputWindow::flush()

View File

@@ -30,8 +30,6 @@
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/ioutputpane.h> #include <coreplugin/ioutputpane.h>
#include <QHash>
#include <QPair>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QToolButton; class QToolButton;
@@ -73,8 +71,6 @@ public:
void appendText(const QString &text, BuildStep::OutputFormat format); void appendText(const QString &text, BuildStep::OutputFormat format);
void registerPositionOf(const Task &task, int linkedOutputLines, int skipLines, int offset = 0); void registerPositionOf(const Task &task, int linkedOutputLines, int skipLines, int offset = 0);
bool knowsPositionOf(const Task &task);
void showPositionOf(const Task &task);
void flush(); void flush();
void reset(); void reset();
@@ -86,13 +82,13 @@ public:
private: private:
void updateFilter() override; void updateFilter() override;
const QList<Core::OutputWindow *> outputWindows() const override { return {m_outputWindow}; }
void loadSettings(); void loadSettings();
void storeSettings() const; void storeSettings() const;
void updateFromSettings(); void updateFromSettings();
Core::OutputWindow *m_outputWindow; Core::OutputWindow *m_outputWindow;
QHash<unsigned int, QPair<int, int>> m_taskPositions;
ShowOutputTaskHandler *m_handler; ShowOutputTaskHandler *m_handler;
QToolButton *m_cancelBuildButton; QToolButton *m_cancelBuildButton;
QToolButton * const m_settingsButton; QToolButton * const m_settingsButton;

View File

@@ -28,10 +28,14 @@
#include "task.h" #include "task.h"
#include "taskhub.h" #include "taskhub.h"
#include <coreplugin/outputwindow.h>
#include <texteditor/fontsettings.h> #include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
#include <utils/algorithm.h>
#include <utils/ansiescapecodehandler.h> #include <utils/ansiescapecodehandler.h>
#include <QPlainTextEdit>
/*! /*!
\class ProjectExplorer::OutputTaskParser \class ProjectExplorer::OutputTaskParser
@@ -113,8 +117,16 @@ void OutputTaskParser::setDetailsFormat(Task &task, const LinkSpecs &linkSpecs)
} }
} }
void OutputTaskParser::runPostPrintActions() void OutputTaskParser::runPostPrintActions(QPlainTextEdit *edit)
{ {
int offset = 0;
if (const auto ow = qobject_cast<Core::OutputWindow *>(edit)) {
Utils::reverseForeach(taskInfo(), [this, ow, &offset](const TaskInfo &ti) {
ow->registerPositionOf(ti.task.taskId, ti.linkedLines, ti.skippedLines, offset);
offset += ti.linkedLines;
});
}
for (const TaskInfo &t : qAsConst(d->scheduledTasks)) for (const TaskInfo &t : qAsConst(d->scheduledTasks))
TaskHub::addTask(t.task); TaskHub::addTask(t.task);
d->scheduledTasks.clear(); d->scheduledTasks.clear();

View File

@@ -57,7 +57,7 @@ protected:
void setDetailsFormat(Task &task, const LinkSpecs &linkSpecs = {}); void setDetailsFormat(Task &task, const LinkSpecs &linkSpecs = {});
private: private:
void runPostPrintActions() override; void runPostPrintActions(QPlainTextEdit *edit) override;
class Private; class Private;
Private * const d; Private * const d;

View File

@@ -27,22 +27,25 @@
#include "task.h" #include "task.h"
#include "compileoutputwindow.h" #include <coreplugin/ioutputpane.h>
#include <coreplugin/outputwindow.h>
#include <utils/algorithm.h>
#include <QAction> #include <QAction>
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
ShowOutputTaskHandler::ShowOutputTaskHandler(CompileOutputWindow *window) : ShowOutputTaskHandler::ShowOutputTaskHandler(Core::IOutputPane *window) : m_window(window)
m_window(window)
{ {
Q_ASSERT(m_window); Q_ASSERT(m_window);
} }
bool ShowOutputTaskHandler::canHandle(const Task &task) const bool ShowOutputTaskHandler::canHandle(const Task &task) const
{ {
return m_window->knowsPositionOf(task); return Utils::anyOf(m_window->outputWindows(), [task](const Core::OutputWindow *ow) {
return ow->knowsPositionOf(task.taskId);
});
} }
void ShowOutputTaskHandler::handle(const Task &task) void ShowOutputTaskHandler::handle(const Task &task)
@@ -50,7 +53,12 @@ void ShowOutputTaskHandler::handle(const Task &task)
Q_ASSERT(canHandle(task)); Q_ASSERT(canHandle(task));
// popup first as this does move the visible area! // popup first as this does move the visible area!
m_window->popup(Core::IOutputPane::Flags(Core::IOutputPane::ModeSwitch | Core::IOutputPane::WithFocus)); m_window->popup(Core::IOutputPane::Flags(Core::IOutputPane::ModeSwitch | Core::IOutputPane::WithFocus));
m_window->showPositionOf(task); for (Core::OutputWindow * const ow : m_window->outputWindows()) {
if (ow->knowsPositionOf(task.taskId)) {
ow->showPositionOf(task.taskId);
break;
}
}
} }
QAction *ShowOutputTaskHandler::createAction(QObject *parent) const QAction *ShowOutputTaskHandler::createAction(QObject *parent) const

View File

@@ -27,24 +27,24 @@
#include "itaskhandler.h" #include "itaskhandler.h"
namespace Core { class IOutputPane; }
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
class CompileOutputWindow;
class ShowOutputTaskHandler : public ITaskHandler class ShowOutputTaskHandler : public ITaskHandler
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ShowOutputTaskHandler(CompileOutputWindow *window); explicit ShowOutputTaskHandler(Core::IOutputPane *window);
bool canHandle(const Task &) const override; bool canHandle(const Task &) const override;
void handle(const Task &task) override; void handle(const Task &task) override;
QAction *createAction(QObject *parent) const override; QAction *createAction(QObject *parent) const override;
private: private:
CompileOutputWindow *m_window; Core::IOutputPane * const m_window;
}; };
} // namespace Internal } // namespace Internal