diff --git a/src/flamegraph.cpp b/src/flamegraph.cpp
index 23daae2da..25c51579f 100644
--- a/src/flamegraph.cpp
+++ b/src/flamegraph.cpp
@@ -546,14 +546,14 @@ struct SearchResults
qint64 directCost = 0;
};
-SearchResults applySearch(FrameGraphicsItem* item, const QString& searchValue)
+SearchResults applySearch(FrameGraphicsItem* item, const QRegularExpression& expression)
{
SearchResults result;
- if (searchValue.isEmpty()) {
+ if (expression.pattern().isEmpty()) {
result.matchType = NoSearch;
- } else if (item->symbol().symbol.contains(searchValue, Qt::CaseInsensitive)
- || (searchValue == QLatin1String("??") && item->symbol().symbol.isEmpty())
- || item->symbol().binary.contains(searchValue, Qt::CaseInsensitive)) {
+ } else if (expression.match(item->symbol().symbol).hasMatch()
+ || (expression.pattern() == QLatin1String("??") && item->symbol().symbol.isEmpty())
+ || item->symbol().binary.contains(expression.pattern(), Qt::CaseInsensitive)) {
result.directCost += item->cost();
result.matchType = DirectMatch;
}
@@ -562,7 +562,7 @@ SearchResults applySearch(FrameGraphicsItem* item, const QString& searchValue)
const auto children = item->childItems();
for (auto* child : children) {
auto* childFrame = static_cast(child);
- auto childMatch = applySearch(childFrame, searchValue);
+ auto childMatch = applySearch(childFrame, expression);
if (result.matchType != DirectMatch
&& (childMatch.matchType == DirectMatch || childMatch.matchType == ChildMatch)) {
result.matchType = ChildMatch;
@@ -806,7 +806,8 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
layout->addWidget(searchInput);
searchInput->setPlaceholderText(i18n("Search..."));
- searchInput->setToolTip(i18n("Search the flame graph for a symbol."));
+ searchInput->setToolTip(tr("
Filter the call graph tree.
Prefix with '%' to turn "
+ "it into an regex.
"));
searchInput->setClearButtonEnabled(true);
connect(searchInput, &QLineEdit::textChanged, this, &FlameGraph::setSearchValue);
connect(this, &FlameGraph::uiResetRequested, this, [this, searchInput] {
@@ -1212,7 +1213,8 @@ void FlameGraph::setSearchValue(const QString& value)
m_search = value;
- auto match = applySearch(m_rootItem, value);
+ QRegularExpression regex(Util::escapeSearchPatternIfNessessary(value));
+ auto match = applySearch(m_rootItem, regex);
if (value.isEmpty()) {
m_searchResultsLabel->hide();
diff --git a/src/resultsbottomuppage.ui b/src/resultsbottomuppage.ui
index f5c16c78a..1db3f43d1 100644
--- a/src/resultsbottomuppage.ui
+++ b/src/resultsbottomuppage.ui
@@ -67,7 +67,7 @@
-
- Filter the call graph tree.
+ <html><head/><body><p>Filter the call graph tree.<br/>Prefix with '%' to turn it into an regex.</p></body></html>
diff --git a/src/resultscallercalleepage.ui b/src/resultscallercalleepage.ui
index f6119633d..4e178e0b3 100644
--- a/src/resultscallercalleepage.ui
+++ b/src/resultscallercalleepage.ui
@@ -67,7 +67,7 @@
-
- Filter the call graph tree.
+ <html><head/><body><p>Filter the call graph tree.<br/>Prefix with '%' to turn it into an regex.</p></body></html>
diff --git a/src/resultstopdownpage.ui b/src/resultstopdownpage.ui
index 2287335bb..9448a1c35 100644
--- a/src/resultstopdownpage.ui
+++ b/src/resultstopdownpage.ui
@@ -67,7 +67,7 @@
-
- Filter the call graph tree.
+ <html><head/><body><p>Filter the call graph tree.<br/>Prefix with '%' to turn it into an regex.</p></body></html>
diff --git a/src/resultsutil.cpp b/src/resultsutil.cpp
index 21a4a44fb..d6c0f6c51 100644
--- a/src/resultsutil.cpp
+++ b/src/resultsutil.cpp
@@ -45,7 +45,7 @@ void connectFilter(QLineEdit* filter, QSortFilterProxyModel* proxy)
proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
QObject::connect(timer, &QTimer::timeout, proxy, [filter, proxy]() {
- proxy->setFilterRegularExpression(QRegularExpression::escape(filter->text()));
+ proxy->setFilterRegularExpression(Util::escapeSearchPatternIfNessessary(filter->text()));
});
QObject::connect(filter, &QLineEdit::textChanged, timer, [timer]() { timer->start(300); });
}
diff --git a/src/util.cpp b/src/util.cpp
index 34ab73adc..fc4fe9c72 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -455,3 +455,8 @@ KParts::ReadOnlyPart* Util::createPart(const QString& pluginName)
return service->createInstance();
#endif
}
+
+QString Util::escapeSearchPatternIfNessessary(const QString& pattern)
+{
+ return pattern.startsWith(QLatin1Char('%')) ? pattern.mid(1) : QRegularExpression::escape(pattern);
+}
diff --git a/src/util.h b/src/util.h
index c1ba483b5..451fcf996 100644
--- a/src/util.h
+++ b/src/util.h
@@ -74,4 +74,7 @@ QString collapseTemplate(const QString& str, int level);
QProcessEnvironment appImageEnvironment();
KParts::ReadOnlyPart* createPart(const QString& pluginName);
+
+// if a pattern is prefixed with % then return the pattern, otherwise do a regex escape
+QString escapeSearchPatternIfNessessary(const QString& pattern);
}