From fce8558f8c5f3d7a40c0cd474a0a29e04b7be898 Mon Sep 17 00:00:00 2001 From: Lieven Hey Date: Tue, 18 Apr 2023 15:17:32 +0200 Subject: [PATCH] add search function to disassembler --- src/models/sourcecodemodel.cpp | 40 +++++++++++++++++++++++ src/models/sourcecodemodel.h | 12 +++++++ src/resultsdisassemblypage.cpp | 60 +++++++++++++++++++++++++++++++--- src/resultsdisassemblypage.h | 3 ++ src/resultsdisassemblypage.ui | 55 +++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 4 deletions(-) diff --git a/src/models/sourcecodemodel.cpp b/src/models/sourcecodemodel.cpp index 6b36a0e0..edb99ab5 100644 --- a/src/models/sourcecodemodel.cpp +++ b/src/models/sourcecodemodel.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "highlighter.hpp" SourceCodeModel::SourceCodeModel(KSyntaxHighlighting::Repository* repository, QObject* parent) @@ -106,6 +108,8 @@ void SourceCodeModel::setDisassembly(const DisassemblyOutput& disassemblyOutput, m_startLine = minLineNumber - 1; // convert to index m_numLines = maxLineNumber - minLineNumber + 1; // include minLineNumber + m_sourceCodeLines.reserve(m_numLines); + for (int i = m_startLine; i < m_startLine + m_numLines; i++) { auto block = m_document->findBlockByLineNumber(i); if (!block.isValid()) @@ -242,3 +246,39 @@ void SourceCodeModel::setSysroot(const QString& sysroot) { m_sysroot = sysroot; } + +void SourceCodeModel::find(const QString& search, Direction direction, int offset) +{ + auto searchFunc = [&search](const SourceCodeLine& line) { + return line.text.indexOf(search, 0, Qt::CaseInsensitive) != -1; + }; + + auto start = direction == Direction::Forward + ? (m_sourceCodeLines.begin() + offset) + : (m_sourceCodeLines.end() - (m_numLines - offset - 1)); // 1 one due to offset of the reverse iterator + + auto it = direction == Direction::Forward + ? std::find_if(start, m_sourceCodeLines.end(), searchFunc) + : (std::find_if(std::make_reverse_iterator(start), m_sourceCodeLines.rend(), searchFunc) + 1).base(); + + // it is less than m_sourceCodeLines.begin() if the backward search ends at m_sourceCodeLines.rend() + if (it >= m_sourceCodeLines.begin() && it < m_sourceCodeLines.end()) { + auto distance = std::distance(m_sourceCodeLines.begin(), it); + auto resultIndex = direction == Direction::Forward ? distance : distance; + emit resultFound(createIndex(resultIndex + 1, SourceCodeColumn)); // to index + return; + } + + it = direction == Direction::Forward + ? std::find_if(m_sourceCodeLines.begin(), start, searchFunc) + : (std::find_if(m_sourceCodeLines.rbegin(), std::make_reverse_iterator(start), searchFunc) + 1).base(); + + if (it != m_sourceCodeLines.end()) { + auto distance = std::distance(m_sourceCodeLines.begin(), it); + auto resultIndex = direction == Direction::Forward ? distance : distance; + emit resultFound(createIndex(resultIndex + 1, SourceCodeColumn)); // to index + return; + } + + emit noResultFound(); +} diff --git a/src/models/sourcecodemodel.h b/src/models/sourcecodemodel.h index 8039b28e..627518d3 100644 --- a/src/models/sourcecodemodel.h +++ b/src/models/sourcecodemodel.h @@ -29,6 +29,12 @@ struct SourceCodeLine QTextLine line; }; +enum class Direction +{ + Forward, + Backward +}; + Q_DECLARE_METATYPE(QTextLine) class SourceCodeModel : public QAbstractTableModel @@ -72,10 +78,16 @@ class SourceCodeModel : public QAbstractTableModel FileLineRole, }; +signals: + void resultFound(QModelIndex index); + void noResultFound(); + public slots: void updateHighlighting(int line); void setSysroot(const QString& sysroot); + void find(const QString& search, Direction direction, int offset); + private: QString m_sysroot; QSet m_validLineNumbers; diff --git a/src/resultsdisassemblypage.cpp b/src/resultsdisassemblypage.cpp index 51a1f80f..7023365b 100644 --- a/src/resultsdisassemblypage.cpp +++ b/src/resultsdisassemblypage.cpp @@ -23,7 +23,9 @@ #include #include +#include #include +#include #include "parsers/perf/perfparser.h" #include "resultsutil.h" @@ -171,6 +173,55 @@ ResultsDisassemblyPage::ResultsDisassemblyPage(CostContextMenu* costContextMenu, showDisassembly(); }); + ui->searchWidget->hide(); + + auto searchNext = [this] { + // point to next entry + int offset = m_currentSearchIndex.isValid() ? m_currentSearchIndex.row() : 0; + m_sourceCodeModel->find(ui->searchEdit->text(), Direction::Forward, offset); + }; + + auto searchPrev = [this] { + // point prev entry, need to subtract 2 since row() is index + 1 + int offset = m_currentSearchIndex.isValid() ? m_currentSearchIndex.row() - 2 : 0; + m_sourceCodeModel->find(ui->searchEdit->text(), Direction::Backward, offset); + }; + + auto findAction = KStandardAction::find( + this, + [this] { + ui->searchWidget->show(); + ui->searchEdit->setFocus(); + }, + this); + ui->sourceCodeView->addAction(findAction); + + auto findNextAction = KStandardAction::findNext(this, searchNext, this); + ui->searchWidget->addAction(findNextAction); + auto findPrevAction = KStandardAction::findPrev(this, searchPrev, this); + ui->searchWidget->addAction(findPrevAction); + + connect(ui->searchEdit, &QLineEdit::returnPressed, findNextAction, &QAction::trigger); + connect(ui->searchButton, &QPushButton::clicked, findNextAction, &QAction::trigger); + connect(ui->nextResult, &QPushButton::clicked, findNextAction, &QAction::trigger); + connect(ui->prevResult, &QPushButton::clicked, findPrevAction, &QAction::trigger); + + KColorScheme colorScheme; + connect(m_sourceCodeModel, &SourceCodeModel::resultFound, this, [this, colorScheme](const QModelIndex& index) { + auto palette = ui->searchEdit->palette(); + m_currentSearchIndex = index; + palette.setBrush(QPalette::Text, colorScheme.foreground()); + ui->searchEdit->setPalette(palette); + ui->sourceCodeView->setCurrentIndex(index); + }); + + connect(m_sourceCodeModel, &SourceCodeModel::noResultFound, this, [this, colorScheme]() { + auto palette = ui->searchEdit->palette(); + palette.setColor(QPalette::Text, Qt::red); + ui->searchEdit->setPalette(palette); + ui->sourceCodeView->clearSelection(); + }); + #if KF5SyntaxHighlighting_FOUND QStringList schemes; @@ -310,17 +361,18 @@ void ResultsDisassemblyPage::showDisassembly(const DisassemblyOutput& disassembl ResultsUtil::hideEmptyColumns(m_callerCalleeResults.selfCosts, ui->assemblyView, DisassemblyModel::COLUMN_COUNT); - ResultsUtil::hideEmptyColumns(m_callerCalleeResults.selfCosts, ui->sourceCodeView, - SourceCodeModel::COLUMN_COUNT); + ResultsUtil::hideEmptyColumns(m_callerCalleeResults.selfCosts, ui->sourceCodeView, SourceCodeModel::COLUMN_COUNT); ResultsUtil::hideEmptyColumns(m_callerCalleeResults.inclusiveCosts, ui->sourceCodeView, SourceCodeModel::COLUMN_COUNT + m_callerCalleeResults.selfCosts.numTypes()); // hide self cost for tracepoints in assembly view, this is basically always zero - ResultsUtil::hideTracepointColumns(m_callerCalleeResults.selfCosts, ui->assemblyView, DisassemblyModel::COLUMN_COUNT); + ResultsUtil::hideTracepointColumns(m_callerCalleeResults.selfCosts, ui->assemblyView, + DisassemblyModel::COLUMN_COUNT); // hide self cost for tracepoints - only show inclusive times instead here - ResultsUtil::hideTracepointColumns(m_callerCalleeResults.selfCosts, ui->sourceCodeView, SourceCodeModel::COLUMN_COUNT); + ResultsUtil::hideTracepointColumns(m_callerCalleeResults.selfCosts, ui->sourceCodeView, + SourceCodeModel::COLUMN_COUNT); setupAsmViewModel(); } diff --git a/src/resultsdisassemblypage.h b/src/resultsdisassemblypage.h index fdfe61be..7f62bbfe 100644 --- a/src/resultsdisassemblypage.h +++ b/src/resultsdisassemblypage.h @@ -70,6 +70,9 @@ class ResultsDisassemblyPage : public QWidget // Model DisassemblyModel* m_disassemblyModel; SourceCodeModel* m_sourceCodeModel; + QModelIndex m_currentSearchIndex; + // Current chosen function symbol + Data::Symbol m_curSymbol; // Architecture QString m_arch; // Objdump binary name diff --git a/src/resultsdisassemblypage.ui b/src/resultsdisassemblypage.ui index b1813c2a..cce78963 100644 --- a/src/resultsdisassemblypage.ui +++ b/src/resultsdisassemblypage.ui @@ -164,6 +164,61 @@ + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Search: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +