From c0c2df203dd26b6af2be5757501bb3cacd692ef6 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 14 Apr 2020 15:28:44 +0200 Subject: Utils: Split up OutputFormatter class An OutputFormatter takes some string and prints it into a text edit. In addition, it can ask any number of registered OutputLineParsers whether they think any special formatting should be applied to the current line. This mechanism is now properly modeled by our class design, rather than being hidden in a monolithic class where everything had the same type, no matter what its purpose was. Prospective contributors can now simply be pointed to the OutputLineParser class and will see at one glance what they have to do. Change-Id: I9844499f062c94fb038ce73fd6f26576910148c2 Reviewed-by: hjk --- src/libs/utils/outputformatter.cpp | 69 +++++++++++++----------- src/libs/utils/outputformatter.h | 76 ++++++++++++++++----------- src/plugins/coreplugin/outputwindow.cpp | 14 ++--- src/plugins/coreplugin/outputwindow.h | 4 +- src/plugins/projectexplorer/appoutputpane.cpp | 4 +- src/plugins/projectexplorer/runcontrol.cpp | 18 +++---- src/plugins/projectexplorer/runcontrol.h | 10 ++-- src/plugins/python/pythonrunconfiguration.cpp | 10 ++-- src/plugins/qtsupport/qtoutputformatter.cpp | 58 ++++++++++++-------- src/plugins/vcsbase/vcsoutputformatter.cpp | 10 ++-- src/plugins/vcsbase/vcsoutputformatter.h | 9 ++-- src/plugins/vcsbase/vcsoutputwindow.cpp | 30 +++++------ 12 files changed, 173 insertions(+), 139 deletions(-) diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index 452ec5ae06..dbc7e0a677 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -48,14 +48,18 @@ public: AnsiEscapeCodeHandler escapeCodeHandler; QPair incompleteLine; optional formatOverride; - QList formatters; - OutputFormatter *nextFormatter = nullptr; + QList lineParsers; + OutputLineParser *nextParser = nullptr; bool boldFontEnabled = true; bool prependCarriageReturn = false; }; } // namespace Internal +OutputLineParser::~OutputLineParser() +{ +} + OutputFormatter::OutputFormatter() : d(new Internal::OutputFormatterPrivate) { @@ -79,12 +83,10 @@ void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText) initFormats(); } -void OutputFormatter::setFormatters(const QList &formatters) +void OutputFormatter::setLineParsers(const QList &parsers) { - for (OutputFormatter * const f : formatters) - f->setPlainTextEdit(plainTextEdit()); - d->formatters = formatters; - d->nextFormatter = nullptr; + d->lineParsers = parsers; + d->nextParser = nullptr; } void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format) @@ -93,7 +95,7 @@ void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format) const QList formattedText = parseAnsi(text, charFmt); const QString cleanLine = std::accumulate(formattedText.begin(), formattedText.end(), QString(), [](const FormattedText &t1, const FormattedText &t2) { return t1.text + t2.text; }); - const Result res = handleMessage(cleanLine, format); + const OutputLineParser::Result res = handleMessage(cleanLine, format); if (res.newContent) { append(res.newContent.value(), charFmt); return; @@ -102,36 +104,42 @@ void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format) append(output.text, output.format); } -OutputFormatter::Result OutputFormatter::handleMessage(const QString &text, OutputFormat format) +OutputLineParser::Result OutputFormatter::handleMessage(const QString &text, OutputFormat format) { - if (d->nextFormatter) { - const Result res = d->nextFormatter->handleMessage(text, format); + if (d->nextParser) { + const OutputLineParser::Result res = d->nextParser->handleLine(text, format); switch (res.status) { - case Status::Done: - d->nextFormatter = nullptr; + case OutputLineParser::Status::Done: + d->nextParser = nullptr; return res; - case Status::InProgress: + case OutputLineParser::Status::InProgress: return res; - case Status::NotHandled: + case OutputLineParser::Status::NotHandled: QTC_CHECK(false); // TODO: This case will be legal after the merge - d->nextFormatter = nullptr; + d->nextParser = nullptr; return res; } } - QTC_CHECK(!d->nextFormatter); - for (OutputFormatter * const formatter : qAsConst(d->formatters)) { - const Result res = formatter->handleMessage(text, format); + QTC_CHECK(!d->nextParser); + for (OutputLineParser * const parser : qAsConst(d->lineParsers)) { + const OutputLineParser::Result res = parser->handleLine(text, format); switch (res.status) { - case Status::Done: + case OutputLineParser::Status::Done: return res; - case Status::InProgress: - d->nextFormatter = formatter; + case OutputLineParser::Status::InProgress: + d->nextParser = parser; return res; - case Status::NotHandled: + case OutputLineParser::Status::NotHandled: break; } } - return Status::NotHandled; + return OutputLineParser::Status::NotHandled; +} + +void OutputFormatter::reset() +{ + for (OutputLineParser * const p : d->lineParsers) + p->reset(); } QTextCharFormat OutputFormatter::charFormat(OutputFormat format) const @@ -145,7 +153,7 @@ QList OutputFormatter::parseAnsi(const QString &text, const QText } const QList OutputFormatter::linkifiedText( - const QList &text, const OutputFormatter::LinkSpecs &linkSpecs) + const QList &text, const OutputLineParser::LinkSpecs &linkSpecs) { if (linkSpecs.isEmpty()) return text; @@ -171,7 +179,7 @@ const QList OutputFormatter::linkifiedText( break; } - const LinkSpec &linkSpec = linkSpecs.at(nextLinkSpecIndex); + const OutputLineParser::LinkSpec &linkSpec = linkSpecs.at(nextLinkSpecIndex); const int localLinkStartPos = linkSpec.startPos - totalTextLengthSoFar; ++nextLinkSpecIndex; @@ -221,10 +229,12 @@ QTextCharFormat OutputFormatter::linkFormat(const QTextCharFormat &inputFormat, return result; } +#ifdef WITH_TESTS void OutputFormatter::overrideTextCharFormat(const QTextCharFormat &fmt) { d->formatOverride = fmt; } +#endif // WITH_TESTS void OutputFormatter::clearLastLine() { @@ -266,13 +276,12 @@ void OutputFormatter::dumpIncompleteLine(const QString &line, OutputFormat forma d->incompleteLine.second = format; } -bool OutputFormatter::handleLink(const QString &href) +void OutputFormatter::handleLink(const QString &href) { - for (OutputFormatter * const f : qAsConst(d->formatters)) { + for (OutputLineParser * const f : qAsConst(d->lineParsers)) { if (f->handleLink(href)) - return true; + return; } - return false; } void OutputFormatter::clear() diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h index d38d573d79..cdb757786e 100644 --- a/src/libs/utils/outputformatter.h +++ b/src/libs/utils/outputformatter.h @@ -41,33 +41,10 @@ namespace Utils { class FormattedText; -namespace Internal { class OutputFormatterPrivate; } - -class QTCREATOR_UTILS_EXPORT OutputFormatter : public QObject +class QTCREATOR_UTILS_EXPORT OutputLineParser { public: - OutputFormatter(); - ~OutputFormatter() override; - - QPlainTextEdit *plainTextEdit() const; - void setPlainTextEdit(QPlainTextEdit *plainText); - - void setFormatters(const QList &formatters); - - void flush(); - - void appendMessage(const QString &text, OutputFormat format); - - virtual bool handleLink(const QString &href); - void clear(); - void setBoldFontEnabled(bool enabled); - - // For unit testing only - void overrideTextCharFormat(const QTextCharFormat &fmt); - -protected: - QTextCharFormat charFormat(OutputFormat format) const; - static QTextCharFormat linkFormat(const QTextCharFormat &inputFormat, const QString &href); + virtual ~OutputLineParser(); enum class Status { Done, InProgress, NotHandled }; class LinkSpec { @@ -88,13 +65,51 @@ protected: optional newContent; // Hard content override. Only to be used in extreme cases. }; + // line contains at most one line feed character, and if it does occur, it's the last character. + // Either way, the input is to be considered "complete" for parsing purposes. + virtual Result handleLine(const QString &line, OutputFormat format) = 0; + + virtual bool handleLink(const QString &href) { Q_UNUSED(href); return false; } + virtual void reset() {} +}; + + + +namespace Internal { class OutputFormatterPrivate; } + +class QTCREATOR_UTILS_EXPORT OutputFormatter : public QObject +{ +public: + OutputFormatter(); + ~OutputFormatter() override; + + QPlainTextEdit *plainTextEdit() const; + void setPlainTextEdit(QPlainTextEdit *plainText); + + void setLineParsers(const QList &parsers); + + void appendMessage(const QString &text, OutputFormat format); + void flush(); + + void handleLink(const QString &href); + void clear(); + void setBoldFontEnabled(bool enabled); + +#ifdef WITH_TESTS + void overrideTextCharFormat(const QTextCharFormat &fmt); +#endif + +#ifndef WITH_TESTS +private: +#endif + QTextCharFormat charFormat(OutputFormat format) const; + static QTextCharFormat linkFormat(const QTextCharFormat &inputFormat, const QString &href); + private: - // text contains at most one line feed character, and if it does occur, it's the last character. - // Either way, the input is to be considered "complete" for formatting purposes. void doAppendMessage(const QString &text, OutputFormat format); - virtual Result handleMessage(const QString &text, OutputFormat format); - virtual void reset() {} + OutputLineParser::Result handleMessage(const QString &text, OutputFormat format); + void reset(); void append(const QString &text, const QTextCharFormat &format); void initFormats(); @@ -103,9 +118,10 @@ private: void clearLastLine(); QList parseAnsi(const QString &text, const QTextCharFormat &format); const QList linkifiedText(const QList &text, - const LinkSpecs &linkSpecs); + const OutputLineParser::LinkSpecs &linkSpecs); Internal::OutputFormatterPrivate *d; }; + } // namespace Utils diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 2cf6643c71..089a37ea93 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -216,9 +216,9 @@ void OutputWindow::keyPressEvent(QKeyEvent *ev) verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum); } -void OutputWindow::setFormatters(const QList &formatters) +void OutputWindow::setLineParsers(const QList &parsers) { - d->formatter.setFormatters(formatters); + d->formatter.setLineParsers(parsers); } void OutputWindow::showEvent(QShowEvent *e) @@ -503,10 +503,10 @@ void OutputWindow::setWordWrapEnabled(bool wrap) // Handles all lines starting with "A" and the following ones up to and including the next // one starting with "A". -class TestFormatterA : public OutputFormatter +class TestFormatterA : public OutputLineParser { private: - Result handleMessage(const QString &text, OutputFormat) override + Result handleLine(const QString &text, OutputFormat) override { static const QString replacement = "handled by A\n"; if (m_handling) { @@ -529,10 +529,10 @@ private: }; // Handles all lines starting with "B". No continuation logic -class TestFormatterB : public OutputFormatter +class TestFormatterB : public OutputLineParser { private: - Result handleMessage(const QString &text, OutputFormat) override + Result handleLine(const QString &text, OutputFormat) override { if (text.startsWith("B")) return {Status::Done, {}, QString("handled by B\n")}; @@ -571,7 +571,7 @@ void Internal::CorePlugin::testOutputFormatter() OutputFormatter formatter; QPlainTextEdit textEdit; formatter.setPlainTextEdit(&textEdit); - formatter.setFormatters({&formatterB, &formatterA}); + formatter.setLineParsers({&formatterB, &formatterA}); // Stress-test the implementation by providing the input in chunks, splitting at all possible // offsets. diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h index 77703f0b9a..4e94d66af5 100644 --- a/src/plugins/coreplugin/outputwindow.h +++ b/src/plugins/coreplugin/outputwindow.h @@ -34,7 +34,7 @@ #include #include -namespace Utils { class OutputFormatter; } +namespace Utils { class OutputLineParser; } namespace Core { @@ -56,7 +56,7 @@ public: OutputWindow(Context context, const QString &settingsKey, QWidget *parent = nullptr); ~OutputWindow() override; - void setFormatters(const QList &formatters); + void setLineParsers(const QList &parsers); void appendMessage(const QString &out, Utils::OutputFormat format); diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index cb24b7c1c2..d16f6fb702 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -154,7 +154,7 @@ AppOutputPane::RunControlTab::RunControlTab(RunControl *runControl, Core::Output runControl(runControl), window(w) { if (runControl && w) - w->setFormatters(runControl->outputFormatters()); + w->setLineParsers(runControl->outputParsers()); } AppOutputPane::AppOutputPane() : @@ -404,7 +404,7 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc) if (tab.runControl) tab.runControl->initiateFinish(); tab.runControl = rc; - tab.window->setFormatters(rc->outputFormatters()); + tab.window->setLineParsers(rc->outputParsers()); handleOldOutput(tab.window); diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 18cf5a3099..241dac4021 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -288,7 +288,7 @@ public: q = nullptr; qDeleteAll(m_workers); m_workers.clear(); - qDeleteAll(outputFormatters); + qDeleteAll(outputParsers); } Q_ENUM(RunControlState) @@ -333,7 +333,7 @@ public: Kit *kit = nullptr; // Not owned. QPointer target; // Not owned. QPointer project; // Not owned. - QList outputFormatters; + QList outputParsers; std::function promptToStop; std::vector m_factories; @@ -384,8 +384,8 @@ void RunControl::setTarget(Target *target) d->buildEnvironment = bc->environment(); } - QTC_CHECK(d->outputFormatters.isEmpty()); - d->outputFormatters = OutputFormatterFactory::createFormatters(target); + QTC_CHECK(d->outputParsers.isEmpty()); + d->outputParsers = OutputFormatterFactory::createFormatters(target); setKit(target->kit()); d->project = target->project(); @@ -828,9 +828,9 @@ void RunControlPrivate::showError(const QString &msg) q->appendMessage(msg + '\n', ErrorMessageFormat); } -QList RunControl::outputFormatters() const +QList RunControl::outputParsers() const { - return d->outputFormatters; + return d->outputParsers; } Core::Id RunControl::runMode() const @@ -1606,9 +1606,9 @@ OutputFormatterFactory::~OutputFormatterFactory() g_outputFormatterFactories.removeOne(this); } -QList OutputFormatterFactory::createFormatters(Target *target) +QList OutputFormatterFactory::createFormatters(Target *target) { - QList formatters; + QList formatters; for (auto factory : qAsConst(g_outputFormatterFactories)) { if (auto formatter = factory->m_creator(target)) formatters << formatter; @@ -1617,7 +1617,7 @@ QList OutputFormatterFactory::createFormatters(Target *target } void OutputFormatterFactory::setFormatterCreator - (const std::function &creator) + (const std::function &creator) { m_creator = creator; } diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h index 99c6a7636c..f68f6fee35 100644 --- a/src/plugins/projectexplorer/runcontrol.h +++ b/src/plugins/projectexplorer/runcontrol.h @@ -45,7 +45,7 @@ namespace Utils { class MacroExpander; -class OutputFormatter; +class OutputLineParser; } // Utils namespace ProjectExplorer { @@ -238,7 +238,7 @@ public: Utils::FilePath targetFilePath() const; Utils::FilePath projectFilePath() const; - QList outputFormatters() const; + QList outputParsers() const; Core::Id runMode() const; const Runnable &runnable() const; @@ -309,13 +309,13 @@ protected: public: virtual ~OutputFormatterFactory(); - static QList createFormatters(Target *target); + static QList createFormatters(Target *target); protected: - void setFormatterCreator(const std::function &creator); + void setFormatterCreator(const std::function &creator); private: - std::function m_creator; + std::function m_creator; }; } // namespace ProjectExplorer diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp index 92e02c5206..c2c522bce3 100644 --- a/src/plugins/python/pythonrunconfiguration.cpp +++ b/src/plugins/python/pythonrunconfiguration.cpp @@ -60,10 +60,10 @@ using namespace Utils; namespace Python { namespace Internal { -class PythonOutputFormatter : public OutputFormatter +class PythonOutputLineParser : public OutputLineParser { public: - PythonOutputFormatter() + PythonOutputLineParser() // Note that moc dislikes raw string literals. : filePattern("^(\\s*)(File \"([^\"]+)\", line (\\d+), .*$)") { @@ -71,7 +71,7 @@ public: } private: - Result handleMessage(const QString &text, OutputFormat format) final + Result handleLine(const QString &text, OutputFormat format) final { if (!m_inTraceBack) { m_inTraceBack = format == StdErrFormat @@ -337,9 +337,9 @@ PythonRunConfigurationFactory::PythonRunConfigurationFactory() PythonOutputFormatterFactory::PythonOutputFormatterFactory() { - setFormatterCreator([](Target *t) -> OutputFormatter * { + setFormatterCreator([](Target *t) -> OutputLineParser * { if (t->project()->mimeType() == Constants::C_PY_MIMETYPE) - return new PythonOutputFormatter; + return new PythonOutputLineParser; return nullptr; }); } diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp index 13ceb23d78..f97851da0e 100644 --- a/src/plugins/qtsupport/qtoutputformatter.cpp +++ b/src/plugins/qtsupport/qtoutputformatter.cpp @@ -79,17 +79,17 @@ public: FileInProjectFinder projectFinder; }; -class QtOutputFormatter : public OutputFormatter +class QtOutputLineParser : public QObject, public OutputLineParser { public: - explicit QtOutputFormatter(Target *target); - ~QtOutputFormatter() override; + explicit QtOutputLineParser(Target *target); + ~QtOutputLineParser() override; protected: virtual void openEditor(const QString &fileName, int line, int column = -1); private: - Result handleMessage(const QString &text, Utils::OutputFormat format) override; + Result handleLine(const QString &text, Utils::OutputFormat format) override; bool handleLink(const QString &href) override; void updateProjectFileList(); @@ -99,7 +99,7 @@ private: friend class QtSupportPlugin; // for testing }; -QtOutputFormatter::QtOutputFormatter(Target *target) +QtOutputLineParser::QtOutputLineParser(Target *target) : d(new QtOutputFormatterPrivate) { d->project = target ? target->project() : nullptr; @@ -110,17 +110,17 @@ QtOutputFormatter::QtOutputFormatter(Target *target) connect(d->project, &Project::fileListChanged, this, - &QtOutputFormatter::updateProjectFileList, + &QtOutputLineParser::updateProjectFileList, Qt::QueuedConnection); } } -QtOutputFormatter::~QtOutputFormatter() +QtOutputLineParser::~QtOutputLineParser() { delete d; } -OutputFormatter::LinkSpec QtOutputFormatter::matchLine(const QString &line) const +OutputLineParser::LinkSpec QtOutputLineParser::matchLine(const QString &line) const { LinkSpec lr; @@ -151,7 +151,7 @@ OutputFormatter::LinkSpec QtOutputFormatter::matchLine(const QString &line) cons return lr; } -OutputFormatter::Result QtOutputFormatter::handleMessage(const QString &txt, OutputFormat format) +OutputLineParser::Result QtOutputLineParser::handleLine(const QString &txt, OutputFormat format) { Q_UNUSED(format); const LinkSpec lr = matchLine(txt); @@ -160,7 +160,7 @@ OutputFormatter::Result QtOutputFormatter::handleMessage(const QString &txt, Out return Status::NotHandled; } -bool QtOutputFormatter::handleLink(const QString &href) +bool QtOutputLineParser::handleLink(const QString &href) { if (!href.isEmpty()) { static const QRegularExpression qmlLineColumnLink("^(" QT_QML_URL_REGEXP ")" // url @@ -227,12 +227,12 @@ bool QtOutputFormatter::handleLink(const QString &href) return false; } -void QtOutputFormatter::openEditor(const QString &fileName, int line, int column) +void QtOutputLineParser::openEditor(const QString &fileName, int line, int column) { Core::EditorManager::openEditorAt(fileName, line, column); } -void QtOutputFormatter::updateProjectFileList() +void QtOutputLineParser::updateProjectFileList() { if (d->project) d->projectFinder.setProjectFiles(d->project->files(Project::SourceFiles)); @@ -242,9 +242,9 @@ void QtOutputFormatter::updateProjectFileList() QtOutputFormatterFactory::QtOutputFormatterFactory() { - setFormatterCreator([](Target *t) -> OutputFormatter * { + setFormatterCreator([](Target *t) -> OutputLineParser * { BaseQtVersion *qt = QtKitAspect::qtVersion(t->kit()); - return qt ? new QtOutputFormatter(t) : nullptr; + return qt ? new QtOutputLineParser(t) : nullptr; }); } @@ -265,11 +265,11 @@ namespace QtSupport { using namespace QtSupport::Internal; -class TestQtOutputFormatter : public QtOutputFormatter +class TestQtOutputLineParser : public QtOutputLineParser { public: - TestQtOutputFormatter() : - QtOutputFormatter(nullptr) + TestQtOutputLineParser() : + QtOutputLineParser(nullptr) { } @@ -286,6 +286,20 @@ public: int column = -1; }; +class TestQtOutputFormatter : public OutputFormatter +{ +public: + TestQtOutputFormatter() : m_parser(new TestQtOutputLineParser) + { + setLineParsers({m_parser}); + } + + ~TestQtOutputFormatter() { delete m_parser; } + +private: + OutputLineParser * const m_parser; +}; + void QtSupportPlugin::testQtOutputFormatter_data() { @@ -409,9 +423,9 @@ void QtSupportPlugin::testQtOutputFormatter() QFETCH(int, line); QFETCH(int, column); - TestQtOutputFormatter formatter; + TestQtOutputLineParser formatter; - QtOutputFormatter::LinkSpec result = formatter.matchLine(input); + QtOutputLineParser::LinkSpec result = formatter.matchLine(input); formatter.handleLink(result.target); QCOMPARE(result.startPos, linkStart); @@ -453,7 +467,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage_data() << "Object::Test in test.cpp:123" << "Object::Test in test.cpp:123" << QTextCharFormat() - << QtOutputFormatter::linkFormat(QTextCharFormat(), "test.cpp:123"); + << OutputFormatter::linkFormat(QTextCharFormat(), "test.cpp:123"); QTest::newRow("colored") << "blue da ba dee" << "blue da ba dee" @@ -491,6 +505,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage() void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi() { QPlainTextEdit edit; + TestQtOutputFormatter formatter; formatter.setPlainTextEdit(&edit); @@ -512,7 +527,8 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi() edit.moveCursor(QTextCursor::WordRight); edit.moveCursor(QTextCursor::Right); - QCOMPARE(edit.currentCharFormat(), QtOutputFormatter::linkFormat(QTextCharFormat(), "file://test.cpp:123")); + QCOMPARE(edit.currentCharFormat(), + OutputFormatter::linkFormat(QTextCharFormat(), "file://test.cpp:123")); edit.moveCursor(QTextCursor::End); QCOMPARE(edit.currentCharFormat(), blueFormat()); diff --git a/src/plugins/vcsbase/vcsoutputformatter.cpp b/src/plugins/vcsbase/vcsoutputformatter.cpp index be6a065f6b..9fd116dda0 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.cpp +++ b/src/plugins/vcsbase/vcsoutputformatter.cpp @@ -34,7 +34,7 @@ namespace VcsBase { -VcsOutputFormatter::VcsOutputFormatter() : +VcsOutputLineParser::VcsOutputLineParser() : m_regexp( "(https?://\\S*)" // https://codereview.org/c/1234 "|(v[0-9]+\\.[0-9]+\\.[0-9]+[\\-A-Za-z0-9]*)" // v0.1.2-beta3 @@ -43,8 +43,8 @@ VcsOutputFormatter::VcsOutputFormatter() : { } -Utils::OutputFormatter::Result VcsOutputFormatter::handleMessage(const QString &text, - Utils::OutputFormat format) +Utils::OutputLineParser::Result VcsOutputLineParser::handleLine(const QString &text, + Utils::OutputFormat format) { Q_UNUSED(format); QRegularExpressionMatchIterator it = m_regexp.globalMatch(text); @@ -62,7 +62,7 @@ Utils::OutputFormatter::Result VcsOutputFormatter::handleMessage(const QString & return {Status::Done, linkSpecs}; } -bool VcsOutputFormatter::handleLink(const QString &href) +bool VcsOutputLineParser::handleLink(const QString &href) { if (href.startsWith("http://") || href.startsWith("https://")) QDesktopServices::openUrl(QUrl(href)); @@ -71,7 +71,7 @@ bool VcsOutputFormatter::handleLink(const QString &href) return true; } -void VcsOutputFormatter::fillLinkContextMenu( +void VcsOutputLineParser::fillLinkContextMenu( QMenu *menu, const QString &workingDirectory, const QString &href) { if (href.isEmpty() || href.startsWith("http://") || href.startsWith("https://")) { diff --git a/src/plugins/vcsbase/vcsoutputformatter.h b/src/plugins/vcsbase/vcsoutputformatter.h index 32cc9de068..e4ebfc6fee 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.h +++ b/src/plugins/vcsbase/vcsoutputformatter.h @@ -31,20 +31,19 @@ QT_FORWARD_DECLARE_CLASS(QMenu) namespace VcsBase { -class VcsOutputFormatter : public Utils::OutputFormatter +class VcsOutputLineParser : public QObject, public Utils::OutputLineParser { Q_OBJECT public: - VcsOutputFormatter(); - ~VcsOutputFormatter() override = default; - bool handleLink(const QString &href) override; + VcsOutputLineParser(); void fillLinkContextMenu(QMenu *menu, const QString &workingDirectory, const QString &href); signals: void referenceClicked(const QString &reference); private: - Result handleMessage(const QString &text, Utils::OutputFormat format) override; + Result handleLine(const QString &text, Utils::OutputFormat format) override; + bool handleLink(const QString &href) override; const QRegularExpression m_regexp; }; diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index f1ca4da868..d2b96e7948 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -97,12 +97,11 @@ class OutputWindowPlainTextEdit : public Core::OutputWindow { public: explicit OutputWindowPlainTextEdit(QWidget *parent = nullptr); - ~OutputWindowPlainTextEdit() override; void appendLines(const QString &s, const QString &repository = QString()); void appendLinesWithStyle(const QString &s, VcsOutputWindow::MessageStyle style, const QString &repository = QString()); - VcsOutputFormatter *formatter(); + VcsOutputLineParser *parser(); protected: void contextMenuEvent(QContextMenuEvent *event) override; @@ -112,7 +111,8 @@ private: QString identifierUnderCursor(const QPoint &pos, QString *repository = nullptr) const; Utils::OutputFormat m_format; - VcsOutputFormatter *m_formatter = nullptr; + Utils::OutputFormatter m_formatter; + VcsOutputLineParser m_parser; }; OutputWindowPlainTextEdit::OutputWindowPlainTextEdit(QWidget *parent) : @@ -121,19 +121,13 @@ OutputWindowPlainTextEdit::OutputWindowPlainTextEdit(QWidget *parent) : setReadOnly(true); setUndoRedoEnabled(false); setFrameStyle(QFrame::NoFrame); - m_formatter = new VcsOutputFormatter; - m_formatter->setBoldFontEnabled(false); - setFormatters({m_formatter}); + m_formatter.setBoldFontEnabled(false); + setLineParsers({&m_parser}); auto agg = new Aggregation::Aggregate; agg->add(this); agg->add(new Core::BaseTextFind(this)); } -OutputWindowPlainTextEdit::~OutputWindowPlainTextEdit() -{ - delete m_formatter; -} - // Search back for beginning of word static inline int firstWordCharacter(const QString &s, int startPos) { @@ -181,9 +175,9 @@ void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event) QString repository; const QString token = identifierUnderCursor(event->pos(), &repository); if (!repository.isEmpty()) { - if (VcsOutputFormatter *f = formatter()) { + if (VcsOutputLineParser * const p = parser()) { if (!href.isEmpty()) - f->fillLinkContextMenu(menu, repository, href); + p->fillLinkContextMenu(menu, repository, href); } } QAction *openAction = nullptr; @@ -228,7 +222,7 @@ void OutputWindowPlainTextEdit::appendLines(const QString &s, const QString &rep const int previousLineCount = document()->lineCount(); - m_formatter->appendMessage(s, m_format); + m_formatter.appendMessage(s, m_format); // Scroll down moveCursor(QTextCursor::End); @@ -255,14 +249,14 @@ void OutputWindowPlainTextEdit::appendLinesWithStyle(const QString &s, } } -VcsOutputFormatter *OutputWindowPlainTextEdit::formatter() +VcsOutputLineParser *OutputWindowPlainTextEdit::parser() { - return m_formatter; + return &m_parser; } void OutputWindowPlainTextEdit::setFormat(VcsOutputWindow::MessageStyle style) { - m_formatter->setBoldFontEnabled(style == VcsOutputWindow::Command); + m_formatter.setBoldFontEnabled(style == VcsOutputWindow::Command); switch (style) { case VcsOutputWindow::Warning: @@ -318,7 +312,7 @@ VcsOutputWindow::VcsOutputWindow() connect(this, &IOutputPane::resetZoom, &d->widget, &Core::OutputWindow::resetZoom); connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged, this, updateBehaviorSettings); - connect(d->widget.formatter(), &VcsOutputFormatter::referenceClicked, + connect(d->widget.parser(), &VcsOutputLineParser::referenceClicked, VcsOutputWindow::instance(), &VcsOutputWindow::referenceClicked); } -- cgit v1.2.3