Core: Change filterNewContent() to use a predicate

At this point this might appear slightly over-designed, but when adding
context matching and highlighting of matches the body of the lastBlock
loop will become much more complex. Something you surly don't want to
copy and paste. On the other hand the following changes are way too
complex to mix them with this refactoring. That's what this change
prepares for, and that's why it is separate.

Task-number: QTCREATORBUG-30167
Change-Id: Idb0ed2471006ebaa199acb164043f8fea8fc0d42
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Mathias Hasselmann
2024-01-13 00:10:25 +01:00
committed by hjk
parent 3f636a710f
commit 5374705531
2 changed files with 30 additions and 13 deletions

View File

@@ -379,30 +379,44 @@ void OutputWindow::setOutputFileNameHint(const QString &fileName)
d->outputFileNameHint = fileName; d->outputFileNameHint = fileName;
} }
void OutputWindow::filterNewContent() OutputWindow::TextMatchingFunction OutputWindow::makeMatchingFunction() const
{ {
QTextBlock lastBlock = document()->findBlockByNumber(d->lastFilteredBlockNumber); if (d->filterText.isEmpty()) {
if (!lastBlock.isValid()) return [](const QString &) { return true; };
lastBlock = document()->begin(); } else if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::RegExp)) {
const bool invert = d->filterMode.testFlag(FilterModeFlag::Inverted);
if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::RegExp)) {
QRegularExpression regExp(d->filterText); QRegularExpression regExp(d->filterText);
if (!d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)) if (!d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive))
regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption); regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
if (!regExp.isValid())
return [](const QString &) { return false; };
for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) return [regExp](const QString &text) { return regExp.match(text).hasMatch(); };
lastBlock.setVisible(d->filterText.isEmpty()
|| regExp.match(lastBlock.text()).hasMatch() != invert);
} else { } else {
const auto cs = d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive) const auto cs = d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)
? Qt::CaseSensitive : Qt::CaseInsensitive; ? Qt::CaseSensitive : Qt::CaseInsensitive;
for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) return [cs, filterText = d->filterText](const QString &text) {
lastBlock.setVisible(d->filterText.isEmpty() return text.contains(filterText, cs);
|| lastBlock.text().contains(d->filterText, cs) != invert); };
} }
return {};
}
void OutputWindow::filterNewContent()
{
const auto findNextMatch = makeMatchingFunction();
QTC_ASSERT(findNextMatch, return);
const bool invert = d->filterMode.testFlag(FilterModeFlag::Inverted)
&& !d->filterText.isEmpty();
QTextBlock lastBlock = document()->findBlockByNumber(d->lastFilteredBlockNumber);
if (!lastBlock.isValid())
lastBlock = document()->begin();
for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
lastBlock.setVisible(findNextMatch(lastBlock.text()) != invert);
d->lastFilteredBlockNumber = document()->lastBlock().blockNumber(); d->lastFilteredBlockNumber = document()->lastBlock().blockNumber();
// FIXME: Why on earth is this necessary? We should probably do something else instead... // FIXME: Why on earth is this necessary? We should probably do something else instead...

View File

@@ -97,6 +97,9 @@ private:
void handleOutputChunk(const QString &output, Utils::OutputFormat format); void handleOutputChunk(const QString &output, Utils::OutputFormat format);
void updateAutoScroll(); void updateAutoScroll();
using TextMatchingFunction = std::function<qsizetype(const QString &text)>;
TextMatchingFunction makeMatchingFunction() const;
Internal::OutputWindowPrivate *d = nullptr; Internal::OutputWindowPrivate *d = nullptr;
}; };