diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/utils/outputformatter.h | 3 | ||||
-rw-r--r-- | src/plugins/coreplugin/find/find.pri | 2 | ||||
-rw-r--r-- | src/plugins/coreplugin/find/findtoolbar.cpp | 70 | ||||
-rw-r--r-- | src/plugins/coreplugin/find/findtoolbar.h | 19 | ||||
-rw-r--r-- | src/plugins/coreplugin/find/optionspopup.cpp | 110 | ||||
-rw-r--r-- | src/plugins/coreplugin/find/optionspopup.h | 59 | ||||
-rw-r--r-- | src/plugins/coreplugin/outputwindow.cpp | 114 | ||||
-rw-r--r-- | src/plugins/coreplugin/outputwindow.h | 22 | ||||
-rw-r--r-- | src/plugins/projectexplorer/appoutputpane.cpp | 98 | ||||
-rw-r--r-- | src/plugins/projectexplorer/appoutputpane.h | 12 | ||||
-rw-r--r-- | src/plugins/qtsupport/qtoutputformatter.cpp | 2 |
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) |