diff options
| author | Jordan Wiens <github@psifertex.com> | 2025-12-19 16:41:05 -0500 |
|---|---|---|
| committer | Jordan Wiens <github@psifertex.com> | 2025-12-19 16:41:05 -0500 |
| commit | 0282141c9b70ca8288a9e434e3b78fcfe2d6343b (patch) | |
| tree | 96bb7a18ca1bed7cf95f59691634b2e5dd8c0748 /examples | |
| parent | 26e768701acd4e48d2810c639754b673b99273f0 (diff) | |
update section list in triage when section list changes
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/triage/sections.cpp | 142 | ||||
| -rw-r--r-- | examples/triage/sections.h | 36 |
2 files changed, 153 insertions, 25 deletions
diff --git a/examples/triage/sections.cpp b/examples/triage/sections.cpp index 95993031..fd8cabb2 100644 --- a/examples/triage/sections.cpp +++ b/examples/triage/sections.cpp @@ -1,5 +1,6 @@ #include <QtWidgets/QGridLayout> #include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QLabel> #include <algorithm> #include <vector> #include "sections.h" @@ -7,6 +8,51 @@ #include "fontsettings.h" +SectionsModel::SectionsModel(QObject* parent, BinaryViewRef data) : QObject(parent), BinaryDataNotification(SectionUpdates) +{ + m_data = data; + m_data->RegisterNotification(this); + updateSections(); +} + + +SectionsModel::~SectionsModel() +{ + m_data->UnregisterNotification(this); +} + + +void SectionsModel::updateSections() +{ + m_sections.clear(); + for (auto& section : m_data->GetSections()) + if (section->GetSemantics() != ExternalSectionSemantics) + m_sections.push_back(section); + sort(m_sections.begin(), m_sections.end(), + [&](SectionRef a, SectionRef b) { return a->GetStart() < b->GetStart(); }); + + emit sectionsChanged(); +} + + +void SectionsModel::OnSectionAdded(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) +{ + QMetaObject::invokeMethod(this, &SectionsModel::updateSections, Qt::QueuedConnection); +} + + +void SectionsModel::OnSectionRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) +{ + QMetaObject::invokeMethod(this, &SectionsModel::updateSections, Qt::QueuedConnection); +} + + +void SectionsModel::OnSectionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) +{ + QMetaObject::invokeMethod(this, &SectionsModel::updateSections, Qt::QueuedConnection); +} + + SegmentsWidget::SegmentsWidget(QWidget* parent, BinaryViewRef data) : QWidget(parent) { QGridLayout* layout = new QGridLayout(); @@ -63,29 +109,77 @@ SegmentsWidget::SegmentsWidget(QWidget* parent, BinaryViewRef data) : QWidget(pa } -SectionsWidget::SectionsWidget(QWidget* parent, BinaryViewRef data) : QWidget(parent) +SectionsWidget::SectionsWidget(QWidget* parent, BinaryViewRef data) : QWidget(parent), m_data(data), m_model(nullptr), m_layout(nullptr), m_isRebuilding(false) { - QGridLayout* layout = new QGridLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->setVerticalSpacing(1); - layout->setHorizontalSpacing(UIContext::getScaledWindowSize(16, 16).width()); + m_model = new SectionsModel(this, data); + + m_layout = new QGridLayout(); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setVerticalSpacing(1); + m_layout->setHorizontalSpacing(UIContext::getScaledWindowSize(16, 16).width()); + setLayout(m_layout); + + connect(m_model, &SectionsModel::sectionsChanged, this, &SectionsWidget::rebuildLayout, Qt::QueuedConnection); + + rebuildLayout(); +} + + +SectionsWidget::~SectionsWidget() +{ + if (m_model) + { + disconnect(m_model, nullptr, this, nullptr); + m_model->blockSignals(true); + } +} + + +void SectionsWidget::rebuildLayout() +{ + if (m_isRebuilding) + return; + + m_isRebuilding = true; + setUpdatesEnabled(false); + + QObjectList children = this->children(); + for (QObject* child : children) + { + if (QWidget* widget = qobject_cast<QWidget*>(child)) + delete widget; + } + + delete m_layout; + + m_layout = new QGridLayout(); + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setVerticalSpacing(1); + m_layout->setHorizontalSpacing(UIContext::getScaledWindowSize(16, 16).width()); + setLayout(m_layout); + + auto sections = m_model->GetSections(); + + if (sections.empty()) + { + setUpdatesEnabled(true); + m_isRebuilding = false; + return; + } size_t maxNameLen = 0; - for (auto& section : data->GetSections()) + for (auto& section : sections) + { if (section->GetName().size() > maxNameLen) maxNameLen = section->GetName().size(); + } if (maxNameLen > 32) maxNameLen = 32; - for (auto& section : data->GetSections()) - if (section->GetSemantics() != ExternalSectionSemantics) - m_sections.push_back(section); - sort(m_sections.begin(), m_sections.end(), - [&](SectionRef a, SectionRef b) { return a->GetStart() < b->GetStart(); }); - int row = 0; - for (auto& section : m_sections) + for (auto& section : sections) { + std::string name = section->GetName(); if (name.size() > maxNameLen) name = name.substr(0, maxNameLen - 1) + std::string("…"); @@ -95,15 +189,15 @@ SectionsWidget::SectionsWidget(QWidget* parent, BinaryViewRef data) : QWidget(pa QString typeName = QString::fromStdString(section->GetType()); QString permissions; - if (data->IsOffsetReadable(section->GetStart())) + if (m_data->IsOffsetReadable(section->GetStart())) permissions += "r"; else permissions += "-"; - if (data->IsOffsetWritable(section->GetStart())) + if (m_data->IsOffsetWritable(section->GetStart())) permissions += "w"; else permissions += "-"; - if (data->IsOffsetExecutable(section->GetStart())) + if (m_data->IsOffsetExecutable(section->GetStart())) permissions += "x"; else permissions += "-"; @@ -118,7 +212,7 @@ SectionsWidget::SectionsWidget(QWidget* parent, BinaryViewRef data) : QWidget(pa QLabel* nameLabel = new QLabel(QString::fromStdString(name)); nameLabel->setFont(getMonospaceFont(this)); - layout->addWidget(nameLabel, row, 0); + m_layout->addWidget(nameLabel, row, 0); QHBoxLayout* rangeLayout = new QHBoxLayout(); rangeLayout->setContentsMargins(0, 0, 0, 0); @@ -129,21 +223,23 @@ SectionsWidget::SectionsWidget(QWidget* parent, BinaryViewRef data) : QWidget(pa rangeLayout->addWidget(beginLabel); rangeLayout->addWidget(dashLabel); rangeLayout->addWidget(endLabel); - layout->addLayout(rangeLayout, row, 1); + m_layout->addLayout(rangeLayout, row, 1); QLabel* permissionsLabel = new QLabel(permissions); permissionsLabel->setFont(getMonospaceFont(this)); - layout->addWidget(permissionsLabel, row, 2); + m_layout->addWidget(permissionsLabel, row, 2); QLabel* typeLabel = new QLabel(typeName); typeLabel->setFont(getMonospaceFont(this)); - layout->addWidget(typeLabel, row, 3); + m_layout->addWidget(typeLabel, row, 3); QLabel* semanticsLabel = new QLabel(semantics); semanticsLabel->setFont(getMonospaceFont(this)); - layout->addWidget(semanticsLabel, row, 4); + m_layout->addWidget(semanticsLabel, row, 4); row++; } - layout->setColumnStretch(5, 1); - setLayout(layout); + m_layout->setColumnStretch(5, 1); + + setUpdatesEnabled(true); + m_isRebuilding = false; } diff --git a/examples/triage/sections.h b/examples/triage/sections.h index 00285df8..d4cdb29e 100644 --- a/examples/triage/sections.h +++ b/examples/triage/sections.h @@ -14,11 +14,43 @@ class SegmentsWidget : public QWidget }; -class SectionsWidget : public QWidget +class SectionsModel : public QObject, public BinaryNinja::BinaryDataNotification { + Q_OBJECT + + BinaryViewRef m_data; std::vector<SectionRef> m_sections; + void updateSections(); + +signals: + void sectionsChanged(); + public: - SectionsWidget(QWidget* parent, BinaryViewRef data); + SectionsModel(QObject* parent, BinaryViewRef data); + virtual ~SectionsModel(); + const std::vector<SectionRef>& GetSections() const { return m_sections; } + + virtual void OnSectionAdded(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override; + virtual void OnSectionRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override; + virtual void OnSectionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override; +}; + + +class SectionsWidget : public QWidget +{ + Q_OBJECT + + BinaryViewRef m_data; + SectionsModel* m_model; + QGridLayout* m_layout; + bool m_isRebuilding; + + void rebuildLayout(); + + public: + SectionsWidget(QWidget* parent, BinaryViewRef data); + virtual ~SectionsWidget(); + const std::vector<SectionRef>& GetSections() const { return m_model->GetSections(); } }; |
