Output panes: Allow to invert the meaning of the filter field

That is, show only the non-matching lines.

Task-number: QTCREATORBUG-19596
Change-Id: Iac06a7c4531688dbf97c7d5c4d0cdb80979b5f95
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Christian Kandeler
2019-11-18 13:56:59 +01:00
parent 9298bf8ff8
commit aacfd340ca
10 changed files with 61 additions and 21 deletions

View File

@@ -102,6 +102,7 @@ protected:
void setupFilterUi(const QString &historyKey); void setupFilterUi(const QString &historyKey);
QString filterText() const; QString filterText() const;
bool filterUsesRegexp() const { return m_filterRegexp; } bool filterUsesRegexp() const { return m_filterRegexp; }
bool filterIsInverted() const { return m_invertFilter; }
Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; } Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; }
void setFilteringEnabled(bool enable); void setFilteringEnabled(bool enable);
QWidget *filterWidget() const { return m_filterOutputLineEdit; } QWidget *filterWidget() const { return m_filterOutputLineEdit; }
@@ -116,14 +117,17 @@ private:
void setRegularExpressions(bool regularExpressions); void setRegularExpressions(bool regularExpressions);
Id filterRegexpActionId() const; Id filterRegexpActionId() const;
Id filterCaseSensitivityActionId() const; Id filterCaseSensitivityActionId() const;
Id filterInvertedActionId() const;
Core::CommandButton * const m_zoomInButton; Core::CommandButton * const m_zoomInButton;
Core::CommandButton * const m_zoomOutButton; Core::CommandButton * const m_zoomOutButton;
QAction *m_filterActionRegexp = nullptr; QAction *m_filterActionRegexp = nullptr;
QAction *m_filterActionCaseSensitive = nullptr; QAction *m_filterActionCaseSensitive = nullptr;
QAction *m_invertFilterAction = nullptr;
Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr; Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr;
IContext *m_context = nullptr; IContext *m_context = nullptr;
bool m_filterRegexp = false; bool m_filterRegexp = false;
bool m_invertFilter = false;
Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
}; };

View File

@@ -146,7 +146,8 @@ bool MessageOutputWindow::canNavigate() const
void MessageOutputWindow::updateFilter() void MessageOutputWindow::updateFilter()
{ {
m_widget->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); m_widget->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp(),
filterIsInverted());
} }
} // namespace Internal } // namespace Internal

View File

@@ -155,6 +155,15 @@ void IOutputPane::setupFilterUi(const QString &historyKey)
Core::ActionManager::registerAction(m_filterActionCaseSensitive, Core::ActionManager::registerAction(m_filterActionCaseSensitive,
filterCaseSensitivityActionId()); filterCaseSensitivityActionId());
m_invertFilterAction = new QAction(this);
m_invertFilterAction->setCheckable(true);
m_invertFilterAction->setText(tr("Show Non-matching Lines"));
connect(m_invertFilterAction, &QAction::toggled, this, [this] {
m_invertFilter = m_invertFilterAction->isChecked();
updateFilter();
});
Core::ActionManager::registerAction(m_invertFilterAction, filterInvertedActionId());
m_filterOutputLineEdit->setPlaceholderText(tr("Filter output...")); m_filterOutputLineEdit->setPlaceholderText(tr("Filter output..."));
m_filterOutputLineEdit->setButtonVisible(FancyLineEdit::Left, true); m_filterOutputLineEdit->setButtonVisible(FancyLineEdit::Left, true);
m_filterOutputLineEdit->setButtonIcon(FancyLineEdit::Left, Icons::MAGNIFIER.icon()); m_filterOutputLineEdit->setButtonIcon(FancyLineEdit::Left, Icons::MAGNIFIER.icon());
@@ -213,7 +222,7 @@ void IOutputPane::updateFilter()
void IOutputPane::filterOutputButtonClicked() void IOutputPane::filterOutputButtonClicked()
{ {
auto popup = new Core::OptionsPopup(m_filterOutputLineEdit, auto popup = new Core::OptionsPopup(m_filterOutputLineEdit,
{filterRegexpActionId(), filterCaseSensitivityActionId()}); {filterRegexpActionId(), filterCaseSensitivityActionId(), filterInvertedActionId()});
popup->show(); popup->show();
} }
@@ -233,6 +242,11 @@ Id IOutputPane::filterCaseSensitivityActionId() const
return Id("OutputFilter.CaseSensitive").withSuffix(metaObject()->className()); return Id("OutputFilter.CaseSensitive").withSuffix(metaObject()->className());
} }
Id IOutputPane::filterInvertedActionId() const
{
return Id("OutputFilter.Invert").withSuffix(metaObject()->className());
}
void IOutputPane::setCaseSensitive(bool caseSensitive) void IOutputPane::setCaseSensitive(bool caseSensitive)
{ {
m_filterCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; m_filterCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;

View File

@@ -280,12 +280,17 @@ void OutputWindow::setWheelZoomEnabled(bool enabled)
d->zoomEnabled = enabled; d->zoomEnabled = enabled;
} }
void OutputWindow::updateFilterProperties(const QString &filterText, void OutputWindow::updateFilterProperties(
Qt::CaseSensitivity caseSensitivity, bool isRegexp) const QString &filterText,
Qt::CaseSensitivity caseSensitivity,
bool isRegexp,
bool isInverted
)
{ {
FilterModeFlags flags; FilterModeFlags flags;
flags.setFlag(FilterModeFlag::CaseSensitive, caseSensitivity == Qt::CaseSensitive) flags.setFlag(FilterModeFlag::CaseSensitive, caseSensitivity == Qt::CaseSensitive)
.setFlag(FilterModeFlag::RegExp, isRegexp); .setFlag(FilterModeFlag::RegExp, isRegexp)
.setFlag(FilterModeFlag::Inverted, isInverted);
if (d->filterMode == flags && d->filterText == filterText) if (d->filterMode == flags && d->filterText == filterText)
return; return;
d->lastFilteredBlockNumber = -1; d->lastFilteredBlockNumber = -1;
@@ -324,6 +329,7 @@ void OutputWindow::filterNewContent()
if (!lastBlock.isValid()) if (!lastBlock.isValid())
lastBlock = document()->begin(); lastBlock = document()->begin();
const bool invert = d->filterMode.testFlag(FilterModeFlag::Inverted);
if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::RegExp)) { 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))
@@ -331,16 +337,17 @@ void OutputWindow::filterNewContent()
for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
lastBlock.setVisible(d->filterText.isEmpty() lastBlock.setVisible(d->filterText.isEmpty()
|| regExp.match(lastBlock.text()).hasMatch()); || regExp.match(lastBlock.text()).hasMatch() != invert);
} else { } else {
if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)) { if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)) {
for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
lastBlock.setVisible(d->filterText.isEmpty() lastBlock.setVisible(d->filterText.isEmpty()
|| lastBlock.text().contains(d->filterText)); || lastBlock.text().contains(d->filterText) != invert);
} else { } else {
for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) for (; lastBlock != document()->end(); lastBlock = lastBlock.next()) {
lastBlock.setVisible(d->filterText.isEmpty() lastBlock.setVisible(d->filterText.isEmpty() || lastBlock.text().toLower()
|| lastBlock.text().toLower().contains(d->filterText.toLower())); .contains(d->filterText.toLower()) != invert);
}
} }
} }

View File

@@ -49,6 +49,7 @@ public:
Default = 0x00, // Plain text, non case sensitive, for initialization Default = 0x00, // Plain text, non case sensitive, for initialization
RegExp = 0x01, RegExp = 0x01,
CaseSensitive = 0x02, CaseSensitive = 0x02,
Inverted = 0x04,
}; };
Q_DECLARE_FLAGS(FilterModeFlags, FilterModeFlag) Q_DECLARE_FLAGS(FilterModeFlags, FilterModeFlag)
@@ -78,7 +79,11 @@ public:
void resetZoom() { setFontZoom(0); } void resetZoom() { setFontZoom(0); }
void setWheelZoomEnabled(bool enabled); void setWheelZoomEnabled(bool enabled);
void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp); void updateFilterProperties(
const QString &filterText,
Qt::CaseSensitivity caseSensitivity,
bool regexp,
bool isInverted);
signals: signals:
void wheelZoom(); void wheelZoom();

View File

@@ -378,7 +378,7 @@ void AppOutputPane::updateFilter()
const int index = currentIndex(); const int index = currentIndex();
if (index != -1) { if (index != -1) {
m_runControlTabs.at(index).window->updateFilterProperties( m_runControlTabs.at(index).window->updateFilterProperties(
filterText(), filterCaseSensitivity(), filterUsesRegexp()); filterText(), filterCaseSensitivity(), filterUsesRegexp(), filterIsInverted());
} }
} }
@@ -724,7 +724,7 @@ void AppOutputPane::tabChanged(int i)
if (i != -1 && index != -1) { if (i != -1 && index != -1) {
const RunControlTab &controlTab = m_runControlTabs[index]; const RunControlTab &controlTab = m_runControlTabs[index];
controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(), controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(),
filterUsesRegexp()); filterUsesRegexp(), filterIsInverted());
enableButtons(controlTab.runControl); enableButtons(controlTab.runControl);
} else { } else {
enableDefaultButtons(); enableDefaultButtons();

View File

@@ -354,7 +354,7 @@ void CompileOutputWindow::setSettings(const CompileOutputSettings &settings)
void CompileOutputWindow::updateFilter() void CompileOutputWindow::updateFilter()
{ {
m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(), m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(),
filterUsesRegexp()); filterUsesRegexp(), filterIsInverted());
} }
void CompileOutputWindow::loadSettings() void CompileOutputWindow::loadSettings()

View File

@@ -351,16 +351,20 @@ int TaskFilterModel::issuesCount(int startRow, int endRow) const
return count; return count;
} }
void TaskFilterModel::updateFilterProperties(const QString &filterText, void TaskFilterModel::updateFilterProperties(
Qt::CaseSensitivity caseSensitivity, bool isRegexp) const QString &filterText,
Qt::CaseSensitivity caseSensitivity,
bool isRegexp,
bool isInverted)
{ {
if (filterText == m_filterText && m_filterCaseSensitivity == caseSensitivity if (filterText == m_filterText && m_filterCaseSensitivity == caseSensitivity
&& m_filterStringIsRegexp == isRegexp) { && m_filterStringIsRegexp == isRegexp && m_filterIsInverted == isInverted) {
return; return;
} }
m_filterText = filterText; m_filterText = filterText;
m_filterCaseSensitivity = caseSensitivity; m_filterCaseSensitivity = caseSensitivity;
m_filterStringIsRegexp = isRegexp; m_filterStringIsRegexp = isRegexp;
m_filterIsInverted = isInverted;
if (m_filterStringIsRegexp) { if (m_filterStringIsRegexp) {
m_filterRegexp.setPattern(m_filterText); m_filterRegexp.setPattern(m_filterText);
m_filterRegexp.setPatternOptions(m_filterCaseSensitivity == Qt::CaseInsensitive m_filterRegexp.setPatternOptions(m_filterCaseSensitivity == Qt::CaseInsensitive
@@ -399,7 +403,7 @@ bool TaskFilterModel::filterAcceptsTask(const Task &task) const
return m_filterStringIsRegexp ? m_filterRegexp.isValid() && s.contains(m_filterRegexp) return m_filterStringIsRegexp ? m_filterRegexp.isValid() && s.contains(m_filterRegexp)
: s.contains(m_filterText, m_filterCaseSensitivity); : s.contains(m_filterText, m_filterCaseSensitivity);
}; };
if (!accepts(task.file.toString()) && !accepts(task.description)) if ((accepts(task.file.toString()) || accepts(task.description)) == m_filterIsInverted)
accept = false; accept = false;
} }

View File

@@ -145,8 +145,11 @@ public:
bool hasFile(const QModelIndex &index) const bool hasFile(const QModelIndex &index) const
{ return taskModel()->hasFile(mapToSource(index)); } { return taskModel()->hasFile(mapToSource(index)); }
void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, void updateFilterProperties(
bool isRegex); const QString &filterText,
Qt::CaseSensitivity caseSensitivity,
bool isRegex,
bool isInverted);
private: private:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
@@ -157,6 +160,7 @@ private:
bool m_includeWarnings; bool m_includeWarnings;
bool m_includeErrors; bool m_includeErrors;
bool m_filterStringIsRegexp = false; bool m_filterStringIsRegexp = false;
bool m_filterIsInverted = false;
Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
QList<Core::Id> m_categoryIds; QList<Core::Id> m_categoryIds;
QString m_filterText; QString m_filterText;

View File

@@ -678,7 +678,8 @@ void TaskWindow::goToPrev()
void TaskWindow::updateFilter() void TaskWindow::updateFilter()
{ {
d->m_filter->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp()); d->m_filter->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp(),
filterIsInverted());
} }
bool TaskWindow::canNavigate() const bool TaskWindow::canNavigate() const