diff --git a/src/models/disassemblymodel.cpp b/src/models/disassemblymodel.cpp index be711a73..0b16c0c5 100644 --- a/src/models/disassemblymodel.cpp +++ b/src/models/disassemblymodel.cpp @@ -16,13 +16,12 @@ #include "highlighter.hpp" #include "sourcecodemodel.h" -DisassemblyModel::DisassemblyModel(QObject* parent) +DisassemblyModel::DisassemblyModel(KSyntaxHighlighting::Repository* repository, QObject* parent) : QAbstractTableModel(parent) , m_document(new QTextDocument(this)) - , m_highlighter(new Highlighter(m_document, this)) + , m_highlighter(new Highlighter(m_document, repository, this)) { m_document->setUndoRedoEnabled(false); - m_highlighter->setDefinitionForName(QStringLiteral("GNU Assembler")); } DisassemblyModel::~DisassemblyModel() = default; @@ -223,3 +222,8 @@ QModelIndex DisassemblyModel::indexForFileLine(const Data::FileLine& fileLine) c return {}; return index(bestMatch, 0); } + +void DisassemblyModel::setSyntaxHighlightDefinition(const KSyntaxHighlighting::Definition& definition) +{ + m_highlighter->setDefinition(definition); +} diff --git a/src/models/disassemblymodel.h b/src/models/disassemblymodel.h index f3ca6cc5..6fce0b9c 100644 --- a/src/models/disassemblymodel.h +++ b/src/models/disassemblymodel.h @@ -18,11 +18,16 @@ class QTextDocument; class Highlighter; +namespace KSyntaxHighlighting { +class Definition; +class Repository; +} + class DisassemblyModel : public QAbstractTableModel { Q_OBJECT public: - explicit DisassemblyModel(QObject* parent = nullptr); + explicit DisassemblyModel(KSyntaxHighlighting::Repository* repository, QObject* parent = nullptr); ~DisassemblyModel(); void setDisassembly(const DisassemblyOutput& disassemblyOutput, const Data::CallerCalleeResults& results); @@ -39,6 +44,11 @@ class DisassemblyModel : public QAbstractTableModel Data::FileLine fileLineForIndex(const QModelIndex& index) const; QModelIndex indexForFileLine(const Data::FileLine& line) const; + Highlighter* highlighter() const + { + return m_highlighter; + } + enum Columns { AddrColumn, @@ -59,6 +69,7 @@ class DisassemblyModel : public QAbstractTableModel public slots: void updateHighlighting(int line); + void setSyntaxHighlightDefinition(const KSyntaxHighlighting::Definition& definition); private: QTextDocument* m_document; diff --git a/src/models/highlighter.cpp b/src/models/highlighter.cpp index d5e64e62..d008e7a8 100644 --- a/src/models/highlighter.cpp +++ b/src/models/highlighter.cpp @@ -19,13 +19,16 @@ #include #endif -Highlighter::Highlighter(QTextDocument* document, QObject* parent) +Highlighter::Highlighter(QTextDocument* document, KSyntaxHighlighting::Repository* repository, QObject* parent) : QObject(parent) #if KF5SyntaxHighlighting_FOUND - , m_repository(std::make_unique()) , m_highlighter(new KSyntaxHighlighting::SyntaxHighlighter(document)) + , m_repository(repository) #endif { +#if !KF5SyntaxHighlighting_FOUND + Q_UNUSED(repository); +#endif document->setDefaultFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); // if qApp is used, UBSAN complains @@ -36,23 +39,18 @@ Highlighter::Highlighter(QTextDocument* document, QObject* parent) Highlighter::~Highlighter() = default; -void Highlighter::setDefinitionForFilename(const QString& filename) +void Highlighter::setDefinition(const KSyntaxHighlighting::Definition& definition) { #if KF5SyntaxHighlighting_FOUND - const auto def = m_repository->definitionForFileName(filename); - m_highlighter->setDefinition(def); -#else - Q_UNUSED(filename); -#endif -} + // don't reparse if definition hasn't changed + if (m_currentDefinition == definition.name()) + return; -void Highlighter::setDefinitionForName(const QString& name) -{ -#if KF5SyntaxHighlighting_FOUND - const auto def = m_repository->definitionForName(name); - m_highlighter->setDefinition(def); + m_highlighter->setDefinition(definition); + m_currentDefinition = definition.name(); + emit definitionChanged(m_currentDefinition); #else - Q_UNUSED(name); + Q_UNUSED(definition); #endif } @@ -68,6 +66,10 @@ bool Highlighter::eventFilter(QObject* /*watched*/, QEvent* event) void Highlighter::updateColorTheme() { #if KF5SyntaxHighlighting_FOUND + if (!m_repository) { + return; + } + KSyntaxHighlighting::Repository::DefaultTheme theme; if (QPalette().base().color().lightness() < 128) { theme = KSyntaxHighlighting::Repository::DarkTheme; diff --git a/src/models/highlighter.hpp b/src/models/highlighter.hpp index c24943bb..ef74101f 100644 --- a/src/models/highlighter.hpp +++ b/src/models/highlighter.hpp @@ -17,6 +17,7 @@ class QTextDocument; namespace KSyntaxHighlighting { class SyntaxHighlighter; +class Definition; class Repository; } @@ -24,11 +25,13 @@ class Highlighter : public QObject { Q_OBJECT public: - Highlighter(QTextDocument* document, QObject* parent = nullptr); + Highlighter(QTextDocument* document, KSyntaxHighlighting::Repository* repository, QObject* parent = nullptr); ~Highlighter(); - void setDefinitionForFilename(const QString& filename); - void setDefinitionForName(const QString& name); + void setDefinition(const KSyntaxHighlighting::Definition& definition); + +signals: + void definitionChanged(const QString& definition); protected: bool eventFilter(QObject* watched, QEvent* event) override; @@ -37,7 +40,8 @@ class Highlighter : public QObject void updateColorTheme(); #if KF5SyntaxHighlighting_FOUND - std::unique_ptr m_repository; KSyntaxHighlighting::SyntaxHighlighter* m_highlighter = nullptr; + KSyntaxHighlighting::Repository* m_repository = nullptr; + QString m_currentDefinition; #endif }; diff --git a/src/models/sourcecodemodel.cpp b/src/models/sourcecodemodel.cpp index 0d4a7f72..24057e81 100644 --- a/src/models/sourcecodemodel.cpp +++ b/src/models/sourcecodemodel.cpp @@ -15,10 +15,10 @@ #include "highlighter.hpp" -SourceCodeModel::SourceCodeModel(QObject* parent) +SourceCodeModel::SourceCodeModel(KSyntaxHighlighting::Repository* repository, QObject* parent) : QAbstractTableModel(parent) , m_document(new QTextDocument(this)) - , m_highlighter(new Highlighter(m_document, this)) + , m_highlighter(new Highlighter(m_document, repository, this)) { m_document->setUndoRedoEnabled(false); qRegisterMetaType(); @@ -64,7 +64,6 @@ void SourceCodeModel::setDisassembly(const DisassemblyOutput& disassemblyOutput, const auto sourceCode = QString::fromUtf8(file.readAll()); m_document->clear(); - m_highlighter->setDefinitionForFilename(disassemblyOutput.mainSourceFileName); m_document->setPlainText(sourceCode); m_document->setTextWidth(m_document->idealWidth()); @@ -231,3 +230,8 @@ void SourceCodeModel::setSysroot(const QString& sysroot) { m_sysroot = sysroot; } + +void SourceCodeModel::setSyntaxHighlightDefinition(const KSyntaxHighlighting::Definition& definition) +{ + m_highlighter->setDefinition(definition); +} diff --git a/src/models/sourcecodemodel.h b/src/models/sourcecodemodel.h index 9278518a..ea68cf72 100644 --- a/src/models/sourcecodemodel.h +++ b/src/models/sourcecodemodel.h @@ -18,13 +18,18 @@ class QTextDocument; class Highlighter; +namespace KSyntaxHighlighting { +class Repository; +class Definition; +} + Q_DECLARE_METATYPE(QTextLine) class SourceCodeModel : public QAbstractTableModel { Q_OBJECT public: - explicit SourceCodeModel(QObject* parent = nullptr); + explicit SourceCodeModel(KSyntaxHighlighting::Repository* repository, QObject* parent = nullptr); ~SourceCodeModel(); void clear(); @@ -39,6 +44,11 @@ class SourceCodeModel : public QAbstractTableModel Data::FileLine fileLineForIndex(const QModelIndex& index) const; QModelIndex indexForFileLine(const Data::FileLine& line) const; + Highlighter* highlighter() const + { + return m_highlighter; + } + enum Columns { SourceCodeLineNumber, @@ -59,6 +69,7 @@ class SourceCodeModel : public QAbstractTableModel public slots: void updateHighlighting(int line); void setSysroot(const QString& sysroot); + void setSyntaxHighlightDefinition(const KSyntaxHighlighting::Definition& definition); private: QString m_sysroot; diff --git a/src/resultsdisassemblypage.cpp b/src/resultsdisassemblypage.cpp index 0addff37..f8934310 100644 --- a/src/resultsdisassemblypage.cpp +++ b/src/resultsdisassemblypage.cpp @@ -28,6 +28,14 @@ #include "parsers/perf/perfparser.h" #include "resultsutil.h" +#if KF5SyntaxHighlighting_FOUND +#include "highlighter.hpp" +#include +#include +#include +#include +#endif + #include "data.h" #include "models/codedelegate.h" #include "models/costdelegate.h" @@ -41,8 +49,14 @@ ResultsDisassemblyPage::ResultsDisassemblyPage(QWidget* parent) : QWidget(parent) , ui(new Ui::ResultsDisassemblyPage) - , m_disassemblyModel(new DisassemblyModel(this)) - , m_sourceCodeModel(new SourceCodeModel(this)) +#if KF5SyntaxHighlighting_FOUND + , m_repository(new KSyntaxHighlighting::Repository) + , m_disassemblyModel(new DisassemblyModel(m_repository.get(), this)) + , m_sourceCodeModel(new SourceCodeModel(m_repository.get(), this)) +#else + , m_disassemblyModel(new DisassemblyModel(nullptr, this)) + , m_sourceCodeModel(new SourceCodeModel(nullptr, this)) +#endif , m_disassemblyCostDelegate(new CostDelegate(DisassemblyModel::CostRole, DisassemblyModel::TotalCostRole, this)) , m_sourceCodeCostDelegate(new CostDelegate(SourceCodeModel::CostRole, SourceCodeModel::TotalCostRole, this)) , m_disassemblyDelegate(new CodeDelegate(DisassemblyModel::RainbowLineNumberRole, DisassemblyModel::HighlightRole, @@ -123,6 +137,38 @@ ResultsDisassemblyPage::ResultsDisassemblyPage(QWidget* parent) } } }); + +#if KF5SyntaxHighlighting_FOUND + QStringList schemes; + + for (const auto& entry : m_repository->definitions()) { + schemes.push_back(entry.name()); + } + + auto connectCompletion = [schemes, this](QComboBox* box, auto* model) { + auto m = new QStringListModel(this); + m->setStringList(schemes); + + auto completer = new QCompleter(this); + completer->setModel(m); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setCompletionMode(QCompleter::PopupCompletion); + box->setCompleter(completer); + + connect(box, qOverload(&QComboBox::activated), this, [this, model, box]() { + model->setSyntaxHighlightDefinition(m_repository->definitionForName(box->currentText())); + }); + + connect(model->highlighter(), &Highlighter::definitionChanged, + [box](const QString& definition) { box->setCurrentText(definition); }); + }; + + connectCompletion(ui->sourceCodeComboBox, m_sourceCodeModel); + connectCompletion(ui->assemblyComboBox, m_disassemblyModel); +#else + ui->customSourceCodeHighlighting->setVisible(false); + ui->customAssemblyHighlighting->setVisible(false); +#endif } ResultsDisassemblyPage::~ResultsDisassemblyPage() = default; @@ -186,6 +232,12 @@ void ResultsDisassemblyPage::showDisassembly(const DisassemblyOutput& disassembl m_disassemblyModel->clear(); m_sourceCodeModel->clear(); +#if KF5SyntaxHighlighting_FOUND + m_sourceCodeModel->setSyntaxHighlightDefinition( + m_repository->definitionForFileName(disassemblyOutput.mainSourceFileName)); + m_disassemblyModel->setSyntaxHighlightDefinition(m_repository->definitionForName(QStringLiteral("GNU Assembler"))); +#endif + const auto& entry = m_callerCalleeResults.entry(m_curSymbol); ui->filenameLabel->setText(disassemblyOutput.mainSourceFileName); diff --git a/src/resultsdisassemblypage.h b/src/resultsdisassemblypage.h index 50496f9d..a04482fa 100644 --- a/src/resultsdisassemblypage.h +++ b/src/resultsdisassemblypage.h @@ -9,6 +9,7 @@ #pragma once #include "data.h" +#include "hotspot-config.h" #include "models/costdelegate.h" #include @@ -34,6 +35,10 @@ struct DisassemblyOutput; class DisassemblyModel; class SourceCodeModel; +namespace KSyntaxHighlighting { +class Repository; +} + class ResultsDisassemblyPage : public QWidget { Q_OBJECT @@ -58,6 +63,9 @@ class ResultsDisassemblyPage : public QWidget void showDisassembly(const DisassemblyOutput& disassemblyOutput); QScopedPointer ui; +#if KF5SyntaxHighlighting_FOUND + QScopedPointer m_repository; +#endif // Model DisassemblyModel* m_disassemblyModel; SourceCodeModel* m_sourceCodeModel; diff --git a/src/resultsdisassemblypage.ui b/src/resultsdisassemblypage.ui index 68a572f5..4da65c07 100644 --- a/src/resultsdisassemblypage.ui +++ b/src/resultsdisassemblypage.ui @@ -44,38 +44,168 @@ - - - Qt::Horizontal - - - - true - - - false + + + + 0 - - true + + 0 - - 200 - - - - - true + + 0 - - false + + 0 - - true + + 0 - - 200 - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + false + + + true + + + + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Syntax Highlighting: + + + + + + + true + + + + + + + + + + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + false + + + true + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Syntax Highlighting: + + + + + + + true + + + + + + + + + + diff --git a/tests/modeltests/tst_models.cpp b/tests/modeltests/tst_models.cpp index 2e41308a..061e0f99 100644 --- a/tests/modeltests/tst_models.cpp +++ b/tests/modeltests/tst_models.cpp @@ -345,7 +345,7 @@ private slots: locationCost.inclusiveCost[0] += 200; locationCost.selfCost[0] += 200; - DisassemblyModel model; + DisassemblyModel model(nullptr); // no disassembly data yet QCOMPARE(model.columnCount(), DisassemblyModel::COLUMN_COUNT); @@ -385,7 +385,7 @@ private slots: Data::CallerCalleeResults results; Data::callerCalleesFromBottomUpData(tree, &results); - SourceCodeModel model; + SourceCodeModel model(nullptr); QCOMPARE(model.columnCount(), SourceCodeModel::COLUMN_COUNT); QCOMPARE(model.rowCount(), 0);