aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/utils/outputformatter.h3
-rw-r--r--src/plugins/coreplugin/find/find.pri2
-rw-r--r--src/plugins/coreplugin/find/findtoolbar.cpp70
-rw-r--r--src/plugins/coreplugin/find/findtoolbar.h19
-rw-r--r--src/plugins/coreplugin/find/optionspopup.cpp110
-rw-r--r--src/plugins/coreplugin/find/optionspopup.h59
-rw-r--r--src/plugins/coreplugin/outputwindow.cpp114
-rw-r--r--src/plugins/coreplugin/outputwindow.h22
-rw-r--r--src/plugins/projectexplorer/appoutputpane.cpp98
-rw-r--r--src/plugins/projectexplorer/appoutputpane.h12
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp2
11 files changed, 418 insertions, 93 deletions
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index c516ca14e2..1db42453d5 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -62,6 +62,9 @@ public:
virtual void clear() {}
void setBoldFontEnabled(bool enabled);
+signals:
+ void contentChanged();
+
protected:
void initFormats();
virtual void clearLastLine();
diff --git a/src/plugins/coreplugin/find/find.pri b/src/plugins/coreplugin/find/find.pri
index 41005912fb..811f20a5c0 100644
--- a/src/plugins/coreplugin/find/find.pri
+++ b/src/plugins/coreplugin/find/find.pri
@@ -8,6 +8,7 @@ HEADERS += \
$$PWD/ifindfilter.h \
$$PWD/ifindsupport.h \
$$PWD/itemviewfind.h \
+ $$PWD/optionspopup.h \
$$PWD/searchresultcolor.h \
$$PWD/searchresulttreeitemdelegate.h \
$$PWD/searchresulttreeitemroles.h \
@@ -29,6 +30,7 @@ SOURCES += \
$$PWD/ifindfilter.cpp \
$$PWD/ifindsupport.cpp \
$$PWD/itemviewfind.cpp \
+ $$PWD/optionspopup.cpp \
$$PWD/searchresulttreeitemdelegate.cpp \
$$PWD/searchresulttreeitems.cpp \
$$PWD/searchresulttreemodel.cpp \
diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp
index 7492c33028..72a2d23e3c 100644
--- a/src/plugins/coreplugin/find/findtoolbar.cpp
+++ b/src/plugins/coreplugin/find/findtoolbar.cpp
@@ -26,6 +26,7 @@
#include "findtoolbar.h"
#include "ifindfilter.h"
#include "findplugin.h"
+#include "optionspopup.h"
#include <coreplugin/coreicons.h>
#include <coreplugin/coreplugin.h>
@@ -659,7 +660,8 @@ void FindToolBar::findFlagsChanged()
void FindToolBar::findEditButtonClicked()
{
- auto popup = new OptionsPopup(m_ui.findEdit);
+ auto popup = new OptionsPopup(m_ui.findEdit, {Constants::CASE_SENSITIVE, Constants::WHOLE_WORDS,
+ Constants::REGULAR_EXPRESSIONS, Constants::PRESERVE_CASE});
popup->show();
}
@@ -1014,71 +1016,5 @@ void FindToolBar::updateReplaceEnabled()
m_replacePreviousAction->setEnabled(globalsEnabled);
}
-OptionsPopup::OptionsPopup(QWidget *parent)
- : QWidget(parent, Qt::Popup)
-{
- setAttribute(Qt::WA_DeleteOnClose);
- auto layout = new QVBoxLayout(this);
- layout->setContentsMargins(2, 2, 2, 2);
- layout->setSpacing(2);
- setLayout(layout);
- QCheckBox *firstCheckBox = createCheckboxForCommand(Constants::CASE_SENSITIVE);
- layout->addWidget(firstCheckBox);
- layout->addWidget(createCheckboxForCommand(Constants::WHOLE_WORDS));
- layout->addWidget(createCheckboxForCommand(Constants::REGULAR_EXPRESSIONS));
- layout->addWidget(createCheckboxForCommand(Constants::PRESERVE_CASE));
- firstCheckBox->setFocus();
- move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
-}
-
-bool OptionsPopup::event(QEvent *ev)
-{
- if (ev->type() == QEvent::ShortcutOverride) {
- auto ke = static_cast<QKeyEvent *>(ev);
- if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
- ev->accept();
- return true;
- }
- }
- return QWidget::event(ev);
-}
-
-bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
-{
- auto checkbox = qobject_cast<QCheckBox *>(obj);
- if (ev->type() == QEvent::KeyPress && checkbox) {
- auto ke = static_cast<QKeyEvent *>(ev);
- if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
- checkbox->click();
- ev->accept();
- return true;
- }
- }
- return QWidget::eventFilter(obj, ev);
-}
-
-void OptionsPopup::actionChanged()
-{
- auto action = qobject_cast<QAction *>(sender());
- QTC_ASSERT(action, return);
- QCheckBox *checkbox = m_checkboxMap.value(action);
- QTC_ASSERT(checkbox, return);
- checkbox->setEnabled(action->isEnabled());
-}
-
-QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
-{
- QAction *action = ActionManager::command(id)->action();
- QCheckBox *checkbox = new QCheckBox(action->text());
- checkbox->setToolTip(action->toolTip());
- checkbox->setChecked(action->isChecked());
- checkbox->setEnabled(action->isEnabled());
- checkbox->installEventFilter(this); // enter key handling
- QObject::connect(checkbox, &QCheckBox::clicked, action, &QAction::setChecked);
- QObject::connect(action, &QAction::changed, this, &OptionsPopup::actionChanged);
- m_checkboxMap.insert(action, checkbox);
- return checkbox;
-}
-
} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/find/findtoolbar.h b/src/plugins/coreplugin/find/findtoolbar.h
index 8d6a9b77a4..f2fb494905 100644
--- a/src/plugins/coreplugin/find/findtoolbar.h
+++ b/src/plugins/coreplugin/find/findtoolbar.h
@@ -43,25 +43,6 @@ class FindToolBarPlaceHolder;
namespace Internal {
-class OptionsPopup : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit OptionsPopup(QWidget *parent);
-
-protected:
- bool event(QEvent *ev) override;
- bool eventFilter(QObject *obj, QEvent *ev) override;
-
-private:
- void actionChanged();
-
- QCheckBox *createCheckboxForCommand(Id id);
-
- QMap<QAction *, QCheckBox *> m_checkboxMap;
-};
-
class FindToolBar : public Utils::StyledBar
{
Q_OBJECT
diff --git a/src/plugins/coreplugin/find/optionspopup.cpp b/src/plugins/coreplugin/find/optionspopup.cpp
new file mode 100644
index 0000000000..d7274f87e0
--- /dev/null
+++ b/src/plugins/coreplugin/find/optionspopup.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "optionspopup.h"
+
+#include <coreplugin/actionmanager/actionmanager.h>
+
+#include <utils/qtcassert.h>
+
+#include <QAction>
+#include <QCheckBox>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QVBoxLayout>
+
+namespace Core {
+
+OptionsPopup::OptionsPopup(QWidget *parent, const QVector<Id> &commands)
+ : QWidget(parent, Qt::Popup)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ auto layout = new QVBoxLayout(this);
+ layout->setContentsMargins(2, 2, 2, 2);
+ layout->setSpacing(2);
+ setLayout(layout);
+
+ bool first = true;
+ for (const Id &command : commands) {
+ QCheckBox *checkBox = createCheckboxForCommand(command);
+ if (first) {
+ checkBox->setFocus();
+ first = false;
+ }
+ layout->addWidget(checkBox);
+ }
+ move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
+}
+
+bool OptionsPopup::event(QEvent *ev)
+{
+ if (ev->type() == QEvent::ShortcutOverride) {
+ auto ke = static_cast<QKeyEvent *>(ev);
+ if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
+ ev->accept();
+ return true;
+ }
+ }
+ return QWidget::event(ev);
+}
+
+bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
+{
+ auto checkbox = qobject_cast<QCheckBox *>(obj);
+ if (ev->type() == QEvent::KeyPress && checkbox) {
+ auto ke = static_cast<QKeyEvent *>(ev);
+ if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
+ checkbox->click();
+ ev->accept();
+ return true;
+ }
+ }
+ return QWidget::eventFilter(obj, ev);
+}
+
+void OptionsPopup::actionChanged()
+{
+ auto action = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(action, return);
+ QCheckBox *checkbox = m_checkboxMap.value(action);
+ QTC_ASSERT(checkbox, return);
+ checkbox->setEnabled(action->isEnabled());
+}
+
+QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
+{
+ QAction *action = ActionManager::command(id)->action();
+ QCheckBox *checkbox = new QCheckBox(action->text());
+ checkbox->setToolTip(action->toolTip());
+ checkbox->setChecked(action->isChecked());
+ checkbox->setEnabled(action->isEnabled());
+ checkbox->installEventFilter(this); // enter key handling
+ QObject::connect(checkbox, &QCheckBox::clicked, action, &QAction::setChecked);
+ QObject::connect(action, &QAction::changed, this, &OptionsPopup::actionChanged);
+ m_checkboxMap.insert(action, checkbox);
+ return checkbox;
+}
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/find/optionspopup.h b/src/plugins/coreplugin/find/optionspopup.h
new file mode 100644
index 0000000000..003280eb36
--- /dev/null
+++ b/src/plugins/coreplugin/find/optionspopup.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/id.h>
+
+#include <QMap>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QCheckBox;
+QT_END_NAMESPACE
+
+namespace Core {
+
+class CORE_EXPORT OptionsPopup : public QWidget
+{
+ Q_OBJECT
+
+public:
+ OptionsPopup(QWidget *parent, const QVector<Id> &commands);
+
+protected:
+ bool event(QEvent *ev) override;
+ bool eventFilter(QObject *obj, QEvent *ev) override;
+
+private:
+ void actionChanged();
+
+ QCheckBox *createCheckboxForCommand(Id id);
+
+ QMap<QAction *, QCheckBox *> m_checkboxMap;
+};
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp
index a2bb9a4835..33c203489d 100644
--- a/src/plugins/coreplugin/outputwindow.cpp
+++ b/src/plugins/coreplugin/outputwindow.cpp
@@ -33,6 +33,7 @@
#include <utils/synchronousprocess.h>
#include <QAction>
+#include <QRegularExpression>
#include <QScrollBar>
#include <QTextBlock>
@@ -67,6 +68,9 @@ public:
int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
Qt::MouseButton mouseButtonPressed = Qt::NoButton;
QTextCursor cursor;
+ QString filterText;
+ QTextBlock lastFilteredBlock;
+ OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default;
};
} // namespace Internal
@@ -196,8 +200,10 @@ OutputFormatter *OutputWindow::formatter() const
void OutputWindow::setFormatter(OutputFormatter *formatter)
{
d->formatter = formatter;
- if (d->formatter)
+ if (d->formatter) {
d->formatter->setPlainTextEdit(this);
+ connect(d->formatter, &OutputFormatter::contentChanged, this, &OutputWindow::filterNewContent);
+ }
}
void OutputWindow::showEvent(QShowEvent *e)
@@ -252,6 +258,99 @@ void OutputWindow::setWheelZoomEnabled(bool enabled)
d->m_zoomEnabled = enabled;
}
+void OutputWindow::setHighlightBgColor(const QColor &bgColor)
+{
+ m_highlightBgColor = bgColor;
+}
+
+void OutputWindow::setHighlightTextColor(const QColor &textColor)
+{
+ m_highlightTextColor = textColor;
+}
+
+QString OutputWindow::filterText() const
+{
+ return d->filterText;
+}
+
+void OutputWindow::setFilterText(const QString &filterText)
+{
+ if (d->filterText != filterText) {
+ d->lastFilteredBlock = {};
+ d->filterText = filterText;
+
+ // Update textedit's background color
+ if (filterText.isEmpty()) {
+ d->formatter->plainTextEdit()->setPalette({});
+ } else {
+ QPalette pal;
+ pal.setColor(QPalette::Active, QPalette::Base, m_highlightBgColor);
+ pal.setColor(QPalette::Inactive, QPalette::Base, m_highlightBgColor.darker(120));
+ pal.setColor(QPalette::Active, QPalette::Text, m_highlightTextColor);
+ pal.setColor(QPalette::Inactive, QPalette::Text, m_highlightTextColor.darker(120));
+ d->formatter->plainTextEdit()->setPalette(pal);
+ }
+
+ setReadOnly(!filterText.isEmpty());
+ filterNewContent();
+ }
+}
+
+OutputWindow::FilterModeFlags OutputWindow::filterMode() const
+{
+ return d->filterMode;
+}
+
+void OutputWindow::setFilterMode(OutputWindow::FilterModeFlag filterMode, bool enabled)
+{
+ if (d->filterMode.testFlag(filterMode) != enabled) {
+ d->filterMode.setFlag(filterMode, enabled);
+ d->lastFilteredBlock = {};
+ filterNewContent();
+ }
+}
+
+void OutputWindow::filterNewContent()
+{
+ bool atBottom = isScrollbarAtBottom();
+ QPlainTextEdit *textEdit = d->formatter->plainTextEdit();
+ if (!textEdit)
+ return;
+
+ QTextDocument *document = textEdit->document();
+
+ auto &lastBlock = d->lastFilteredBlock;
+
+ if (!lastBlock.isValid())
+ lastBlock = document->begin();
+
+ if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::RegExp)) {
+ QRegularExpression regExp(d->filterText);
+ if (!d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive))
+ regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+
+ for (; lastBlock != document->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || regExp.match(lastBlock.text()).hasMatch());
+ } else {
+ if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)) {
+ for (; lastBlock != document->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || lastBlock.text().contains(d->filterText));
+ } else {
+ for (; lastBlock != document->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || lastBlock.text().toLower().contains(d->filterText.toLower()));
+ }
+ }
+
+ lastBlock = document->lastBlock();
+ textEdit->setDocument(document);
+
+ if (atBottom)
+ scrollToBottom();
+}
+
QString OutputWindow::doNewlineEnforcement(const QString &out)
{
d->scrollToBottom = true;
@@ -280,6 +379,19 @@ int OutputWindow::maxCharCount() const
return d->maxCharCount;
}
+bool OutputWindow::isReadOnly() const
+{
+ if (d->formatter)
+ return d->formatter->plainTextEdit()->isReadOnly();
+ return false;
+}
+
+void OutputWindow::setReadOnly(bool readOnly)
+{
+ if (d->formatter)
+ d->formatter->plainTextEdit()->setReadOnly(readOnly);
+}
+
void OutputWindow::appendMessage(const QString &output, OutputFormat format)
{
QString out = SynchronousProcess::normalizeNewlines(output);
diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h
index 5e966c64ec..56972b84e7 100644
--- a/src/plugins/coreplugin/outputwindow.h
+++ b/src/plugins/coreplugin/outputwindow.h
@@ -45,6 +45,13 @@ class CORE_EXPORT OutputWindow : public QPlainTextEdit
Q_OBJECT
public:
+ enum class FilterModeFlag {
+ Default = 0x00, // Plain text, non case sensitive, for initialization
+ RegExp = 0x01,
+ CaseSensitive = 0x02,
+ };
+ Q_DECLARE_FLAGS(FilterModeFlags, FilterModeFlag)
+
OutputWindow(Context context, QWidget *parent = nullptr);
~OutputWindow() override;
@@ -65,10 +72,21 @@ public:
void setMaxCharCount(int count);
int maxCharCount() const;
+ bool isReadOnly() const;
+ void setReadOnly(bool readOnly);
+
void setBaseFont(const QFont &newFont);
float fontZoom() const;
void setFontZoom(float zoom);
void setWheelZoomEnabled(bool enabled);
+ void setHighlightBgColor(const QColor &bgColor);
+ void setHighlightTextColor(const QColor &textColor);
+
+ QString filterText() const;
+ void setFilterText(const QString &filterText);
+
+ FilterModeFlags filterMode() const;
+ void setFilterMode(FilterModeFlag filterMode, bool enabled);
signals:
void wheelZoom();
@@ -92,6 +110,10 @@ private:
QTime m_lastMessage;
void enableUndoRedo();
QString doNewlineEnforcement(const QString &out);
+ void filterNewContent();
+
+ QColor m_highlightBgColor;
+ QColor m_highlightTextColor;
Internal::OutputWindowPrivate *d;
};
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp
index 4e2686d524..0caedd578e 100644
--- a/src/plugins/projectexplorer/appoutputpane.cpp
+++ b/src/plugins/projectexplorer/appoutputpane.cpp
@@ -36,6 +36,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/find/basetextfind.h>
+#include <coreplugin/find/optionspopup.h>
#include <coreplugin/icore.h>
#include <coreplugin/outputwindow.h>
#include <texteditor/behaviorsettings.h>
@@ -99,6 +100,12 @@ const char CLEAN_OLD_OUTPUT_KEY[] = "ProjectExplorer/Settings/CleanOldAppOutput"
const char MERGE_CHANNELS_KEY[] = "ProjectExplorer/Settings/MergeStdErrAndStdOut";
const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapAppOutput";
const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxAppOutputLines";
+
+
+// Output filtering
+const char FILTER_REGULAR_EXPRESSIONS[] = "OutputFilter.RegularExpressions";
+const char FILTER_CASE_SENSITIVE[] = "OutputFilter.CaseSensitive";
+
}
namespace ProjectExplorer {
@@ -180,6 +187,7 @@ AppOutputPane::AppOutputPane() :
m_zoomInButton(new QToolButton),
m_zoomOutButton(new QToolButton),
m_settingsButton(new QToolButton),
+ m_filterOutputLineEdit(new Utils::FancyLineEdit),
m_formatterWidget(new QWidget)
{
setObjectName("AppOutputPane"); // Used in valgrind engine
@@ -237,6 +245,32 @@ AppOutputPane::AppOutputPane() :
Core::ICore::showOptionsDialog(OPTIONS_PAGE_ID);
});
+ m_filterActionRegexp = new QAction(this);
+ m_filterActionRegexp->setCheckable(true);
+ m_filterActionRegexp->setText(tr("Use Regular Expressions"));
+ connect(m_filterActionRegexp, &QAction::toggled, this, &AppOutputPane::setRegularExpressions);
+
+ Core::ActionManager::registerAction(m_filterActionRegexp, FILTER_REGULAR_EXPRESSIONS);
+
+ m_filterActionCaseSensitive = new QAction(this);
+ m_filterActionCaseSensitive->setCheckable(true);
+ m_filterActionCaseSensitive->setText(tr("Case Sensitive"));
+ connect(m_filterActionCaseSensitive, &QAction::toggled, this, &AppOutputPane::setCaseSensitive);
+ Core::ActionManager::registerAction(m_filterActionCaseSensitive, FILTER_CASE_SENSITIVE);
+
+ m_filterOutputLineEdit->setPlaceholderText(tr("Filter output..."));
+ m_filterOutputLineEdit->setButtonVisible(Utils::FancyLineEdit::Left, true);
+ m_filterOutputLineEdit->setButtonIcon(Utils::FancyLineEdit::Left, Utils::Icons::MAGNIFIER.icon());
+ m_filterOutputLineEdit->setFiltering(true);
+ m_filterOutputLineEdit->setEnabled(false);
+ connect(m_filterOutputLineEdit, &Utils::FancyLineEdit::textChanged, this, &AppOutputPane::updateFilter);
+ connect(m_filterOutputLineEdit, &Utils::FancyLineEdit::returnPressed, this, &AppOutputPane::updateFilter);
+
+ connect(m_filterOutputLineEdit, &Utils::FancyLineEdit::leftButtonClicked, this, [&](){
+ if (currentIndex() >= 0)
+ AppOutputPane::filterOutputButtonClicked();
+ });
+
auto formatterWidgetsLayout = new QHBoxLayout;
formatterWidgetsLayout->setContentsMargins(QMargins());
m_formatterWidget->setLayout(formatterWidgetsLayout);
@@ -354,7 +388,7 @@ QWidget *AppOutputPane::outputWidget(QWidget *)
QList<QWidget*> AppOutputPane::toolBarWidgets() const
{
return { m_reRunButton, m_stopButton, m_attachButton, m_zoomInButton,
- m_zoomOutButton, m_settingsButton, m_formatterWidget };
+ m_settingsButton, m_zoomOutButton, m_filterOutputLineEdit, m_formatterWidget };
}
QString AppOutputPane::displayName() const
@@ -399,9 +433,14 @@ void AppOutputPane::setFocus()
void AppOutputPane::updateFontSettings()
{
- QFont f = TextEditor::TextEditorSettings::fontSettings().font();
- for (const RunControlTab &rcTab : qAsConst(m_runControlTabs))
- rcTab.window->setBaseFont(f);
+ const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::fontSettings();
+ for (const RunControlTab &rcTab : qAsConst(m_runControlTabs)) {
+ rcTab.window->setBaseFont(fs.font());
+ rcTab.window->setHighlightBgColor(fs.toTextCharFormat(TextEditor::C_SEARCH_RESULT)
+ .background().color());
+ rcTab.window->setHighlightTextColor(fs.toTextCharFormat(TextEditor::C_SEARCH_RESULT)
+ .foreground().color());
+ }
}
void AppOutputPane::updateBehaviorSettings()
@@ -411,6 +450,44 @@ void AppOutputPane::updateBehaviorSettings()
rcTab.window->setWheelZoomEnabled(zoomEnabled);
}
+void AppOutputPane::updateFilter()
+{
+ const QString filter = m_filterOutputLineEdit->text();
+ const int index = currentIndex();
+ if (index != -1)
+ m_runControlTabs.at(index).window->setFilterText(filter);
+}
+
+void AppOutputPane::configureCurrentWindow()
+{
+ using Core::OutputWindow;
+ const QString filter = m_filterOutputLineEdit->text();
+ const int index = currentIndex();
+ if (index != -1) {
+ Core::OutputWindow *currWindow = m_runControlTabs.at(index).window;
+ currWindow->setFilterText(filter);
+ currWindow->setFilterMode(OutputWindow::FilterModeFlag::RegExp, m_filterRegexp);
+ currWindow->setFilterMode(OutputWindow::FilterModeFlag::CaseSensitive, m_filterCaseSensitive);
+ }
+}
+
+void AppOutputPane::filterOutputButtonClicked()
+{
+ auto popup = new Core::OptionsPopup(m_filterOutputLineEdit,
+ {FILTER_REGULAR_EXPRESSIONS, FILTER_CASE_SENSITIVE});
+ popup->show();
+}
+
+void AppOutputPane::setRegularExpressions(bool regularExpressions)
+{
+ m_filterRegexp = regularExpressions;
+}
+
+void AppOutputPane::setCaseSensitive(bool caseSensitive)
+{
+ m_filterCaseSensitive = caseSensitive;
+}
+
void AppOutputPane::createNewOutputWindow(RunControl *rc)
{
QTC_ASSERT(rc, return);
@@ -459,6 +536,7 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
}
// Create new
static int counter = 0;
+ const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::fontSettings();
Core::Id contextId = Core::Id(C_APP_OUTPUT).withSuffix(counter++);
Core::Context context(contextId);
Core::OutputWindow *ow = new Core::OutputWindow(context, m_tabWidget);
@@ -467,7 +545,11 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
ow->setWordWrapEnabled(m_settings.wrapOutput);
ow->setMaxCharCount(m_settings.maxCharCount);
ow->setWheelZoomEnabled(TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
- ow->setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
+ ow->setBaseFont(fs.font());
+ ow->setHighlightBgColor(fs.toTextCharFormat(TextEditor::C_SEARCH_RESULT)
+ .background().color());
+ ow->setHighlightTextColor(fs.toTextCharFormat(TextEditor::C_SEARCH_RESULT)
+ .foreground().color());
ow->setFontZoom(m_zoom);
connect(ow, &Core::OutputWindow::wheelZoom, this, [this, ow]() {
@@ -483,6 +565,7 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
m_tabWidget->addTab(ow, rc->displayName());
qCDebug(appOutputLog) << "AppOutputPane::createNewOutputWindow: Adding tab for" << rc;
updateCloseActions();
+ m_filterOutputLineEdit->setEnabled(m_tabWidget->count() > 0);
}
void AppOutputPane::handleOldOutput(Core::OutputWindow *window) const
@@ -645,6 +728,7 @@ void AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode)
runControl->initiateFinish(); // Will self-destruct.
m_runControlTabs.removeAt(index);
updateCloseActions();
+ m_filterOutputLineEdit->setEnabled(m_tabWidget->count() > 0);
if (m_runControlTabs.isEmpty())
hide();
@@ -726,7 +810,9 @@ void AppOutputPane::tabChanged(int i)
{
const int index = indexOf(m_tabWidget->widget(i));
if (i != -1 && index != -1) {
- enableButtons(m_runControlTabs.at(index).runControl);
+ const RunControlTab &controlTab = m_runControlTabs[index];
+ controlTab.window->setFilterText(m_filterOutputLineEdit->text());
+ enableButtons(controlTab.runControl);
} else {
enableDefaultButtons();
}
diff --git a/src/plugins/projectexplorer/appoutputpane.h b/src/plugins/projectexplorer/appoutputpane.h
index 32f5669398..c44e6c728f 100644
--- a/src/plugins/projectexplorer/appoutputpane.h
+++ b/src/plugins/projectexplorer/appoutputpane.h
@@ -30,6 +30,7 @@
#include <coreplugin/ioutputpane.h>
#include <coreplugin/dialogs/ioptionspage.h>
+#include <utils/fancylineedit.h>
#include <utils/outputformat.h>
#include <QPointer>
@@ -145,6 +146,12 @@ private:
void updateFontSettings();
void storeZoomFactor();
void updateBehaviorSettings();
+ void updateFilter();
+ void configureCurrentWindow();
+ void filterOutputButtonClicked();
+
+ void setCaseSensitive(bool caseSensitive);
+ void setRegularExpressions(bool regularExpressions);
void loadSettings();
void storeSettings() const;
@@ -163,9 +170,14 @@ private:
QToolButton *m_zoomInButton;
QToolButton *m_zoomOutButton;
QToolButton * const m_settingsButton;
+ QAction *m_filterActionRegexp = nullptr;
+ QAction *m_filterActionCaseSensitive = nullptr;
+ Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr;
QWidget *m_formatterWidget;
float m_zoom;
AppOutputSettings m_settings;
+ bool m_filterRegexp = false;
+ bool m_filterCaseSensitive = false;
};
class AppOutputSettingsPage : public Core::IOptionsPage
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 2b7933ea8a..1bffe659cc 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -187,6 +187,8 @@ void QtOutputFormatter::appendMessage(const QString &txt, const QTextCharFormat
appendMessagePart(output.text, output.format);
d->cursor.endEditBlock();
+
+ emit contentChanged();
}
void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, OutputFormat format)