summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/triage/exports.cpp68
-rw-r--r--examples/triage/exports.h23
2 files changed, 70 insertions, 21 deletions
diff --git a/examples/triage/exports.cpp b/examples/triage/exports.cpp
index 4d274b1a..04547144 100644
--- a/examples/triage/exports.cpp
+++ b/examples/triage/exports.cpp
@@ -25,13 +25,10 @@ GenericExportsModel::GenericExportsModel(QWidget* parent, BinaryViewRef data): Q
}
m_updateTimer = new QTimer(this);
- m_updateTimer->setSingleShot(true);
m_updateTimer->setInterval(500);
connect(m_updateTimer, &QTimer::timeout, this, &GenericExportsModel::updateModel);
- connect(this, &GenericExportsModel::modelUpdate, this, [=, this]() {
- if (m_updateTimer->isActive())
- return;
- m_updateTimer->start();
+ connect(this, &GenericExportsModel::updateTimerOnUIThread, this, [=, this]() {
+ updateTimer(m_needsUpdate);
});
m_data->RegisterNotification(this);
@@ -49,6 +46,10 @@ GenericExportsModel::~GenericExportsModel()
void GenericExportsModel::updateModel()
{
+ if (!m_needsUpdate)
+ return;
+
+ setNeedsUpdate(false);
beginResetModel();
m_allEntries.clear();
for (auto& sym : m_data->GetSymbolsOfType(FunctionSymbol))
@@ -237,40 +238,64 @@ void GenericExportsModel::setFilter(const std::string& filterText)
endResetModel();
}
-
-void GenericExportsModel::OnAnalysisFunctionAdded(BinaryNinja::BinaryView* view, BinaryNinja::Function* func)
+void GenericExportsModel::setNeedsUpdate(bool needed)
{
- emit modelUpdate();
+ if (m_needsUpdate.exchange(needed) == needed)
+ return;
+
+ updateTimer(needed);
}
+void GenericExportsModel::updateTimer(bool needsUpdate)
+{
+ if (needsUpdate && !m_updateTimer->isActive())
+ m_updateTimer->start();
+ if (!needsUpdate && m_updateTimer->isActive())
+ m_updateTimer->stop();
+}
-void GenericExportsModel::OnAnalysisFunctionRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Function* func)
+void GenericExportsModel::pauseUpdates()
{
- emit modelUpdate();
+ m_updatesPaused = true;
+ setNeedsUpdate(false);
}
+void GenericExportsModel::resumeUpdates()
+{
+ m_updatesPaused = false;
+ setNeedsUpdate(true);
+}
-void GenericExportsModel::OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Function* func)
+void GenericExportsModel::onBinaryViewNotification()
{
- emit modelUpdate();
+ if (m_updatesPaused)
+ return;
+
+ // This can be called from any thread so we cannot directly
+ // update the timer. Emitting a signal is relatively expensive
+ // given how frequently we receive notifications, so we only
+ // emit a signal if we didn't already need an update.
+ if (!m_needsUpdate.exchange(true))
+ emit updateTimerOnUIThread();
}
void GenericExportsModel::OnSymbolAdded(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym)
{
- emit modelUpdate();
+ if ((sym->GetBinding() == GlobalBinding) || (sym->GetBinding() == WeakBinding))
+ onBinaryViewNotification();
}
void GenericExportsModel::OnSymbolUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym)
{
- emit modelUpdate();
+ onBinaryViewNotification();
}
void GenericExportsModel::OnSymbolRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym)
{
- emit modelUpdate();
+ onBinaryViewNotification();
}
@@ -403,6 +428,19 @@ void ExportsTreeView::keyPressEvent(QKeyEvent* event)
QTreeView::keyPressEvent(event);
}
+void ExportsTreeView::showEvent(QShowEvent* event)
+{
+ QTreeView::showEvent(event);
+ m_model->resumeUpdates();
+}
+
+
+void ExportsTreeView::hideEvent(QHideEvent* event)
+{
+ QTreeView::hideEvent(event);
+ m_model->pauseUpdates();
+}
+
ExportsWidget::ExportsWidget(QWidget* parent, TriageView* view, BinaryViewRef data) : QWidget(parent)
{
diff --git a/examples/triage/exports.h b/examples/triage/exports.h
index 6ab94407..96c2b779 100644
--- a/examples/triage/exports.h
+++ b/examples/triage/exports.h
@@ -13,16 +13,25 @@ class GenericExportsModel : public QAbstractItemModel, public BinaryNinja::Binar
BinaryViewRef m_data;
std::vector<SymbolRef> m_allEntries, m_entries;
std::string m_filter;
+ QTimer* m_updateTimer;
Qt::SortOrder m_sortOrder;
int m_sortCol;
bool m_hasOrdinals;
- QTimer* m_updateTimer;
+
+ // Read from arbitrary threads while processing notifications.
+ std::atomic<bool> m_updatesPaused = false;
+ // Read/written from arbitrary threads while processing notifications.
+ std::atomic<bool> m_needsUpdate = true;
void performSort(int col, Qt::SortOrder order);
void updateModel();
- signals:
- void modelUpdate();
+ void updateTimer(bool);
+ void setNeedsUpdate(bool);
+ void onBinaryViewNotification();
+
+signals:
+ void updateTimerOnUIThread();
public:
GenericExportsModel(QWidget* parent, BinaryViewRef data);
@@ -37,11 +46,11 @@ class GenericExportsModel : public QAbstractItemModel, public BinaryNinja::Binar
virtual void sort(int col, Qt::SortOrder order) override;
void setFilter(const std::string& filterText);
+ void pauseUpdates();
+ void resumeUpdates();
+
SymbolRef getSymbol(const QModelIndex& index);
- virtual void OnAnalysisFunctionAdded(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
- virtual void OnAnalysisFunctionRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
- virtual void OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
virtual void OnSymbolAdded(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
virtual void OnSymbolUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
virtual void OnSymbolRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
@@ -75,6 +84,8 @@ class ExportsTreeView : public QTreeView, public FilterTarget
protected:
virtual void keyPressEvent(QKeyEvent* event) override;
+ virtual void showEvent(QShowEvent* event) override;
+ virtual void hideEvent(QHideEvent* event) override;
private Q_SLOTS:
void exportSelected(const QModelIndex& cur, const QModelIndex& prev);