summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-10-07 14:32:48 -0400
committerMason Reed <mason@vector35.com>2025-10-07 14:33:34 -0400
commit4a227e0523391bc026bf96c3c31d44a39cac1701 (patch)
treecc603b899a446fb469a0be3ae4c2c77e6351c091 /plugins
parent3e24f6ab0b373d8718e26a19ac296044cc0d19c6 (diff)
[WARP] Format UI plugin
Diffstat (limited to 'plugins')
-rw-r--r--plugins/warp/ui/containers.cpp471
-rw-r--r--plugins/warp/ui/containers.h245
-rw-r--r--plugins/warp/ui/matched.cpp139
-rw-r--r--plugins/warp/ui/matched.h16
-rw-r--r--plugins/warp/ui/matches.cpp281
-rw-r--r--plugins/warp/ui/matches.h26
-rw-r--r--plugins/warp/ui/plugin.cpp114
-rw-r--r--plugins/warp/ui/plugin.h52
-rw-r--r--plugins/warp/ui/shared/constraint.cpp178
-rw-r--r--plugins/warp/ui/shared/constraint.h66
-rw-r--r--plugins/warp/ui/shared/fetchdialog.cpp325
-rw-r--r--plugins/warp/ui/shared/fetchdialog.h48
-rw-r--r--plugins/warp/ui/shared/fetcher.cpp115
-rw-r--r--plugins/warp/ui/shared/fetcher.h45
-rw-r--r--plugins/warp/ui/shared/function.cpp498
-rw-r--r--plugins/warp/ui/shared/function.h177
-rw-r--r--plugins/warp/ui/shared/misc.cpp186
-rw-r--r--plugins/warp/ui/shared/misc.h126
-rw-r--r--plugins/warp/ui/shared/search.cpp496
-rw-r--r--plugins/warp/ui/shared/search.h291
20 files changed, 1936 insertions, 1959 deletions
diff --git a/plugins/warp/ui/containers.cpp b/plugins/warp/ui/containers.cpp
index 689d695f..f800f977 100644
--- a/plugins/warp/ui/containers.cpp
+++ b/plugins/warp/ui/containers.cpp
@@ -1,274 +1,283 @@
#include "containers.h"
-QVariant WarpSourcesModel::data(const QModelIndex &index, int role) const
+QVariant WarpSourcesModel::data(const QModelIndex& index, int role) const
{
- if (!index.isValid())
- return {};
- if (index.row() < 0 || index.row() >= rowCount())
- return {};
+ if (!index.isValid())
+ return {};
+ if (index.row() < 0 || index.row() >= rowCount())
+ return {};
- const auto &r = m_rows[static_cast<size_t>(index.row())];
+ const auto& r = m_rows[static_cast<size_t>(index.row())];
- // Build a small two-dot status icon (left: writable, right: uncommitted)
- auto statusIcon = [](bool writable, bool uncommitted) -> QIcon {
- static QIcon cache[2][2]; // [writable][uncommitted]
- QIcon &cached = cache[writable ? 1 : 0][uncommitted ? 1 : 0];
- if (!cached.isNull())
- return cached;
+ // Build a small two-dot status icon (left: writable, right: uncommitted)
+ auto statusIcon = [](bool writable, bool uncommitted) -> QIcon {
+ static QIcon cache[2][2]; // [writable][uncommitted]
+ QIcon& cached = cache[writable ? 1 : 0][uncommitted ? 1 : 0];
+ if (!cached.isNull())
+ return cached;
- const int w = 16, h = 12, radius = 4;
- QPixmap pm(w, h);
- pm.fill(Qt::transparent);
- QPainter p(&pm);
- p.setRenderHint(QPainter::Antialiasing, true);
+ const int w = 16, h = 12, radius = 4;
+ QPixmap pm(w, h);
+ pm.fill(Qt::transparent);
+ QPainter p(&pm);
+ p.setRenderHint(QPainter::Antialiasing, true);
- // Colors
- QColor writableOn(76, 175, 80); // green
- QColor writableOff(158, 158, 158); // grey
- QColor uncommittedOn(255, 193, 7); // amber
- QColor uncommittedOff(158, 158, 158); // grey
+ // Colors
+ QColor writableOn(76, 175, 80); // green
+ QColor writableOff(158, 158, 158); // grey
+ QColor uncommittedOn(255, 193, 7); // amber
+ QColor uncommittedOff(158, 158, 158); // grey
- // Left dot: writable
- p.setBrush(writable ? writableOn : writableOff);
- p.setPen(Qt::NoPen);
- p.drawEllipse(QPoint(4, h / 2), radius, radius);
+ // Left dot: writable
+ p.setBrush(writable ? writableOn : writableOff);
+ p.setPen(Qt::NoPen);
+ p.drawEllipse(QPoint(4, h / 2), radius, radius);
- // Right dot: uncommitted
- p.setBrush(uncommitted ? uncommittedOn : uncommittedOff);
- p.drawEllipse(QPoint(w - 6, h / 2), radius, radius);
+ // Right dot: uncommitted
+ p.setBrush(uncommitted ? uncommittedOn : uncommittedOff);
+ p.drawEllipse(QPoint(w - 6, h / 2), radius, radius);
- p.end();
- cached = QIcon(pm);
- return cached;
- };
+ p.end();
+ cached = QIcon(pm);
+ return cached;
+ };
- if (role == Qt::DecorationRole && index.column() == PathCol)
- {
- return statusIcon(r.writable, r.uncommitted);
- }
+ if (role == Qt::DecorationRole && index.column() == PathCol)
+ {
+ return statusIcon(r.writable, r.uncommitted);
+ }
- if (role == Qt::ToolTipRole && index.column() == PathCol)
- {
- QStringList parts;
- parts << (r.writable ? "Writable" : "Read-only");
- parts << (r.uncommitted ? "Uncommitted changes" : "No uncommitted changes");
- return parts.join(" • ");
- }
+ if (role == Qt::ToolTipRole && index.column() == PathCol)
+ {
+ QStringList parts;
+ parts << (r.writable ? "Writable" : "Read-only");
+ parts << (r.uncommitted ? "Uncommitted changes" : "No uncommitted changes");
+ return parts.join(" • ");
+ }
- if (role == Qt::DisplayRole)
- {
- switch (index.column())
- {
- case GuidCol: return r.guid;
- case PathCol: return r.path;
- case WritableCol: return r.writable ? "Yes" : "No";
- case UncommittedCol: return r.uncommitted ? "Yes" : "No";
- default: return {};
- }
- }
+ if (role == Qt::DisplayRole)
+ {
+ switch (index.column())
+ {
+ case GuidCol:
+ return r.guid;
+ case PathCol:
+ return r.path;
+ case WritableCol:
+ return r.writable ? "Yes" : "No";
+ case UncommittedCol:
+ return r.uncommitted ? "Yes" : "No";
+ default:
+ return {};
+ }
+ }
- if (role == Qt::CheckStateRole)
- {
- // Optional: expose as checkboxes if someone ever shows these columns
- switch (index.column())
- {
- case WritableCol: return r.writable ? Qt::Checked : Qt::Unchecked;
- case UncommittedCol: return r.uncommitted ? Qt::Checked : Qt::Unchecked;
- default: break;
- }
- }
+ if (role == Qt::CheckStateRole)
+ {
+ // Optional: expose as checkboxes if someone ever shows these columns
+ switch (index.column())
+ {
+ case WritableCol:
+ return r.writable ? Qt::Checked : Qt::Unchecked;
+ case UncommittedCol:
+ return r.uncommitted ? Qt::Checked : Qt::Unchecked;
+ default:
+ break;
+ }
+ }
- return {};
+ return {};
}
-WarpContainerWidget::WarpContainerWidget(Warp::Ref<Warp::Container> container, QWidget *parent) : QWidget(parent)
+WarpContainerWidget::WarpContainerWidget(Warp::Ref<Warp::Container> container, QWidget* parent) : QWidget(parent)
{
- m_container = std::move(container);
- auto *layout = new QVBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- m_tabs = new QTabWidget(this);
- layout->addWidget(m_tabs);
+ m_container = std::move(container);
+ auto* layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ m_tabs = new QTabWidget(this);
+ layout->addWidget(m_tabs);
- // Sources tab
- m_sourcesPage = new QWidget(this);
- auto *sourcesLayout = new QVBoxLayout(m_sourcesPage);
- m_sourcesView = new QTableView(m_sourcesPage);
- m_sourcesModel = new WarpSourcesModel(m_sourcesPage);
- m_sourcesModel->setContainer(m_container);
- m_sourcesView->setModel(m_sourcesModel);
- m_sourcesView->horizontalHeader()->setStretchLastSection(true);
- m_sourcesView->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_sourcesView->setSelectionMode(QAbstractItemView::SingleSelection);
+ // Sources tab
+ m_sourcesPage = new QWidget(this);
+ auto* sourcesLayout = new QVBoxLayout(m_sourcesPage);
+ m_sourcesView = new QTableView(m_sourcesPage);
+ m_sourcesModel = new WarpSourcesModel(m_sourcesPage);
+ m_sourcesModel->setContainer(m_container);
+ m_sourcesView->setModel(m_sourcesModel);
+ m_sourcesView->horizontalHeader()->setStretchLastSection(true);
+ m_sourcesView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_sourcesView->setSelectionMode(QAbstractItemView::SingleSelection);
- // Make the table look like a simple list that shows only the source path
- m_sourcesView->setShowGrid(false);
- m_sourcesView->verticalHeader()->setVisible(false);
- m_sourcesView->horizontalHeader()->setVisible(false);
- m_sourcesView->setAlternatingRowColors(false);
- m_sourcesView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_sourcesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- m_sourcesView->setWordWrap(false);
- m_sourcesView->setIconSize(QSize(16, 12));
- // Ensure long paths truncate from the left: "...tail/of/the/path"
- m_sourcesView->setTextElideMode(Qt::ElideLeft);
- // Hide GUID column, keep only the Path column visible
- m_sourcesView->setColumnHidden(WarpSourcesModel::GuidCol, true);
- // Also hide boolean columns; their state is shown as an icon next to the path
- m_sourcesView->setColumnHidden(WarpSourcesModel::WritableCol, true);
- m_sourcesView->setColumnHidden(WarpSourcesModel::UncommittedCol, true);
- // Ensure the remaining (Path) column fills the width
- m_sourcesView->horizontalHeader()->setSectionResizeMode(WarpSourcesModel::PathCol, QHeaderView::Stretch);
+ // Make the table look like a simple list that shows only the source path
+ m_sourcesView->setShowGrid(false);
+ m_sourcesView->verticalHeader()->setVisible(false);
+ m_sourcesView->horizontalHeader()->setVisible(false);
+ m_sourcesView->setAlternatingRowColors(false);
+ m_sourcesView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_sourcesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_sourcesView->setWordWrap(false);
+ m_sourcesView->setIconSize(QSize(16, 12));
+ // Ensure long paths truncate from the left: "...tail/of/the/path"
+ m_sourcesView->setTextElideMode(Qt::ElideLeft);
+ // Hide GUID column, keep only the Path column visible
+ m_sourcesView->setColumnHidden(WarpSourcesModel::GuidCol, true);
+ // Also hide boolean columns; their state is shown as an icon next to the path
+ m_sourcesView->setColumnHidden(WarpSourcesModel::WritableCol, true);
+ m_sourcesView->setColumnHidden(WarpSourcesModel::UncommittedCol, true);
+ // Ensure the remaining (Path) column fills the width
+ m_sourcesView->horizontalHeader()->setSectionResizeMode(WarpSourcesModel::PathCol, QHeaderView::Stretch);
- // Per-item context menu
- m_sourcesView->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(m_sourcesView, &QWidget::customContextMenuRequested, this, [this](const QPoint &pos) {
- QMenu menu(m_sourcesView);
- const QModelIndex index = m_sourcesView->indexAt(pos);
+ // Per-item context menu
+ m_sourcesView->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_sourcesView, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) {
+ QMenu menu(m_sourcesView);
+ const QModelIndex index = m_sourcesView->indexAt(pos);
- if (!index.isValid())
- {
- QAction *actAdd = menu.addAction(tr("Add Source"));
- QAction *chosen = menu.exec(m_sourcesView->viewport()->mapToGlobal(pos));
- if (!chosen)
- return;
- if (chosen == actAdd)
- {
- std::string sourceName;
- if (!BinaryNinja::GetTextLineInput(sourceName, "Source name:", "Add Source"))
- return;
- if (const auto sourceId = m_container->AddSource(sourceName); !sourceId.has_value())
- {
- BinaryNinja::LogAlertF("Failed to add source: {}", sourceName);
- return;
- }
- m_sourcesModel->reload();
- }
- } else
- {
- m_sourcesView->setCurrentIndex(index.sibling(index.row(), WarpSourcesModel::PathCol));
+ if (!index.isValid())
+ {
+ QAction* actAdd = menu.addAction(tr("Add Source"));
+ QAction* chosen = menu.exec(m_sourcesView->viewport()->mapToGlobal(pos));
+ if (!chosen)
+ return;
+ if (chosen == actAdd)
+ {
+ std::string sourceName;
+ if (!BinaryNinja::GetTextLineInput(sourceName, "Source name:", "Add Source"))
+ return;
+ if (const auto sourceId = m_container->AddSource(sourceName); !sourceId.has_value())
+ {
+ BinaryNinja::LogAlertF("Failed to add source: {}", sourceName);
+ return;
+ }
+ m_sourcesModel->reload();
+ }
+ }
+ else
+ {
+ m_sourcesView->setCurrentIndex(index.sibling(index.row(), WarpSourcesModel::PathCol));
- const int row = index.row();
- const QModelIndex pathIdx = m_sourcesModel->index(row, WarpSourcesModel::PathCol);
- const QModelIndex guidIdx = m_sourcesModel->index(row, WarpSourcesModel::GuidCol);
- const QString path = m_sourcesModel->data(pathIdx, Qt::DisplayRole).toString();
- const QFileInfo fi(path);
-
- const QString guid = m_sourcesModel->data(guidIdx, Qt::DisplayRole).toString();
+ const int row = index.row();
+ const QModelIndex pathIdx = m_sourcesModel->index(row, WarpSourcesModel::PathCol);
+ const QModelIndex guidIdx = m_sourcesModel->index(row, WarpSourcesModel::GuidCol);
+ const QString path = m_sourcesModel->data(pathIdx, Qt::DisplayRole).toString();
+ const QFileInfo fi(path);
- QAction *actReveal = menu.addAction(tr("Reveal in File Browser"));
- actReveal->setEnabled(fi.exists());
- QAction *actCopyPath = menu.addAction(tr("Copy Path"));
- QAction *actCopyGuid = menu.addAction(tr("Copy GUID"));
-
- QAction *chosen = menu.exec(m_sourcesView->viewport()->mapToGlobal(pos));
- if (!chosen)
- return;
- if (chosen == actCopyPath)
- QGuiApplication::clipboard()->setText(path);
- else if (chosen == actCopyGuid)
- QGuiApplication::clipboard()->setText(guid);
- else if (chosen == actReveal)
- QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));
- }
- });
+ const QString guid = m_sourcesModel->data(guidIdx, Qt::DisplayRole).toString();
+ QAction* actReveal = menu.addAction(tr("Reveal in File Browser"));
+ actReveal->setEnabled(fi.exists());
+ QAction* actCopyPath = menu.addAction(tr("Copy Path"));
+ QAction* actCopyGuid = menu.addAction(tr("Copy GUID"));
- sourcesLayout->addWidget(m_sourcesView);
- m_tabs->addTab(m_sourcesPage, tr("Sources"));
+ QAction* chosen = menu.exec(m_sourcesView->viewport()->mapToGlobal(pos));
+ if (!chosen)
+ return;
+ if (chosen == actCopyPath)
+ QGuiApplication::clipboard()->setText(path);
+ else if (chosen == actCopyGuid)
+ QGuiApplication::clipboard()->setText(guid);
+ else if (chosen == actReveal)
+ QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));
+ }
+ });
- // Search tab
- m_searchTab = new WarpSearchWidget(m_container, this);
- m_tabs->addTab(m_searchTab, tr("Search"));
- // Periodic refresh timer for the Sources view
- m_refreshTimer = new QTimer(this);
- m_refreshTimer->setInterval(5000);
- connect(m_refreshTimer, &QTimer::timeout, this, [this]() {
- // Only refresh if the widget and the Sources page are actually visible
- if (!this->isVisible() || !m_sourcesPage || !m_sourcesPage->isVisible())
- return;
+ sourcesLayout->addWidget(m_sourcesView);
+ m_tabs->addTab(m_sourcesPage, tr("Sources"));
- // Preserve selection by GUID across reloads
- QString currentGuid;
- if (const QModelIndex currentIdx = m_sourcesView->currentIndex(); currentIdx.isValid())
- {
- const int row = currentIdx.row();
- const QModelIndex guidIdx = m_sourcesModel->index(row, WarpSourcesModel::GuidCol);
- currentGuid = m_sourcesModel->data(guidIdx, Qt::DisplayRole).toString();
- }
+ // Search tab
+ m_searchTab = new WarpSearchWidget(m_container, this);
+ m_tabs->addTab(m_searchTab, tr("Search"));
- m_sourcesModel->reload();
+ // Periodic refresh timer for the Sources view
+ m_refreshTimer = new QTimer(this);
+ m_refreshTimer->setInterval(5000);
+ connect(m_refreshTimer, &QTimer::timeout, this, [this]() {
+ // Only refresh if the widget and the Sources page are actually visible
+ if (!this->isVisible() || !m_sourcesPage || !m_sourcesPage->isVisible())
+ return;
- if (!currentGuid.isEmpty())
- {
- for (int r = 0; r < m_sourcesModel->rowCount(); ++r)
- {
- const QModelIndex gIdx = m_sourcesModel->index(r, WarpSourcesModel::GuidCol);
- if (m_sourcesModel->data(gIdx, Qt::DisplayRole).toString() == currentGuid)
- {
- m_sourcesView->setCurrentIndex(m_sourcesModel->index(r, WarpSourcesModel::PathCol));
- break;
- }
- }
- }
- });
- m_refreshTimer->start();
+ // Preserve selection by GUID across reloads
+ QString currentGuid;
+ if (const QModelIndex currentIdx = m_sourcesView->currentIndex(); currentIdx.isValid())
+ {
+ const int row = currentIdx.row();
+ const QModelIndex guidIdx = m_sourcesModel->index(row, WarpSourcesModel::GuidCol);
+ currentGuid = m_sourcesModel->data(guidIdx, Qt::DisplayRole).toString();
+ }
- // Optional: force a refresh when switching back to the Sources tab
- connect(m_tabs, &QTabWidget::currentChanged, this, [this](const int idx) {
- QWidget *w = m_tabs->widget(idx);
- if (w == m_sourcesPage)
- m_sourcesModel->reload();
- });
+ m_sourcesModel->reload();
+
+ if (!currentGuid.isEmpty())
+ {
+ for (int r = 0; r < m_sourcesModel->rowCount(); ++r)
+ {
+ const QModelIndex gIdx = m_sourcesModel->index(r, WarpSourcesModel::GuidCol);
+ if (m_sourcesModel->data(gIdx, Qt::DisplayRole).toString() == currentGuid)
+ {
+ m_sourcesView->setCurrentIndex(m_sourcesModel->index(r, WarpSourcesModel::PathCol));
+ break;
+ }
+ }
+ }
+ });
+ m_refreshTimer->start();
+
+ // Optional: force a refresh when switching back to the Sources tab
+ connect(m_tabs, &QTabWidget::currentChanged, this, [this](const int idx) {
+ QWidget* w = m_tabs->widget(idx);
+ if (w == m_sourcesPage)
+ m_sourcesModel->reload();
+ });
}
-WarpContainersPane::WarpContainersPane(QWidget *parent) : QWidget(parent)
+WarpContainersPane::WarpContainersPane(QWidget* parent) : QWidget(parent)
{
- auto *splitter = new QSplitter(Qt::Vertical, this);
- splitter->setContentsMargins(0, 0, 0, 0);
- auto *mainLayout = new QVBoxLayout(this);
- mainLayout->setContentsMargins(0, 0, 0, 0);
- mainLayout->setSpacing(0);
- mainLayout->addWidget(splitter);
- auto newPalette = palette();
- newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
- setAutoFillBackground(true);
- setPalette(newPalette);
+ auto* splitter = new QSplitter(Qt::Vertical, this);
+ splitter->setContentsMargins(0, 0, 0, 0);
+ auto* mainLayout = new QVBoxLayout(this);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+ mainLayout->setSpacing(0);
+ mainLayout->addWidget(splitter);
+ auto newPalette = palette();
+ newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
+ setAutoFillBackground(true);
+ setPalette(newPalette);
- // List on top
- m_list = new QListWidget(splitter);
- m_list->setSelectionMode(QAbstractItemView::SingleSelection);
- m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- m_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
- m_list->setUniformItemSizes(true);
+ // List on top
+ m_list = new QListWidget(splitter);
+ m_list->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+ m_list->setUniformItemSizes(true);
- // Make names larger and show end of long strings (elide at the start)
- {
- QFont f = m_list->font();
- f.setPointSizeF(f.pointSizeF() + 2.0); // bump size
- m_list->setFont(f);
- m_list->setTextElideMode(Qt::ElideLeft);
- }
+ // Make names larger and show end of long strings (elide at the start)
+ {
+ QFont f = m_list->font();
+ f.setPointSizeF(f.pointSizeF() + 2.0); // bump size
+ m_list->setFont(f);
+ m_list->setTextElideMode(Qt::ElideLeft);
+ }
- // Container view (tabs) below
- m_stack = new QStackedWidget(splitter);
- m_stack->setContentsMargins(0, 0, 0, 0);
+ // Container view (tabs) below
+ m_stack = new QStackedWidget(splitter);
+ m_stack->setContentsMargins(0, 0, 0, 0);
- splitter->setStretchFactor(0, 0); // list: minimal growth
- splitter->setStretchFactor(1, 1); // stack: takes remaining space
- splitter->setCollapsible(0, false);
- splitter->setCollapsible(1, false);
+ splitter->setStretchFactor(0, 0); // list: minimal growth
+ splitter->setStretchFactor(1, 1); // stack: takes remaining space
+ splitter->setCollapsible(0, false);
+ splitter->setCollapsible(1, false);
- populate();
+ populate();
- connect(m_list, &QListWidget::currentRowChanged, this, [this](int row) {
- if (row >= 0 && row < m_stack->count())
- m_stack->setCurrentIndex(row);
- });
+ connect(m_list, &QListWidget::currentRowChanged, this, [this](int row) {
+ if (row >= 0 && row < m_stack->count())
+ m_stack->setCurrentIndex(row);
+ });
- // Select the first container if available
- if (m_list->count() > 0)
- {
- m_list->setCurrentRow(0);
- }
+ // Select the first container if available
+ if (m_list->count() > 0)
+ {
+ m_list->setCurrentRow(0);
+ }
}
diff --git a/plugins/warp/ui/containers.h b/plugins/warp/ui/containers.h
index 80ffa12f..d5e82242 100644
--- a/plugins/warp/ui/containers.h
+++ b/plugins/warp/ui/containers.h
@@ -14,162 +14,165 @@
class WarpSourcesModel final : public QAbstractTableModel
{
- Q_OBJECT
+ Q_OBJECT
public:
- enum Columns : int
- {
- GuidCol = 0,
- PathCol,
- WritableCol,
- UncommittedCol,
- ColumnCount
- };
+ enum Columns : int
+ {
+ GuidCol = 0,
+ PathCol,
+ WritableCol,
+ UncommittedCol,
+ ColumnCount
+ };
- explicit WarpSourcesModel(QObject *parent = nullptr)
- : QAbstractTableModel(parent)
- {
- }
+ explicit WarpSourcesModel(QObject* parent = nullptr) : QAbstractTableModel(parent) {}
- void setContainer(Warp::Ref<Warp::Container> container)
- {
- m_container = std::move(container);
- reload();
- }
+ void setContainer(Warp::Ref<Warp::Container> container)
+ {
+ m_container = std::move(container);
+ reload();
+ }
- void reload()
- {
- // Fetch synchronously (can be adapted to async if needed)
- beginResetModel();
- m_rows.clear();
- for (const auto &src: m_container->GetSources())
- {
- QString guid = QString::fromStdString(src.ToString());
- QString path = QString::fromStdString(m_container->SourcePath(src).value_or(std::string{}));
- bool writable = m_container->IsSourceWritable(src);
- bool uncommitted = m_container->IsSourceUncommitted(src);
- m_rows.push_back({guid, path, writable, uncommitted});
- }
- endResetModel();
- }
+ void reload()
+ {
+ // Fetch synchronously (can be adapted to async if needed)
+ beginResetModel();
+ m_rows.clear();
+ for (const auto& src : m_container->GetSources())
+ {
+ QString guid = QString::fromStdString(src.ToString());
+ QString path = QString::fromStdString(m_container->SourcePath(src).value_or(std::string {}));
+ bool writable = m_container->IsSourceWritable(src);
+ bool uncommitted = m_container->IsSourceUncommitted(src);
+ m_rows.push_back({guid, path, writable, uncommitted});
+ }
+ endResetModel();
+ }
- int rowCount(const QModelIndex &parent = QModelIndex()) const override
- {
- if (parent.isValid()) return 0;
- return static_cast<int>(m_rows.size());
- }
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override
+ {
+ if (parent.isValid())
+ return 0;
+ return static_cast<int>(m_rows.size());
+ }
- int columnCount(const QModelIndex &parent = QModelIndex()) const override
- {
- Q_UNUSED(parent);
- return ColumnCount;
- }
+ int columnCount(const QModelIndex& parent = QModelIndex()) const override
+ {
+ Q_UNUSED(parent);
+ return ColumnCount;
+ }
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const override
- {
- if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
- {
- switch (section)
- {
- case GuidCol: return "Source GUID";
- case PathCol: return "Path";
- case WritableCol: return "Writable";
- case UncommittedCol: return "Uncommitted";
- default: return {};
- }
- }
- return {};
- }
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override
+ {
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ {
+ switch (section)
+ {
+ case GuidCol:
+ return "Source GUID";
+ case PathCol:
+ return "Path";
+ case WritableCol:
+ return "Writable";
+ case UncommittedCol:
+ return "Uncommitted";
+ default:
+ return {};
+ }
+ }
+ return {};
+ }
private:
- struct Row
- {
- QString guid;
- QString path;
- bool writable;
- bool uncommitted;
- };
+ struct Row
+ {
+ QString guid;
+ QString path;
+ bool writable;
+ bool uncommitted;
+ };
- std::vector<Row> m_rows;
- Warp::Ref<Warp::Container> m_container;
+ std::vector<Row> m_rows;
+ Warp::Ref<Warp::Container> m_container;
};
class WarpContainerWidget : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit WarpContainerWidget(Warp::Ref<Warp::Container> container, QWidget *parent = nullptr);
+ explicit WarpContainerWidget(Warp::Ref<Warp::Container> container, QWidget* parent = nullptr);
private:
- Warp::Ref<Warp::Container> m_container;
+ Warp::Ref<Warp::Container> m_container;
- QTabWidget *m_tabs = nullptr;
+ QTabWidget* m_tabs = nullptr;
- // Sources
- QTableView *m_sourcesView = nullptr;
- WarpSourcesModel *m_sourcesModel = nullptr;
- QWidget* m_sourcesPage = nullptr;
- QTimer* m_refreshTimer = nullptr;
+ // Sources
+ QTableView* m_sourcesView = nullptr;
+ WarpSourcesModel* m_sourcesModel = nullptr;
+ QWidget* m_sourcesPage = nullptr;
+ QTimer* m_refreshTimer = nullptr;
- // Search
- WarpSearchWidget *m_searchTab = nullptr;
+ // Search
+ WarpSearchWidget* m_searchTab = nullptr;
};
class WarpContainersPane : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit WarpContainersPane(QWidget *parent = nullptr);
+ explicit WarpContainersPane(QWidget* parent = nullptr);
- void refresh()
- {
- // Clear and repopulate from current container list
- m_list->clear();
- while (m_stack->count() > 0)
- {
- QWidget *w = m_stack->widget(0);
- m_stack->removeWidget(w);
- delete w;
- }
- m_containers.clear();
- populate();
- if (m_list->count() > 0)
- m_list->setCurrentRow(0);
- }
+ void refresh()
+ {
+ // Clear and repopulate from current container list
+ m_list->clear();
+ while (m_stack->count() > 0)
+ {
+ QWidget* w = m_stack->widget(0);
+ m_stack->removeWidget(w);
+ delete w;
+ }
+ m_containers.clear();
+ populate();
+ if (m_list->count() > 0)
+ m_list->setCurrentRow(0);
+ }
private:
- void populate()
- {
- // Retrieve all available containers
- const auto all = Warp::Container::All();
- m_containers = all; // copy vector<Ref<Container>>
+ void populate()
+ {
+ // Retrieve all available containers
+ const auto all = Warp::Container::All();
+ m_containers = all; // copy vector<Ref<Container>>
- for (const auto &c: m_containers)
- {
- const QString name = QString::fromStdString(c->GetName());
- auto *item = new QListWidgetItem(name, m_list);
- item->setSizeHint(QSize(item->sizeHint().width(), itemHeightPx()));
- auto *widget = new WarpContainerWidget(c, m_stack);
- m_stack->addWidget(widget);
- }
+ for (const auto& c : m_containers)
+ {
+ const QString name = QString::fromStdString(c->GetName());
+ auto* item = new QListWidgetItem(name, m_list);
+ item->setSizeHint(QSize(item->sizeHint().width(), itemHeightPx()));
+ auto* widget = new WarpContainerWidget(c, m_stack);
+ m_stack->addWidget(widget);
+ }
- // Visual style: behave like a vertical tab bar
- // m_list->setFrameShape(QFrame::NoFrame);
- // m_list->setSpacing(0);
- }
+ // Visual style: behave like a vertical tab bar
+ // m_list->setFrameShape(QFrame::NoFrame);
+ // m_list->setSpacing(0);
+ }
- static int itemHeightPx()
- {
- // A reasonable, readable height per entry
- return 28;
- }
+ static int itemHeightPx()
+ {
+ // A reasonable, readable height per entry
+ return 28;
+ }
private:
- QListWidget *m_list = nullptr;
- QStackedWidget *m_stack = nullptr;
- std::vector<Warp::Ref<Warp::Container> > m_containers;
+ QListWidget* m_list = nullptr;
+ QStackedWidget* m_stack = nullptr;
+ std::vector<Warp::Ref<Warp::Container>> m_containers;
};
diff --git a/plugins/warp/ui/matched.cpp b/plugins/warp/ui/matched.cpp
index 618c1b4c..aff6779f 100644
--- a/plugins/warp/ui/matched.cpp
+++ b/plugins/warp/ui/matched.cpp
@@ -4,88 +4,85 @@
#include "theme.h"
-const char *WARP_APPLY_ACTIVITY = "analysis.warp.apply";
+const char* WARP_APPLY_ACTIVITY = "analysis.warp.apply";
WarpMatchedWidget::WarpMatchedWidget(BinaryViewRef current)
{
- m_current = current;
- // Create the QT stuff
- QGridLayout *layout = new QGridLayout(this);
- layout->setContentsMargins(2, 2, 2, 2);
- layout->setSpacing(2);
- auto newPalette = palette();
- newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
- setAutoFillBackground(true);
- setPalette(newPalette);
+ m_current = current;
+ // Create the QT stuff
+ QGridLayout* layout = new QGridLayout(this);
+ layout->setContentsMargins(2, 2, 2, 2);
+ layout->setSpacing(2);
+ auto newPalette = palette();
+ newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
+ setAutoFillBackground(true);
+ setPalette(newPalette);
- // TODO: Split horizontally if the widget is displayed in a sidebar that is vertically challenged.
- m_splitter = new QSplitter(Qt::Vertical);
- m_splitter->setContentsMargins(0, 0, 0, 0);
+ // TODO: Split horizontally if the widget is displayed in a sidebar that is vertically challenged.
+ m_splitter = new QSplitter(Qt::Vertical);
+ m_splitter->setContentsMargins(0, 0, 0, 0);
- // Add a widget to display the matches.
- m_tableWidget = new WarpFunctionTableWidget(this);
- m_tableWidget->setContentsMargins(0, 0, 0, 0);
- m_splitter->addWidget(m_tableWidget);
+ // Add a widget to display the matches.
+ m_tableWidget = new WarpFunctionTableWidget(this);
+ m_tableWidget->setContentsMargins(0, 0, 0, 0);
+ m_splitter->addWidget(m_tableWidget);
- // Toggle the applying workflow, this workflow sets all the data for the function based on the matched function data.
- m_tableWidget->RegisterContextMenuAction("Toggle Application",
- [this](WarpFunctionItem *, std::optional<uint64_t> address) {
- if (!address.has_value())
- return;
- for (const auto &func: m_current->GetAnalysisFunctionsForAddress(
- *address))
- {
- const bool previous = BinaryNinja::Settings::Instance()->Get<bool>(
- WARP_APPLY_ACTIVITY, func);
- BinaryNinja::Settings::Instance()->Set(
- WARP_APPLY_ACTIVITY, !previous, func);
- func->Reanalyze();
- }
- });
+ // Toggle the applying workflow, this workflow sets all the data for the function based on the matched function
+ // data.
+ m_tableWidget->RegisterContextMenuAction(
+ "Toggle Application", [this](WarpFunctionItem*, std::optional<uint64_t> address) {
+ if (!address.has_value())
+ return;
+ for (const auto& func : m_current->GetAnalysisFunctionsForAddress(*address))
+ {
+ const bool previous = BinaryNinja::Settings::Instance()->Get<bool>(WARP_APPLY_ACTIVITY, func);
+ BinaryNinja::Settings::Instance()->Set(WARP_APPLY_ACTIVITY, !previous, func);
+ func->Reanalyze();
+ }
+ });
- layout->addWidget(m_splitter, 1, 0, 1, 5);
- setLayout(layout);
+ layout->addWidget(m_splitter, 1, 0, 1, 5);
+ setLayout(layout);
- Update();
+ Update();
- connect(m_tableWidget->GetTableView(), &QTableView::clicked, this,
- [this](const QModelIndex &index) {
- if (m_current == nullptr)
- return;
- if (!index.isValid())
- return;
- const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
- if (!sourceIndex.isValid())
- return;
- auto selectedItem = m_tableWidget->GetModel()->GetAddress(sourceIndex);
- if (!selectedItem.has_value())
- return;
- // Navigate to the address in the view, so the user feels like they are doing something.
- auto currentView = m_current->GetCurrentView();
- m_current->Navigate(currentView, selectedItem.value());
- });
+ connect(m_tableWidget->GetTableView(), &QTableView::clicked, this, [this](const QModelIndex& index) {
+ if (m_current == nullptr)
+ return;
+ if (!index.isValid())
+ return;
+ const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
+ if (!sourceIndex.isValid())
+ return;
+ auto selectedItem = m_tableWidget->GetModel()->GetAddress(sourceIndex);
+ if (!selectedItem.has_value())
+ return;
+ // Navigate to the address in the view, so the user feels like they are doing something.
+ auto currentView = m_current->GetCurrentView();
+ m_current->Navigate(currentView, selectedItem.value());
+ });
}
void WarpMatchedWidget::Update()
{
- m_tableWidget->GetTableView()->setSortingEnabled(false);
- m_tableWidget->GetTableView()->setEnabled(false);
- m_tableWidget->GetProxyModel()->setDynamicSortFilter(false);
- m_tableWidget->GetTableView()->setUpdatesEnabled(false);
- m_tableWidget->GetTableView()->setModel(nullptr);
- m_tableWidget->GetProxyModel()->setSourceModel(nullptr);
- for (const auto &analysisFunction: m_current->GetAnalysisFunctionList())
- {
- if (const auto &matchedFunction = Warp::Function::GetMatched(*analysisFunction))
- {
- uint64_t startAddress = analysisFunction->GetStart();
- m_tableWidget->InsertFunction(startAddress, new WarpFunctionItem(matchedFunction, analysisFunction));
- }
- }
- m_tableWidget->GetTableView()->setModel(m_tableWidget->GetProxyModel());
- m_tableWidget->GetProxyModel()->setSourceModel(m_tableWidget->GetModel());
- m_tableWidget->GetProxyModel()->setDynamicSortFilter(true);
- m_tableWidget->GetTableView()->setEnabled(true);
- m_tableWidget->GetTableView()->setSortingEnabled(true);
- m_tableWidget->GetTableView()->setUpdatesEnabled(true);
+ m_tableWidget->GetTableView()->setSortingEnabled(false);
+ m_tableWidget->GetTableView()->setEnabled(false);
+ m_tableWidget->GetProxyModel()->setDynamicSortFilter(false);
+ m_tableWidget->GetTableView()->setUpdatesEnabled(false);
+ m_tableWidget->GetTableView()->setModel(nullptr);
+ m_tableWidget->GetProxyModel()->setSourceModel(nullptr);
+ for (const auto& analysisFunction : m_current->GetAnalysisFunctionList())
+ {
+ if (const auto& matchedFunction = Warp::Function::GetMatched(*analysisFunction))
+ {
+ uint64_t startAddress = analysisFunction->GetStart();
+ m_tableWidget->InsertFunction(startAddress, new WarpFunctionItem(matchedFunction, analysisFunction));
+ }
+ }
+ m_tableWidget->GetTableView()->setModel(m_tableWidget->GetProxyModel());
+ m_tableWidget->GetProxyModel()->setSourceModel(m_tableWidget->GetModel());
+ m_tableWidget->GetProxyModel()->setDynamicSortFilter(true);
+ m_tableWidget->GetTableView()->setEnabled(true);
+ m_tableWidget->GetTableView()->setSortingEnabled(true);
+ m_tableWidget->GetTableView()->setUpdatesEnabled(true);
}
diff --git a/plugins/warp/ui/matched.h b/plugins/warp/ui/matched.h
index 5e333e25..70c624d5 100644
--- a/plugins/warp/ui/matched.h
+++ b/plugins/warp/ui/matched.h
@@ -6,22 +6,22 @@
class WarpMatchedFunctionTableWidget : public WarpFunctionTableWidget
{
- Q_OBJECT
+ Q_OBJECT
};
class WarpMatchedWidget : public QWidget
{
- Q_OBJECT
- BinaryViewRef m_current;
+ Q_OBJECT
+ BinaryViewRef m_current;
- QSplitter *m_splitter;
+ QSplitter* m_splitter;
- WarpFunctionTableWidget *m_tableWidget;
+ WarpFunctionTableWidget* m_tableWidget;
public:
- explicit WarpMatchedWidget(BinaryViewRef current);
+ explicit WarpMatchedWidget(BinaryViewRef current);
- ~WarpMatchedWidget() override = default;
+ ~WarpMatchedWidget() override = default;
- void Update();
+ void Update();
};
diff --git a/plugins/warp/ui/matches.cpp b/plugins/warp/ui/matches.cpp
index b03d72c6..5ec3da1a 100644
--- a/plugins/warp/ui/matches.cpp
+++ b/plugins/warp/ui/matches.cpp
@@ -13,178 +13,179 @@
WarpCurrentFunctionWidget::WarpCurrentFunctionWidget()
{
- // We must explicitly support no current function.
- m_current = nullptr;
+ // We must explicitly support no current function.
+ m_current = nullptr;
- m_logger = new BinaryNinja::Logger("WARP UI");
+ m_logger = new BinaryNinja::Logger("WARP UI");
- // Create the QT stuff
- QGridLayout *layout = new QGridLayout(this);
- layout->setContentsMargins(2, 2, 2, 2);
- layout->setSpacing(2);
- auto newPalette = palette();
- newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
- setAutoFillBackground(true);
- setPalette(newPalette);
+ // Create the QT stuff
+ QGridLayout* layout = new QGridLayout(this);
+ layout->setContentsMargins(2, 2, 2, 2);
+ layout->setSpacing(2);
+ auto newPalette = palette();
+ newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor));
+ setAutoFillBackground(true);
+ setPalette(newPalette);
- // TODO: Split horizontally if the widget is displayed in a sidebar that is vertically challenged.
- m_splitter = new QSplitter(Qt::Vertical);
- m_splitter->setContentsMargins(0, 0, 0, 0);
+ // TODO: Split horizontally if the widget is displayed in a sidebar that is vertically challenged.
+ m_splitter = new QSplitter(Qt::Vertical);
+ m_splitter->setContentsMargins(0, 0, 0, 0);
- // Add a widget to display the matches.
- m_tableWidget = new WarpFunctionTableWidget(this);
- m_tableWidget->setContentsMargins(0, 0, 0, 0);
- m_splitter->addWidget(m_tableWidget);
+ // Add a widget to display the matches.
+ m_tableWidget = new WarpFunctionTableWidget(this);
+ m_tableWidget->setContentsMargins(0, 0, 0, 0);
+ m_splitter->addWidget(m_tableWidget);
- // Add a widget to display the info about the selected function match.
- m_infoWidget = new WarpFunctionInfoWidget(this);
- m_infoWidget->setContentsMargins(0, 0, 0, 0);
- m_splitter->addWidget(m_infoWidget);
+ // Add a widget to display the info about the selected function match.
+ m_infoWidget = new WarpFunctionInfoWidget(this);
+ m_infoWidget->setContentsMargins(0, 0, 0, 0);
+ m_splitter->addWidget(m_infoWidget);
- layout->addWidget(m_splitter, 1, 0, 1, 5);
- setLayout(layout);
+ layout->addWidget(m_splitter, 1, 0, 1, 5);
+ setLayout(layout);
- m_tableWidget->RegisterContextMenuAction("Apply", [this](WarpFunctionItem *item, std::optional<uint64_t>) {
- if (item == nullptr)
- return;
- Warp::Ref<Warp::Function> selectedFunction = item->GetFunction();
- if (!selectedFunction)
- return;
- selectedFunction->Apply(*m_current);
- // Update analysis so that the selected function shows.
- m_current->GetView()->UpdateAnalysis();
- // So it shows visually as selected.
- m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction);
- });
- m_tableWidget->RegisterContextMenuAction("Search for Source",
- [this](WarpFunctionItem *item, std::optional<uint64_t>) {
- // Apply the source as the filter.
- if (const auto source = item->GetSource(); source)
- m_tableWidget->setFilter(source->ToString());
- });
+ m_tableWidget->RegisterContextMenuAction("Apply", [this](WarpFunctionItem* item, std::optional<uint64_t>) {
+ if (item == nullptr)
+ return;
+ Warp::Ref<Warp::Function> selectedFunction = item->GetFunction();
+ if (!selectedFunction)
+ return;
+ selectedFunction->Apply(*m_current);
+ // Update analysis so that the selected function shows.
+ m_current->GetView()->UpdateAnalysis();
+ // So it shows visually as selected.
+ m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction);
+ });
+ m_tableWidget->RegisterContextMenuAction(
+ "Search for Source", [this](WarpFunctionItem* item, std::optional<uint64_t>) {
+ // Apply the source as the filter.
+ if (const auto source = item->GetSource(); source)
+ m_tableWidget->setFilter(source->ToString());
+ });
- connect(m_tableWidget->GetTableView(), &QTableView::clicked, this,
- [this](const QModelIndex &index) {
- if (m_current == nullptr)
- return;
- if (!index.isValid())
- return;
- const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
- if (!sourceIndex.isValid())
- return;
- auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex);
- // Access the first column in the row
- if (!selectedItem)
- return;
- m_infoWidget->SetFunction(selectedItem->GetFunction());
- m_infoWidget->UpdateInfo();
- });
+ connect(m_tableWidget->GetTableView(), &QTableView::clicked, this, [this](const QModelIndex& index) {
+ if (m_current == nullptr)
+ return;
+ if (!index.isValid())
+ return;
+ const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
+ if (!sourceIndex.isValid())
+ return;
+ auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex);
+ // Access the first column in the row
+ if (!selectedItem)
+ return;
+ m_infoWidget->SetFunction(selectedItem->GetFunction());
+ m_infoWidget->UpdateInfo();
+ });
- connect(m_tableWidget->GetTableView(), &QTableView::doubleClicked, this, [=, this](const QModelIndex &index) {
- if (m_current == nullptr)
- return;
- // Get the selected row for the given index.
- if (!index.isValid())
- return;
- const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
- if (!sourceIndex.isValid())
- return;
- auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex);
- // Access the first column in the row
- if (!selectedItem)
- return;
- Warp::Ref<Warp::Function> selectedFunction = selectedItem->GetFunction();
+ connect(m_tableWidget->GetTableView(), &QTableView::doubleClicked, this, [=, this](const QModelIndex& index) {
+ if (m_current == nullptr)
+ return;
+ // Get the selected row for the given index.
+ if (!index.isValid())
+ return;
+ const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index);
+ if (!sourceIndex.isValid())
+ return;
+ auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex);
+ // Access the first column in the row
+ if (!selectedItem)
+ return;
+ Warp::Ref<Warp::Function> selectedFunction = selectedItem->GetFunction();
- // Actually apply the newly selected function.
- selectedFunction->Apply(*m_current);
+ // Actually apply the newly selected function.
+ selectedFunction->Apply(*m_current);
- // Update analysis so that the selected function shows.
- m_current->GetView()->UpdateAnalysis();
+ // Update analysis so that the selected function shows.
+ m_current->GetView()->UpdateAnalysis();
- // So it shows visually as selected.
- m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction);
- });
+ // So it shows visually as selected.
+ m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction);
+ });
}
void WarpCurrentFunctionWidget::SetFetcher(std::shared_ptr<WarpFetcher> fetcher)
{
- m_fetcher = fetcher;
+ m_fetcher = fetcher;
}
void WarpCurrentFunctionWidget::SetCurrentFunction(FunctionRef current)
{
- if (m_current == current)
- return;
- m_current = current;
- m_infoWidget->SetAnalysisFunction(m_current);
+ if (m_current == current)
+ return;
+ m_current = current;
+ m_infoWidget->SetAnalysisFunction(m_current);
- // If we have a fetcher we should also let it know to try and fetch the possible functions from the containers.
- if (current && m_fetcher)
- {
- m_fetcher->AddPendingFunction(current);
+ // If we have a fetcher we should also let it know to try and fetch the possible functions from the containers.
+ if (current && m_fetcher)
+ {
+ m_fetcher->AddPendingFunction(current);
- // TODO: Automatically fetch the function, I need to figure out how to make this debounce correctly so that all requests are processed in line.
- if (!m_fetcher->m_requestInProgress.exchange(true))
- {
- BinaryNinja::WorkerPriorityEnqueue([this]() {
- BinaryNinja::Ref bgTask = new BinaryNinja::BackgroundTask("Fetching WARP Functions...", true);
- const auto allowedTags = GetAllowedTagsFromView(m_current->GetView());
- m_fetcher->FetchPendingFunctions(allowedTags);
- bgTask->Finish();
- });
- }
- }
+ // TODO: Automatically fetch the function, I need to figure out how to make this debounce correctly so that all
+ // requests are processed in line.
+ if (!m_fetcher->m_requestInProgress.exchange(true))
+ {
+ BinaryNinja::WorkerPriorityEnqueue([this]() {
+ BinaryNinja::Ref bgTask = new BinaryNinja::BackgroundTask("Fetching WARP Functions...", true);
+ const auto allowedTags = GetAllowedTagsFromView(m_current->GetView());
+ m_fetcher->FetchPendingFunctions(allowedTags);
+ bgTask->Finish();
+ });
+ }
+ }
- UpdateMatches();
+ UpdateMatches();
}
void WarpCurrentFunctionWidget::UpdateMatches()
{
- if (!m_current)
- return;
- const auto guid = Warp::GetAnalysisFunctionGUID(*m_current);
- if (!guid.has_value())
- return;
+ if (!m_current)
+ return;
+ const auto guid = Warp::GetAnalysisFunctionGUID(*m_current);
+ if (!guid.has_value())
+ return;
- // Set the matched function for highlighting.
- Warp::Ref<Warp::Function> matchedFunction = Warp::Function::GetMatched(*m_current);
- m_tableWidget->GetModel()->SetMatchedFunction(matchedFunction);
+ // Set the matched function for highlighting.
+ Warp::Ref<Warp::Function> matchedFunction = Warp::Function::GetMatched(*m_current);
+ m_tableWidget->GetModel()->SetMatchedFunction(matchedFunction);
- // We swapped functions, reset the info widget to the default state with new analysis function.
- m_infoWidget->SetFunction(matchedFunction);
- m_infoWidget->UpdateInfo();
+ // We swapped functions, reset the info widget to the default state with new analysis function.
+ m_infoWidget->SetFunction(matchedFunction);
+ m_infoWidget->UpdateInfo();
- Warp::Ref<Warp::Target> target = Warp::Target::FromPlatform(*m_current->GetPlatform());
+ Warp::Ref<Warp::Target> target = Warp::Target::FromPlatform(*m_current->GetPlatform());
- // Add all the possible matches for the current function to the model.
- QVector<WarpFunctionItem *> matches;
- bool matchedFuncAdded = false;
- // TODO: When we add in the networked container we need to update this stuff on a separate thread and show a spinny thing.
- for (const auto &container: Warp::Container::All())
- {
- for (const auto &source: container->GetSourcesWithFunctionGUID(*target, guid.value()))
- {
- for (const auto &function: container->GetFunctionsWithGUID(*target, source, guid.value()))
- {
- // TODO: This does not work.
- if (matchedFunction && BNWARPFunctionsEqual(function->m_object, matchedFunction->m_object))
- matchedFuncAdded = true;
- auto item = new WarpFunctionItem(function, m_current);
- item->SetContainer(container);
- item->SetSource(source);
- matches.emplace_back(item);
- }
- }
- }
+ // Add all the possible matches for the current function to the model.
+ QVector<WarpFunctionItem*> matches;
+ bool matchedFuncAdded = false;
+ // TODO: When we add in the networked container we need to update this stuff on a separate thread and show a spinny
+ // thing.
+ for (const auto& container : Warp::Container::All())
+ {
+ for (const auto& source : container->GetSourcesWithFunctionGUID(*target, guid.value()))
+ {
+ for (const auto& function : container->GetFunctionsWithGUID(*target, source, guid.value()))
+ {
+ // TODO: This does not work.
+ if (matchedFunction && BNWARPFunctionsEqual(function->m_object, matchedFunction->m_object))
+ matchedFuncAdded = true;
+ auto item = new WarpFunctionItem(function, m_current);
+ item->SetContainer(container);
+ item->SetSource(source);
+ matches.emplace_back(item);
+ }
+ }
+ }
- // Add the matched function unconditionally, assuming it has not been found in a container.
- // NOTE: This happens when you load from a database for example.
- if (matchedFunction && !matchedFuncAdded)
- {
- auto item = new WarpFunctionItem(matchedFunction, m_current);
- matches.emplace_back(item);
- }
+ // Add the matched function unconditionally, assuming it has not been found in a container.
+ // NOTE: This happens when you load from a database for example.
+ if (matchedFunction && !matchedFuncAdded)
+ {
+ auto item = new WarpFunctionItem(matchedFunction, m_current);
+ matches.emplace_back(item);
+ }
- m_tableWidget->SetFunctions(matches);
+ m_tableWidget->SetFunctions(matches);
}
diff --git a/plugins/warp/ui/matches.h b/plugins/warp/ui/matches.h
index 88926add..6a2061ef 100644
--- a/plugins/warp/ui/matches.h
+++ b/plugins/warp/ui/matches.h
@@ -9,28 +9,28 @@
class WarpCurrentFunctionWidget : public QWidget
{
- Q_OBJECT
- FunctionRef m_current;
+ Q_OBJECT
+ FunctionRef m_current;
- QSplitter *m_splitter;
+ QSplitter* m_splitter;
- WarpFunctionTableWidget *m_tableWidget;
- WarpFunctionInfoWidget *m_infoWidget;
+ WarpFunctionTableWidget* m_tableWidget;
+ WarpFunctionInfoWidget* m_infoWidget;
- LoggerRef m_logger;
+ LoggerRef m_logger;
- std::shared_ptr<WarpFetcher> m_fetcher;
+ std::shared_ptr<WarpFetcher> m_fetcher;
public:
- explicit WarpCurrentFunctionWidget();
+ explicit WarpCurrentFunctionWidget();
- ~WarpCurrentFunctionWidget() override = default;
+ ~WarpCurrentFunctionWidget() override = default;
- void SetFetcher(std::shared_ptr<WarpFetcher> fetcher);
+ void SetFetcher(std::shared_ptr<WarpFetcher> fetcher);
- void SetCurrentFunction(FunctionRef current);
+ void SetCurrentFunction(FunctionRef current);
- FunctionRef GetCurrentFunction() { return m_current; };
+ FunctionRef GetCurrentFunction() { return m_current; };
- void UpdateMatches();
+ void UpdateMatches();
};
diff --git a/plugins/warp/ui/plugin.cpp b/plugins/warp/ui/plugin.cpp
index b1cc9a5b..e8088d7c 100644
--- a/plugins/warp/ui/plugin.cpp
+++ b/plugins/warp/ui/plugin.cpp
@@ -10,7 +10,7 @@
using namespace BinaryNinja;
-QIcon GetColoredIcon(const QString &iconPath, const QColor &color)
+QIcon GetColoredIcon(const QString& iconPath, const QColor& color)
{
auto pixmap = QPixmap(iconPath);
auto mask = pixmap.createMaskFromColor(QColor(0, 0, 0), Qt::MaskInColor);
@@ -24,7 +24,7 @@ Ref<BackgroundTask> GetMatcherTask()
// TODO: What happens if we have multiple views open matching? This fails.
// Look for the matcher background task to determine if we are stopping or starting it.
Ref<BackgroundTask> matcherTask = nullptr;
- for (const auto &task: BackgroundTask::GetRunningTasks())
+ for (const auto& task : BackgroundTask::GetRunningTasks())
{
std::string progressText = task->GetProgressText();
if (progressText.find("Matching on WARP") != std::string::npos)
@@ -35,22 +35,29 @@ Ref<BackgroundTask> GetMatcherTask()
void ShowNetworkNotice()
{
- // By default, network access is disabled for WARP, this function will show the user a notice to enable it and restart.
+ // By default, network access is disabled for WARP, this function will show the user a notice to enable it and
+ // restart.
const auto settings = Settings::Instance();
const bool networkNoticeShown = QSettings().value("warp/NetworkNoticeShown", false).toBool();
QSettings().setValue("warp/NetworkNoticeShown", true);
if (!networkNoticeShown && settings->Contains("network.enableWARP") && !settings->Get<bool>("network.enableWARP"))
{
- const bool enable = ShowMessageBox("Enable WARP Network Access?",
- "Network access is disabled by default. Enable WARP network features now?\n\n"
- "You can change this later in Settings.",
- YesNoButtonSet, InformationIcon) == YesButton;
+ const bool enable =
+ ShowMessageBox("Enable WARP Network Access?",
+ "Network access is disabled by default. Enable WARP network features now?\n\n"
+ "You can change this later in Settings.",
+ YesNoButtonSet, InformationIcon)
+ == YesButton;
settings->Set("network.enableWARP", enable);
// TODO: Add a notifyRestartRequired call here
if (enable)
- ShowMessageBox("WARP Network Enabled", "Please restart Binary Ninja to allow WARP to make requests to the server.", OKButtonSet, InformationIcon);
+ ShowMessageBox("WARP Network Enabled",
+ "Please restart Binary Ninja to allow WARP to make requests to the server.", OKButtonSet,
+ InformationIcon);
else
- ShowMessageBox("WARP Network Disabled", "WARP network access will remain disabled. You can enable it later from Settings.", OKButtonSet, InformationIcon);
+ ShowMessageBox("WARP Network Disabled",
+ "WARP network access will remain disabled. You can enable it later from Settings.", OKButtonSet,
+ InformationIcon);
}
}
@@ -63,24 +70,24 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
ShowNetworkNotice();
m_headerWidget = new QWidget();
- QHBoxLayout *headerLayout = new QHBoxLayout();
+ QHBoxLayout* headerLayout = new QHBoxLayout();
headerLayout->setContentsMargins(0, 0, 0, 0);
headerLayout->setSpacing(0);
- QToolBar *headerToolbar = new QToolBar(this);
+ QToolBar* headerToolbar = new QToolBar(this);
headerToolbar->setContentsMargins(0, 0, 0, 0);
headerToolbar->setIconSize(QSize(20, 20));
auto fetchIcon = GetColoredIcon(":/icons/images/arrow-pull.png", getThemeColor(BlueStandardHighlightColor));
auto fetchAction = headerToolbar->addAction(fetchIcon, "Fetch data from WARP containers", [this]() {
- UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ UIActionHandler* handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
handler->executeAction("WARP\\Fetch");
});
fetchAction->setToolTip("Fetch data from WARP containers");
auto commitIcon = GetColoredIcon(":/icons/images/arrow-push.png", getThemeColor(BlueStandardHighlightColor));
auto commitAction = headerToolbar->addAction(commitIcon, "Commit a WARP file to a source", [this]() {
- UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ UIActionHandler* handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
handler->executeAction("WARP\\Commit File");
});
commitAction->setToolTip("Commit a WARP file to a source");
@@ -90,14 +97,14 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
auto loadIcon = GetColoredIcon(":/icons/images/file-add.png", getThemeColor(BlueStandardHighlightColor));
auto loadAction = headerToolbar->addAction(loadIcon, "Load Signature File", [this]() {
- UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ UIActionHandler* handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
handler->executeAction("WARP\\Load File");
});
loadAction->setToolTip("Load a signature file to match against");
auto saveIcon = GetColoredIcon(":/icons/images/edit.png", getThemeColor(BlueStandardHighlightColor));
auto saveAction = headerToolbar->addAction(saveIcon, "Create Signature File", [this]() {
- UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ UIActionHandler* handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
handler->executeAction("WARP\\Create\\From Current View");
});
saveAction->setToolTip("Save data to a signature file");
@@ -105,10 +112,10 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
headerToolbar->addSeparator();
static auto matcherStopIcon = GetColoredIcon(":/icons/images/stop.png", getThemeColor(RedStandardHighlightColor));
- static auto matcherStartIcon = GetColoredIcon(":/icons/images/start.png",
- getThemeColor(GreenStandardHighlightColor));
+ static auto matcherStartIcon =
+ GetColoredIcon(":/icons/images/start.png", getThemeColor(GreenStandardHighlightColor));
m_matcherAction = headerToolbar->addAction(matcherStartIcon, "Run Matcher", [this]() {
- UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ UIActionHandler* handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
if (Ref<BackgroundTask> matcherTask = GetMatcherTask())
matcherTask->Cancel();
else if (!isMatcherRunning)
@@ -120,9 +127,7 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
m_matcherAction->setToolTip("Run the matcher on all functions");
auto refreshIcon = GetColoredIcon(":/icons/images/refresh.png", getThemeColor(BlueStandardHighlightColor));
- auto refreshAction = headerToolbar->addAction(refreshIcon, "Refresh the view data", [this]() {
- Update();
- });
+ auto refreshAction = headerToolbar->addAction(refreshIcon, "Refresh the view data", [this]() { Update(); });
refreshAction->setToolTip("Refresh the sidebar data");
// Push the toolbar to the right using a stretch space.
@@ -130,31 +135,31 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
headerLayout->addWidget(headerToolbar, 0);
m_headerWidget->setLayout(headerLayout);
- QFrame *currentFunctionFrame = new QFrame(this);
+ QFrame* currentFunctionFrame = new QFrame(this);
m_currentFunctionWidget = new WarpCurrentFunctionWidget();
- QVBoxLayout *currentFunctionLayout = new QVBoxLayout();
+ QVBoxLayout* currentFunctionLayout = new QVBoxLayout();
currentFunctionLayout->setContentsMargins(0, 0, 0, 0);
currentFunctionLayout->setSpacing(0);
currentFunctionLayout->addWidget(m_currentFunctionWidget);
currentFunctionFrame->setLayout(currentFunctionLayout);
- QFrame *matchedFrame = new QFrame(this);
+ QFrame* matchedFrame = new QFrame(this);
m_matchedWidget = new WarpMatchedWidget(m_data);
- QVBoxLayout *matchedLayout = new QVBoxLayout();
+ QVBoxLayout* matchedLayout = new QVBoxLayout();
matchedLayout->setContentsMargins(0, 0, 0, 0);
matchedLayout->setSpacing(0);
matchedLayout->addWidget(m_matchedWidget);
matchedFrame->setLayout(matchedLayout);
- QFrame *containerFrame = new QFrame(this);
+ QFrame* containerFrame = new QFrame(this);
m_containerWidget = new WarpContainersPane();
- QVBoxLayout *containerLayout = new QVBoxLayout();
+ QVBoxLayout* containerLayout = new QVBoxLayout();
containerLayout->setContentsMargins(0, 0, 0, 0);
containerLayout->setSpacing(0);
containerLayout->addWidget(m_containerWidget);
containerFrame->setLayout(containerLayout);
- QVBoxLayout *layout = new QVBoxLayout(this);
+ QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
@@ -167,11 +172,7 @@ WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP")
this->setLayout(layout);
// Do a full update if analysis has been done, otherwise we may persist old data and not have new data.
- m_analysisEvent = new AnalysisCompletionEvent(m_data, [this]() {
- ExecuteOnMainThread([this]() {
- Update();
- });
- });
+ m_analysisEvent = new AnalysisCompletionEvent(m_data, [this]() { ExecuteOnMainThread([this]() { Update(); }); });
const std::shared_ptr<WarpFetcher> fetcher = WarpFetcher::Global();
fetcher->AddCompletionCallback([this]() {
@@ -188,9 +189,7 @@ WarpSidebarWidget::~WarpSidebarWidget()
m_analysisEvent->Cancel();
}
-void WarpSidebarWidget::focus()
-{
-}
+void WarpSidebarWidget::focus() {}
void WarpSidebarWidget::Update()
{
@@ -203,15 +202,16 @@ void WarpSidebarWidget::Update()
void WarpSidebarWidget::setMatcherActionIcon(bool running)
{
static auto matcherStopIcon = GetColoredIcon(":/icons/images/stop.png", getThemeColor(RedStandardHighlightColor));
- static auto matcherStartIcon = GetColoredIcon(":/icons/images/start.png",
- getThemeColor(GreenStandardHighlightColor));
+ static auto matcherStartIcon =
+ GetColoredIcon(":/icons/images/start.png", getThemeColor(GreenStandardHighlightColor));
isMatcherRunning = running;
if (running)
{
m_matcherAction->setIcon(matcherStopIcon);
m_matcherAction->setToolTip("Stop the matcher");
m_matcherAction->setIconText("Stop Matcher");
- } else
+ }
+ else
{
m_matcherAction->setIcon(matcherStartIcon);
m_matcherAction->setToolTip("Run the matcher on all functions");
@@ -219,7 +219,7 @@ void WarpSidebarWidget::setMatcherActionIcon(bool running)
}
}
-void WarpSidebarWidget::notifyViewChanged(ViewFrame *view)
+void WarpSidebarWidget::notifyViewChanged(ViewFrame* view)
{
if (!view)
return;
@@ -230,7 +230,7 @@ void WarpSidebarWidget::notifyViewChanged(ViewFrame *view)
// TODO: We need to set some stuff here prolly.
}
-void WarpSidebarWidget::notifyViewLocationChanged(View *view, const ViewLocation &location)
+void WarpSidebarWidget::notifyViewLocationChanged(View* view, const ViewLocation& location)
{
// Warp sidebar really should only update if it is visible, otherwise its a waste of cycles.
if (!this->isVisible())
@@ -241,25 +241,23 @@ void WarpSidebarWidget::notifyViewLocationChanged(View *view, const ViewLocation
m_currentFunctionWidget->SetCurrentFunction(function);
}
-WarpSidebarWidgetType::WarpSidebarWidgetType() : SidebarWidgetType(QImage(":/icons/images/warp.png"), "WARP")
-{
-
-}
-
+WarpSidebarWidgetType::WarpSidebarWidgetType() : SidebarWidgetType(QImage(":/icons/images/warp.png"), "WARP") {}
-extern "C" {
-BN_DECLARE_UI_ABI_VERSION
-BINARYNINJAPLUGIN void CorePluginDependencies()
+extern "C"
{
- // We must have WARP to enable this plugin!
- AddRequiredPluginDependency("warp_ninja");
-}
+ BN_DECLARE_UI_ABI_VERSION
-BINARYNINJAPLUGIN bool UIPluginInit()
-{
- RegisterWarpFetchFunctionsCommand();
- Sidebar::addSidebarWidgetType(new WarpSidebarWidgetType());
- return true;
-}
+ BINARYNINJAPLUGIN void CorePluginDependencies()
+ {
+ // We must have WARP to enable this plugin!
+ AddRequiredPluginDependency("warp_ninja");
+ }
+
+ BINARYNINJAPLUGIN bool UIPluginInit()
+ {
+ RegisterWarpFetchFunctionsCommand();
+ Sidebar::addSidebarWidgetType(new WarpSidebarWidgetType());
+ return true;
+ }
}
diff --git a/plugins/warp/ui/plugin.h b/plugins/warp/ui/plugin.h
index 56b31711..7f406e19 100644
--- a/plugins/warp/ui/plugin.h
+++ b/plugins/warp/ui/plugin.h
@@ -8,48 +8,48 @@
class WarpSidebarWidget : public SidebarWidget
{
- Q_OBJECT
- BinaryNinja::Ref<BinaryNinja::Logger> m_logger;
- BinaryViewRef m_data;
- ViewFrame *m_currentFrame;
- QWidget *m_headerWidget;
+ Q_OBJECT
+ BinaryNinja::Ref<BinaryNinja::Logger> m_logger;
+ BinaryViewRef m_data;
+ ViewFrame* m_currentFrame;
+ QWidget* m_headerWidget;
- BinaryNinja::Ref<BinaryNinja::AnalysisCompletionEvent> m_analysisEvent;
- QAction *m_matcherAction;
- bool isMatcherRunning = false;
+ BinaryNinja::Ref<BinaryNinja::AnalysisCompletionEvent> m_analysisEvent;
+ QAction* m_matcherAction;
+ bool isMatcherRunning = false;
- WarpCurrentFunctionWidget *m_currentFunctionWidget;
- WarpMatchedWidget *m_matchedWidget;
- WarpContainersPane *m_containerWidget;
+ WarpCurrentFunctionWidget* m_currentFunctionWidget;
+ WarpMatchedWidget* m_matchedWidget;
+ WarpContainersPane* m_containerWidget;
public:
- explicit WarpSidebarWidget(BinaryViewRef data);
+ explicit WarpSidebarWidget(BinaryViewRef data);
- ~WarpSidebarWidget() override;
+ ~WarpSidebarWidget() override;
- QWidget *headerWidget() override { return m_headerWidget; }
+ QWidget* headerWidget() override { return m_headerWidget; }
- void focus() override;
+ void focus() override;
- void Update();
+ void Update();
- void setMatcherActionIcon(bool running);
+ void setMatcherActionIcon(bool running);
- void notifyViewChanged(ViewFrame *) override;
+ void notifyViewChanged(ViewFrame*) override;
- void notifyViewLocationChanged(View *, const ViewLocation &) override;
+ void notifyViewLocationChanged(View*, const ViewLocation&) override;
};
class WarpSidebarWidgetType : public SidebarWidgetType
{
public:
- WarpSidebarWidgetType();
+ WarpSidebarWidgetType();
- SidebarWidgetLocation defaultLocation() const override { return SidebarWidgetLocation::RightContent; }
- SidebarContextSensitivity contextSensitivity() const override { return PerViewTypeSidebarContext; }
+ SidebarWidgetLocation defaultLocation() const override { return SidebarWidgetLocation::RightContent; }
+ SidebarContextSensitivity contextSensitivity() const override { return PerViewTypeSidebarContext; }
- WarpSidebarWidget *createWidget(ViewFrame *viewFrame, BinaryViewRef data) override
- {
- return new WarpSidebarWidget(data);
- }
+ WarpSidebarWidget* createWidget(ViewFrame* viewFrame, BinaryViewRef data) override
+ {
+ return new WarpSidebarWidget(data);
+ }
};
diff --git a/plugins/warp/ui/shared/constraint.cpp b/plugins/warp/ui/shared/constraint.cpp
index c871fc68..39c9c7d3 100644
--- a/plugins/warp/ui/shared/constraint.cpp
+++ b/plugins/warp/ui/shared/constraint.cpp
@@ -5,127 +5,127 @@
#include "theme.h"
-WarpConstraintItem::WarpConstraintItem(const Warp::Constraint &constraint) : m_constraint(constraint)
+WarpConstraintItem::WarpConstraintItem(const Warp::Constraint& constraint) : m_constraint(constraint)
{
- QString guidStr = QString::fromStdString(constraint.guid.ToString());
- if (const auto offset = constraint.offset; offset)
- guidStr += QString(" @ %1").arg(*offset, 0, 16);
- setText(guidStr);
+ QString guidStr = QString::fromStdString(constraint.guid.ToString());
+ if (const auto offset = constraint.offset; offset)
+ guidStr += QString(" @ %1").arg(*offset, 0, 16);
+ setText(guidStr);
}
-WarpConstraintItemModel::WarpConstraintItemModel(const QStringList &labels, QObject *parent)
+WarpConstraintItemModel::WarpConstraintItemModel(const QStringList& labels, QObject* parent)
{
- this->setHorizontalHeaderLabels(labels);
+ this->setHorizontalHeaderLabels(labels);
}
-void WarpConstraintItemModel::AddItem(WarpConstraintItem *item)
+void WarpConstraintItemModel::AddItem(WarpConstraintItem* item)
{
- QList<QStandardItem *> row = {};
- row.insert(COL_CONSTRAINT_ITEM, item);
- appendRow(row);
+ QList<QStandardItem*> row = {};
+ row.insert(COL_CONSTRAINT_ITEM, item);
+ appendRow(row);
}
-WarpConstraintItem *WarpConstraintItemModel::GetItem(const QModelIndex &index) const
+WarpConstraintItem* WarpConstraintItemModel::GetItem(const QModelIndex& index) const
{
- if (!index.isValid())
- return nullptr;
- return dynamic_cast<WarpConstraintItem *>(item(index.row(), COL_CONSTRAINT_ITEM));
+ if (!index.isValid())
+ return nullptr;
+ return dynamic_cast<WarpConstraintItem*>(item(index.row(), COL_CONSTRAINT_ITEM));
}
-QVariant WarpConstraintItemModel::data(const QModelIndex &index, int role) const
+QVariant WarpConstraintItemModel::data(const QModelIndex& index, int role) const
{
- // Highlight constraints that are found in analysis.
- if (role == Qt::BackgroundRole)
- {
- if (const auto item = GetItem(index); item)
- {
- auto itemConstraint = item->GetConstraint();
- // TODO: We really should store the guid in a hashmap or something instead of looping over it for every item.
- for (const auto &constraint: m_matchedConstraints)
- {
- if (constraint.guid == itemConstraint.guid)
- {
- static QColor matchedColor = getThemeColor(GreenStandardHighlightColor);
- matchedColor.setAlpha(100);
- if (constraint.offset == itemConstraint.offset)
- matchedColor.setAlpha(128);
- return matchedColor;
- }
- }
- }
- }
+ // Highlight constraints that are found in analysis.
+ if (role == Qt::BackgroundRole)
+ {
+ if (const auto item = GetItem(index); item)
+ {
+ auto itemConstraint = item->GetConstraint();
+ // TODO: We really should store the guid in a hashmap or something instead of looping over it for every
+ // item.
+ for (const auto& constraint : m_matchedConstraints)
+ {
+ if (constraint.guid == itemConstraint.guid)
+ {
+ static QColor matchedColor = getThemeColor(GreenStandardHighlightColor);
+ matchedColor.setAlpha(100);
+ if (constraint.offset == itemConstraint.offset)
+ matchedColor.setAlpha(128);
+ return matchedColor;
+ }
+ }
+ }
+ }
- return QStandardItemModel::data(index, role);
+ return QStandardItemModel::data(index, role);
}
-WarpConstraintTableWidget::WarpConstraintTableWidget(QWidget *parent)
+WarpConstraintTableWidget::WarpConstraintTableWidget(QWidget* parent)
{
- QGridLayout *layout = new QGridLayout(this);
- layout->setContentsMargins(2, 2, 2, 2);
- layout->setVerticalSpacing(4);
+ QGridLayout* layout = new QGridLayout(this);
+ layout->setContentsMargins(2, 2, 2, 2);
+ layout->setVerticalSpacing(4);
- m_table = new QTableView(this);
- m_model = new WarpConstraintItemModel({"Constraint"}, this);
- m_proxyModel = new GenericTextFilterModel(this);
- m_proxyModel->setSourceModel(m_model);
- m_table->setModel(m_proxyModel);
+ m_table = new QTableView(this);
+ m_model = new WarpConstraintItemModel({"Constraint"}, this);
+ m_proxyModel = new GenericTextFilterModel(this);
+ m_proxyModel->setSourceModel(m_model);
+ m_table->setModel(m_proxyModel);
- m_filterEdit = new FilterEdit(this);
- m_filterView = new FilteredView(this, m_table, this, m_filterEdit);
- m_filterView->setFilterPlaceholderText("Search constraints");
+ m_filterEdit = new FilterEdit(this);
+ m_filterView = new FilteredView(this, m_table, this, m_filterEdit);
+ m_filterView->setFilterPlaceholderText("Search constraints");
- layout->addWidget(m_filterEdit, 0, 0, 1, 5);
- layout->addWidget(m_table, 1, 0, 1, 5);
+ layout->addWidget(m_filterEdit, 0, 0, 1, 5);
+ layout->addWidget(m_table, 1, 0, 1, 5);
- // Make the table look nice.
- m_table->horizontalHeader()->setStretchLastSection(true);
- m_table->verticalHeader()->hide();
- m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_table->setSelectionMode(QAbstractItemView::SingleSelection);
- m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_table->setFocusPolicy(Qt::NoFocus);
- m_table->setShowGrid(false);
- m_table->setAlternatingRowColors(false);
- m_table->setSortingEnabled(true);
- // NOTE: We only have a single column right now, so disable the header.
- m_table->horizontalHeader()->hide();
- // Decrease row height to make it look nice.
- m_table->verticalHeader()->setDefaultSectionSize(30);
+ // Make the table look nice.
+ m_table->horizontalHeader()->setStretchLastSection(true);
+ m_table->verticalHeader()->hide();
+ m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_table->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_table->setFocusPolicy(Qt::NoFocus);
+ m_table->setShowGrid(false);
+ m_table->setAlternatingRowColors(false);
+ m_table->setSortingEnabled(true);
+ // NOTE: We only have a single column right now, so disable the header.
+ m_table->horizontalHeader()->hide();
+ // Decrease row height to make it look nice.
+ m_table->verticalHeader()->setDefaultSectionSize(30);
- // Make the highlight less bright.
- QPalette palette = m_table->palette();
- palette.setColor(QPalette::Highlight, getThemeColor(SelectionColor));
- m_table->setPalette(palette);
+ // Make the highlight less bright.
+ QPalette palette = m_table->palette();
+ palette.setColor(QPalette::Highlight, getThemeColor(SelectionColor));
+ m_table->setPalette(palette);
}
-void WarpConstraintTableWidget::SetConstraints(QVector<WarpConstraintItem *> constraints)
+void WarpConstraintTableWidget::SetConstraints(QVector<WarpConstraintItem*> constraints)
{
- // Clear matches as they are no longer valid.
- m_model->clear();
- m_model->setRowCount(0);
+ // Clear matches as they are no longer valid.
+ m_model->clear();
+ m_model->setRowCount(0);
- // Temporarily disable sorting so we can add rows faster
- m_table->setModel(m_model);
- m_table->setSortingEnabled(false);
- m_table->setEnabled(false);
+ // Temporarily disable sorting so we can add rows faster
+ m_table->setModel(m_model);
+ m_table->setSortingEnabled(false);
+ m_table->setEnabled(false);
- for (const auto &constraint: constraints)
- m_model->AddItem(constraint);
+ for (const auto& constraint : constraints)
+ m_model->AddItem(constraint);
- // We are done, re-enable table.
- m_table->setEnabled(true);
- m_table->setModel(m_proxyModel);
- m_table->setSortingEnabled(true);
+ // We are done, re-enable table.
+ m_table->setEnabled(true);
+ m_table->setModel(m_proxyModel);
+ m_table->setSortingEnabled(true);
}
-void WarpConstraintTableWidget::SetMatchedConstraints(
- const std::vector<Warp::Constraint> &analysisConstraints)
+void WarpConstraintTableWidget::SetMatchedConstraints(const std::vector<Warp::Constraint>& analysisConstraints)
{
- m_model->SetMatchedConstraints(analysisConstraints);
+ m_model->SetMatchedConstraints(analysisConstraints);
}
-void WarpConstraintTableWidget::setFilter(const std::string &filter)
+void WarpConstraintTableWidget::setFilter(const std::string& filter)
{
- m_proxyModel->setFilterFixedString(QString::fromStdString(filter));
- m_filterView->showFilter(QString::fromStdString(filter));
+ m_proxyModel->setFilterFixedString(QString::fromStdString(filter));
+ m_filterView->showFilter(QString::fromStdString(filter));
}
diff --git a/plugins/warp/ui/shared/constraint.h b/plugins/warp/ui/shared/constraint.h
index 2f064836..edee36e5 100644
--- a/plugins/warp/ui/shared/constraint.h
+++ b/plugins/warp/ui/shared/constraint.h
@@ -9,70 +9,62 @@
class WarpConstraintItem : public QStandardItem
{
- Warp::Constraint m_constraint;
+ Warp::Constraint m_constraint;
public:
- WarpConstraintItem(const Warp::Constraint &constraint);
+ WarpConstraintItem(const Warp::Constraint& constraint);
- Warp::Constraint GetConstraint() { return m_constraint; }
+ Warp::Constraint GetConstraint() { return m_constraint; }
};
class WarpConstraintItemModel : public QStandardItemModel
{
- Q_OBJECT
+ Q_OBJECT
- // The current analysis constraints used to highlight matching constraints.
- std::vector<Warp::Constraint> m_matchedConstraints;
+ // The current analysis constraints used to highlight matching constraints.
+ std::vector<Warp::Constraint> m_matchedConstraints;
public:
- WarpConstraintItemModel(const QStringList &labels, QObject *parent);
+ WarpConstraintItemModel(const QStringList& labels, QObject* parent);
- static constexpr int COL_CONSTRAINT_ITEM = 0;
+ static constexpr int COL_CONSTRAINT_ITEM = 0;
- void AddItem(WarpConstraintItem *item);
+ void AddItem(WarpConstraintItem* item);
- WarpConstraintItem *GetItem(const QModelIndex &index) const;
+ WarpConstraintItem* GetItem(const QModelIndex& index) const;
- QVariant data(const QModelIndex &index, int role) const override;
+ QVariant data(const QModelIndex& index, int role) const override;
- void SetMatchedConstraints(const std::vector<Warp::Constraint> &analysisConstraints)
- {
- m_matchedConstraints = analysisConstraints;
- }
+ void SetMatchedConstraints(const std::vector<Warp::Constraint>& analysisConstraints)
+ {
+ m_matchedConstraints = analysisConstraints;
+ }
};
class WarpConstraintTableWidget : public QWidget, public FilterTarget
{
- Q_OBJECT
+ Q_OBJECT
- QTableView *m_table;
- WarpConstraintItemModel *m_model;
- GenericTextFilterModel *m_proxyModel;
- FilterEdit *m_filterEdit;
- FilteredView *m_filterView;
+ QTableView* m_table;
+ WarpConstraintItemModel* m_model;
+ GenericTextFilterModel* m_proxyModel;
+ FilterEdit* m_filterEdit;
+ FilteredView* m_filterView;
public:
- explicit WarpConstraintTableWidget(QWidget *parent = nullptr);
+ explicit WarpConstraintTableWidget(QWidget* parent = nullptr);
- void SetConstraints(QVector<WarpConstraintItem *> constraints);
+ void SetConstraints(QVector<WarpConstraintItem*> constraints);
- void SetMatchedConstraints(const std::vector<Warp::Constraint> &analysisConstraints);
+ void SetMatchedConstraints(const std::vector<Warp::Constraint>& analysisConstraints);
- void setFilter(const std::string &) override;
+ void setFilter(const std::string&) override;
- void scrollToFirstItem() override
- {
- }
+ void scrollToFirstItem() override {}
- void scrollToCurrentItem() override
- {
- }
+ void scrollToCurrentItem() override {}
- void selectFirstItem() override
- {
- }
+ void selectFirstItem() override {}
- void activateFirstItem() override
- {
- }
+ void activateFirstItem() override {}
};
diff --git a/plugins/warp/ui/shared/fetchdialog.cpp b/plugins/warp/ui/shared/fetchdialog.cpp
index 1d18aa92..328f00c2 100644
--- a/plugins/warp/ui/shared/fetchdialog.cpp
+++ b/plugins/warp/ui/shared/fetchdialog.cpp
@@ -11,236 +11,231 @@
using namespace BinaryNinja;
-static void AddListItem(QListWidget *list, const QString &value)
+static void AddListItem(QListWidget* list, const QString& value)
{
- if (value.trimmed().isEmpty())
- return;
- // Avoid duplicates
- for (int i = 0; i < list->count(); ++i)
- if (list->item(i)->text().compare(value, Qt::CaseInsensitive) == 0)
- return;
- list->addItem(value.trimmed());
+ if (value.trimmed().isEmpty())
+ return;
+ // Avoid duplicates
+ for (int i = 0; i < list->count(); ++i)
+ if (list->item(i)->text().compare(value, Qt::CaseInsensitive) == 0)
+ return;
+ list->addItem(value.trimmed());
}
-WarpFetchDialog::WarpFetchDialog(BinaryViewRef bv,
- std::shared_ptr<WarpFetcher> fetcher,
- QWidget *parent)
- : QDialog(parent), m_fetchProcessor(std::move(fetcher)), m_bv(std::move(bv))
+WarpFetchDialog::WarpFetchDialog(BinaryViewRef bv, std::shared_ptr<WarpFetcher> fetcher, QWidget* parent) :
+ QDialog(parent), m_fetchProcessor(std::move(fetcher)), m_bv(std::move(bv))
{
- setWindowTitle("Fetch WARP Functions");
+ setWindowTitle("Fetch WARP Functions");
- auto form = new QFormLayout();
- m_containerCombo = new QComboBox(this);
- populateContainers();
- m_containerCombo->addItem("All Containers"); // index 0 for "all"
- for (const auto &c: m_containers)
- m_containerCombo->addItem(QString::fromStdString(c->GetName()));
+ auto form = new QFormLayout();
+ m_containerCombo = new QComboBox(this);
+ populateContainers();
+ m_containerCombo->addItem("All Containers"); // index 0 for "all"
+ for (const auto& c : m_containers)
+ m_containerCombo->addItem(QString::fromStdString(c->GetName()));
- // Tags editor
- m_tagsList = new QListWidget(this);
- m_addTagBtn = new QPushButton(this);
- m_addTagBtn->setText("+");
- m_addTagBtn->setToolTip("Add tag");
- m_removeTagBtn = new QPushButton(this);
- m_removeTagBtn->setText("-");
- m_removeTagBtn->setToolTip("Remove selected tag(s)");
- m_resetTagBtn = new QPushButton(this);
- m_resetTagBtn->setText("Reset");
- m_resetTagBtn->setToolTip("Reset tags to: official, trusted");
- auto tagBtnRow = new QHBoxLayout();
- tagBtnRow->addWidget(m_addTagBtn);
- tagBtnRow->addWidget(m_removeTagBtn);
- tagBtnRow->addWidget(m_resetTagBtn);
- tagBtnRow->addStretch();
- auto tagCol = new QVBoxLayout();
- tagCol->addWidget(m_tagsList);
- tagCol->addLayout(tagBtnRow);
- auto tagWrapper = new QWidget(this);
- tagWrapper->setLayout(tagCol);
+ // Tags editor
+ m_tagsList = new QListWidget(this);
+ m_addTagBtn = new QPushButton(this);
+ m_addTagBtn->setText("+");
+ m_addTagBtn->setToolTip("Add tag");
+ m_removeTagBtn = new QPushButton(this);
+ m_removeTagBtn->setText("-");
+ m_removeTagBtn->setToolTip("Remove selected tag(s)");
+ m_resetTagBtn = new QPushButton(this);
+ m_resetTagBtn->setText("Reset");
+ m_resetTagBtn->setToolTip("Reset tags to: official, trusted");
+ auto tagBtnRow = new QHBoxLayout();
+ tagBtnRow->addWidget(m_addTagBtn);
+ tagBtnRow->addWidget(m_removeTagBtn);
+ tagBtnRow->addWidget(m_resetTagBtn);
+ tagBtnRow->addStretch();
+ auto tagCol = new QVBoxLayout();
+ tagCol->addWidget(m_tagsList);
+ tagCol->addLayout(tagBtnRow);
+ auto tagWrapper = new QWidget(this);
+ tagWrapper->setLayout(tagCol);
- // Make tags list compact with a fixed maximum height and no vertical expansion
- m_tagsList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
- m_tagsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- m_tagsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- m_tagsList->setMaximumHeight(120);
- m_tagsList->setToolTip("A source must have atleast ONE of these tags to be considered");
+ // Make tags list compact with a fixed maximum height and no vertical expansion
+ m_tagsList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+ m_tagsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ m_tagsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ m_tagsList->setMaximumHeight(120);
+ m_tagsList->setToolTip("A source must have atleast ONE of these tags to be considered");
- // Defaults from processor tags
- for (const auto &t: GetAllowedTagsFromView(m_bv))
- AddListItem(m_tagsList, QString::fromStdString(t));
+ // Defaults from processor tags
+ for (const auto& t : GetAllowedTagsFromView(m_bv))
+ AddListItem(m_tagsList, QString::fromStdString(t));
- // Batch size and matcher checkbox
- m_batchSize = new QSpinBox(this);
- m_batchSize->setRange(10, 1000);
- m_batchSize->setValue(GetBatchSizeFromView(m_bv));
- m_batchSize->setToolTip("Number of functions to fetch in each batch");
+ // Batch size and matcher checkbox
+ m_batchSize = new QSpinBox(this);
+ m_batchSize->setRange(10, 1000);
+ m_batchSize->setValue(GetBatchSizeFromView(m_bv));
+ m_batchSize->setToolTip("Number of functions to fetch in each batch");
- m_rerunMatcher = new QCheckBox("Re-run matcher after fetch", this);
- m_rerunMatcher->setChecked(true);
+ m_rerunMatcher = new QCheckBox("Re-run matcher after fetch", this);
+ m_rerunMatcher->setChecked(true);
- m_clearProcessed = new QCheckBox("Refetch all functions", this);
- m_clearProcessed->setToolTip("Clears the processed cache before fetching again, this will refetch all functions in the view");
- m_clearProcessed->setChecked(false);
+ m_clearProcessed = new QCheckBox("Refetch all functions", this);
+ m_clearProcessed->setToolTip(
+ "Clears the processed cache before fetching again, this will refetch all functions in the view");
+ m_clearProcessed->setChecked(false);
- form->addRow(new QLabel("Container: "), m_containerCombo);
- form->addRow(new QLabel("Allowed Tags: "), tagWrapper);
- form->addRow(new QLabel("Batch Size: "), m_batchSize);
- form->addRow(m_rerunMatcher);
- form->addRow(m_clearProcessed);
+ form->addRow(new QLabel("Container: "), m_containerCombo);
+ form->addRow(new QLabel("Allowed Tags: "), tagWrapper);
+ form->addRow(new QLabel("Batch Size: "), m_batchSize);
+ form->addRow(m_rerunMatcher);
+ form->addRow(m_clearProcessed);
- auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- connect(buttons, &QDialogButtonBox::accepted, this, &WarpFetchDialog::onAccept);
- connect(buttons, &QDialogButtonBox::rejected, this, &WarpFetchDialog::onReject);
+ auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ connect(buttons, &QDialogButtonBox::accepted, this, &WarpFetchDialog::onAccept);
+ connect(buttons, &QDialogButtonBox::rejected, this, &WarpFetchDialog::onReject);
- auto root = new QVBoxLayout(this);
- root->addLayout(form);
- root->addWidget(buttons);
- setLayout(root);
+ auto root = new QVBoxLayout(this);
+ root->addLayout(form);
+ root->addWidget(buttons);
+ setLayout(root);
- // Wire buttons
- connect(m_addTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onAddTag);
- connect(m_removeTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onRemoveTag);
- connect(m_resetTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onResetTags);
+ // Wire buttons
+ connect(m_addTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onAddTag);
+ connect(m_removeTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onRemoveTag);
+ connect(m_resetTagBtn, &QPushButton::clicked, this, &WarpFetchDialog::onResetTags);
}
void WarpFetchDialog::populateContainers()
{
- m_containers = Warp::Container::All();
+ m_containers = Warp::Container::All();
}
void WarpFetchDialog::onAddTag()
{
- bool ok = false;
- const auto text = QInputDialog::getText(this, "Add Tag", "Tag:", QLineEdit::Normal, {}, &ok);
- if (ok)
- AddListItem(m_tagsList, text);
+ bool ok = false;
+ const auto text = QInputDialog::getText(this, "Add Tag", "Tag:", QLineEdit::Normal, {}, &ok);
+ if (ok)
+ AddListItem(m_tagsList, text);
}
void WarpFetchDialog::onRemoveTag()
{
- for (auto *item: m_tagsList->selectedItems())
- delete item;
+ for (auto* item : m_tagsList->selectedItems())
+ delete item;
}
void WarpFetchDialog::onResetTags()
{
- m_tagsList->clear();
- AddListItem(m_tagsList, "official");
- AddListItem(m_tagsList, "trusted");
+ m_tagsList->clear();
+ AddListItem(m_tagsList, "official");
+ AddListItem(m_tagsList, "trusted");
}
std::vector<Warp::SourceTag> WarpFetchDialog::collectTags() const
{
- std::vector<Warp::SourceTag> out;
- out.reserve(m_tagsList->count());
- for (int i = 0; i < m_tagsList->count(); ++i)
- out.emplace_back(m_tagsList->item(i)->text().trimmed().toStdString());
- return out;
+ std::vector<Warp::SourceTag> out;
+ out.reserve(m_tagsList->count());
+ for (int i = 0; i < m_tagsList->count(); ++i)
+ out.emplace_back(m_tagsList->item(i)->text().trimmed().toStdString());
+ return out;
}
void WarpFetchDialog::onAccept()
{
- const int idx = m_containerCombo->currentIndex();
- std::optional<size_t> containerIndex;
- if (idx > 0) // 0 == All Containers
- containerIndex = static_cast<size_t>(idx - 1);
+ const int idx = m_containerCombo->currentIndex();
+ std::optional<size_t> containerIndex;
+ if (idx > 0) // 0 == All Containers
+ containerIndex = static_cast<size_t>(idx - 1);
- const auto batch = static_cast<size_t>(m_batchSize->value());
- const bool rerun = m_rerunMatcher->isChecked();
+ const auto batch = static_cast<size_t>(m_batchSize->value());
+ const bool rerun = m_rerunMatcher->isChecked();
- const auto tags = collectTags();
- // Persist tags to the view settings.
- SetTagsToView(m_bv, tags);
+ const auto tags = collectTags();
+ // Persist tags to the view settings.
+ SetTagsToView(m_bv, tags);
- if (m_clearProcessed->isChecked())
- m_fetchProcessor->ClearProcessed();
+ if (m_clearProcessed->isChecked())
+ m_fetchProcessor->ClearProcessed();
- // Execute the network fetch in batches
- runBatchedFetch(containerIndex, tags, batch, rerun);
+ // Execute the network fetch in batches
+ runBatchedFetch(containerIndex, tags, batch, rerun);
- accept();
+ accept();
}
void WarpFetchDialog::onReject()
{
- const auto tags = collectTags();
- // Persist tags to the view settings.
- SetTagsToView(m_bv, tags);
- reject();
+ const auto tags = collectTags();
+ // Persist tags to the view settings.
+ SetTagsToView(m_bv, tags);
+ reject();
}
-void WarpFetchDialog::runBatchedFetch(const std::optional<size_t> &containerIndex,
- const std::vector<Warp::SourceTag> &allowedTags,
- size_t batchSize,
- bool rerunMatcher)
+void WarpFetchDialog::runBatchedFetch(const std::optional<size_t>& containerIndex,
+ const std::vector<Warp::SourceTag>& allowedTags, size_t batchSize, bool rerunMatcher)
{
- if (!m_bv)
- return;
- // Collect functions in the view and enqueue them to the shared fetcher
- std::vector<Ref<Function>> funcs = m_bv->GetAnalysisFunctionList();
- if (funcs.empty())
- return;
- const size_t totalFuncs = funcs.size();
- const size_t totalBatches = (totalFuncs + batchSize - 1) / batchSize;
+ if (!m_bv)
+ return;
+ // Collect functions in the view and enqueue them to the shared fetcher
+ std::vector<Ref<Function>> funcs = m_bv->GetAnalysisFunctionList();
+ if (funcs.empty())
+ return;
+ const size_t totalFuncs = funcs.size();
+ const size_t totalBatches = (totalFuncs + batchSize - 1) / batchSize;
- // Create a background task to show progress in the UI
- Ref<BackgroundTask> task = new BackgroundTask("Fetching WARP functions (0 / " + std::to_string(totalBatches) + ")", false);
+ // Create a background task to show progress in the UI
+ Ref<BackgroundTask> task =
+ new BackgroundTask("Fetching WARP functions (0 / " + std::to_string(totalBatches) + ")", false);
- auto fetcher = m_fetchProcessor;
- auto bv = m_bv;
+ auto fetcher = m_fetchProcessor;
+ auto bv = m_bv;
- // TODO: Too many captures in this thing lol.
- WorkerInteractiveEnqueue([fetcher, bv, funcs = std::move(funcs), batchSize, rerunMatcher, task, allowedTags]() mutable {
- size_t processed = 0;
- size_t batchIndex = 0;
+ // TODO: Too many captures in this thing lol.
+ WorkerInteractiveEnqueue(
+ [fetcher, bv, funcs = std::move(funcs), batchSize, rerunMatcher, task, allowedTags]() mutable {
+ size_t processed = 0;
+ size_t batchIndex = 0;
- while (processed < funcs.size())
- {
- const size_t remaining = funcs.size() - processed;
- const size_t thisBatchCount = std::min(batchSize, remaining);
+ while (processed < funcs.size())
+ {
+ const size_t remaining = funcs.size() - processed;
+ const size_t thisBatchCount = std::min(batchSize, remaining);
- for (size_t i = 0; i < thisBatchCount; ++i)
- fetcher->AddPendingFunction(funcs[processed + i]);
+ for (size_t i = 0; i < thisBatchCount; ++i)
+ fetcher->AddPendingFunction(funcs[processed + i]);
- fetcher->FetchPendingFunctions(allowedTags);
+ fetcher->FetchPendingFunctions(allowedTags);
- ++batchIndex;
- processed += thisBatchCount;
+ ++batchIndex;
+ processed += thisBatchCount;
- task->SetProgressText("Fetching WARP functions (" + std::to_string(batchIndex) + " / " + std::to_string((funcs.size() + batchSize - 1) / batchSize) + ")");
- }
+ task->SetProgressText("Fetching WARP functions (" + std::to_string(batchIndex) + " / "
+ + std::to_string((funcs.size() + batchSize - 1) / batchSize) + ")");
+ }
- task->Finish();
- // TODO: Print how long it took?
- Logger("WARP Fetcher").LogInfo("Finished fetching WARP functions...");
+ task->Finish();
+ // TODO: Print how long it took?
+ Logger("WARP Fetcher").LogInfo("Finished fetching WARP functions...");
- if (rerunMatcher && bv)
- Warp::RunMatcher(*bv);
- });
+ if (rerunMatcher && bv)
+ Warp::RunMatcher(*bv);
+ });
}
void RegisterWarpFetchFunctionsCommand()
{
- // Register a UI action and bind it globally. Add it to the Tools menu.
- const QString actionName = "WARP\\Fetch";
- if (!UIAction::isActionRegistered(actionName))
- UIAction::registerAction(actionName);
+ // Register a UI action and bind it globally. Add it to the Tools menu.
+ const QString actionName = "WARP\\Fetch";
+ if (!UIAction::isActionRegistered(actionName))
+ UIAction::registerAction(actionName);
- UIActionHandler::globalActions()->bindAction(
- actionName,
- UIAction(
- [](const UIActionContext &context) {
- if (const BinaryViewRef bv = context.binaryView; bv)
- {
- WarpFetchDialog dlg(bv, WarpFetcher::Global(), nullptr);
- dlg.exec();
- }
- },
- [](const UIActionContext &context) {
- return context.binaryView != nullptr;
- }
- )
- );
+ UIActionHandler::globalActions()->bindAction(actionName,
+ UIAction(
+ [](const UIActionContext& context) {
+ if (const BinaryViewRef bv = context.binaryView; bv)
+ {
+ WarpFetchDialog dlg(bv, WarpFetcher::Global(), nullptr);
+ dlg.exec();
+ }
+ },
+ [](const UIActionContext& context) { return context.binaryView != nullptr; }));
- Menu::mainMenu("Plugins")->addAction(actionName, "Plugins");
+ Menu::mainMenu("Plugins")->addAction(actionName, "Plugins");
}
diff --git a/plugins/warp/ui/shared/fetchdialog.h b/plugins/warp/ui/shared/fetchdialog.h
index a99eef19..c642d31e 100644
--- a/plugins/warp/ui/shared/fetchdialog.h
+++ b/plugins/warp/ui/shared/fetchdialog.h
@@ -13,49 +13,45 @@
class WarpFetchDialog : public QDialog
{
- Q_OBJECT
+ Q_OBJECT
- QComboBox *m_containerCombo;
+ QComboBox* m_containerCombo;
- QListWidget *m_tagsList;
- QPushButton *m_addTagBtn;
- QPushButton *m_removeTagBtn;
- QPushButton *m_resetTagBtn;
+ QListWidget* m_tagsList;
+ QPushButton* m_addTagBtn;
+ QPushButton* m_removeTagBtn;
+ QPushButton* m_resetTagBtn;
- QSpinBox *m_batchSize;
- QCheckBox *m_rerunMatcher;
- QCheckBox *m_clearProcessed;
+ QSpinBox* m_batchSize;
+ QCheckBox* m_rerunMatcher;
+ QCheckBox* m_clearProcessed;
- std::vector<Warp::Ref<Warp::Container> > m_containers;
+ std::vector<Warp::Ref<Warp::Container>> m_containers;
- std::shared_ptr<WarpFetcher> m_fetchProcessor;
- BinaryViewRef m_bv;
+ std::shared_ptr<WarpFetcher> m_fetchProcessor;
+ BinaryViewRef m_bv;
public:
- explicit WarpFetchDialog(BinaryViewRef bv,
- std::shared_ptr<WarpFetcher> fetchProcessor,
- QWidget *parent = nullptr);
+ explicit WarpFetchDialog(BinaryViewRef bv, std::shared_ptr<WarpFetcher> fetchProcessor, QWidget* parent = nullptr);
private slots:
- void onAddTag();
+ void onAddTag();
- void onRemoveTag();
+ void onRemoveTag();
- void onResetTags();
+ void onResetTags();
- void onAccept();
+ void onAccept();
- void onReject();
+ void onReject();
private:
- void populateContainers();
+ void populateContainers();
- std::vector<Warp::SourceTag> collectTags() const;
+ std::vector<Warp::SourceTag> collectTags() const;
- void runBatchedFetch(const std::optional<size_t> &containerIndex,
- const std::vector<Warp::SourceTag> &allowedTags,
- size_t batchSize,
- bool rerunMatcher);
+ void runBatchedFetch(const std::optional<size_t>& containerIndex, const std::vector<Warp::SourceTag>& allowedTags,
+ size_t batchSize, bool rerunMatcher);
};
void RegisterWarpFetchFunctionsCommand();
diff --git a/plugins/warp/ui/shared/fetcher.cpp b/plugins/warp/ui/shared/fetcher.cpp
index 299050a5..1a262878 100644
--- a/plugins/warp/ui/shared/fetcher.cpp
+++ b/plugins/warp/ui/shared/fetcher.cpp
@@ -2,89 +2,90 @@
WarpFetcher::WarpFetcher()
{
- m_logger = new BinaryNinja::Logger("WARP Fetcher");
+ m_logger = new BinaryNinja::Logger("WARP Fetcher");
}
-void WarpFetcher::AddPendingFunction(const FunctionRef &func)
+void WarpFetcher::AddPendingFunction(const FunctionRef& func)
{
- std::lock_guard<std::mutex> lock(m_requestMutex);
- const auto guid = Warp::GetAnalysisFunctionGUID(*func);
- if (!guid.has_value() || m_processedGuids.contains(*guid))
- return;
- m_pendingRequests.push_back(func);
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ const auto guid = Warp::GetAnalysisFunctionGUID(*func);
+ if (!guid.has_value() || m_processedGuids.contains(*guid))
+ return;
+ m_pendingRequests.push_back(func);
}
std::vector<FunctionRef> WarpFetcher::FlushPendingFunctions()
{
- std::lock_guard<std::mutex> lock(m_requestMutex);
- std::vector<FunctionRef> requests = std::move(m_pendingRequests);
- m_pendingRequests.clear();
- return requests;
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ std::vector<FunctionRef> requests = std::move(m_pendingRequests);
+ m_pendingRequests.clear();
+ return requests;
}
void WarpFetcher::ExecuteCompletionCallback()
{
- BinaryNinja::ExecuteOnMainThread([this]() {
- // TODO: Holding the mutex here is dangerous!
- std::lock_guard<std::mutex> lock(m_requestMutex);
- m_completionCallbacks.erase(
- std::ranges::remove_if(m_completionCallbacks,
- [](const auto &cb) { return cb() == RemoveCallback; }).begin(),
- m_completionCallbacks.end());
- });
+ BinaryNinja::ExecuteOnMainThread([this]() {
+ // TODO: Holding the mutex here is dangerous!
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ m_completionCallbacks.erase(
+ std::ranges::remove_if(m_completionCallbacks, [](const auto& cb) { return cb() == RemoveCallback; })
+ .begin(),
+ m_completionCallbacks.end());
+ });
}
std::shared_ptr<WarpFetcher> WarpFetcher::Global()
{
- static auto global = std::make_shared<WarpFetcher>();
- return global;
+ static auto global = std::make_shared<WarpFetcher>();
+ return global;
}
void WarpFetcher::FetchPendingFunctions(const std::vector<Warp::SourceTag>& allowedTags)
{
- m_requestInProgress = true;
- const auto requests = FlushPendingFunctions();
- if (requests.empty())
- {
- m_logger->LogDebug("No pending requests to fetch... skipping");
- m_requestInProgress = false;
- return;
- }
+ m_requestInProgress = true;
+ const auto requests = FlushPendingFunctions();
+ if (requests.empty())
+ {
+ m_logger->LogDebug("No pending requests to fetch... skipping");
+ m_requestInProgress = false;
+ return;
+ }
- const auto start_time = std::chrono::high_resolution_clock::now();
+ const auto start_time = std::chrono::high_resolution_clock::now();
- // Because we must fetch for a single target we map the function guids to the associated platform to perform fetches for each.
- std::map<PlatformRef, std::vector<Warp::FunctionGUID>> platformMappedGuids;
- for (const auto &func: requests)
- {
- const auto guid = Warp::GetAnalysisFunctionGUID(*func);
- if (!guid.has_value())
- continue;
- auto platform = func->GetPlatform();
- platformMappedGuids[platform].push_back(guid.value());
- }
+ // Because we must fetch for a single target we map the function guids to the associated platform to perform fetches
+ // for each.
+ std::map<PlatformRef, std::vector<Warp::FunctionGUID>> platformMappedGuids;
+ for (const auto& func : requests)
+ {
+ const auto guid = Warp::GetAnalysisFunctionGUID(*func);
+ if (!guid.has_value())
+ continue;
+ auto platform = func->GetPlatform();
+ platformMappedGuids[platform].push_back(guid.value());
+ }
- for (const auto &[platform, guids] : platformMappedGuids)
- {
- m_logger->LogDebugF("Fetching {} functions for platform {}", guids.size(), platform->GetName());
- auto target = Warp::Target::FromPlatform(*platform);
- for (const auto &container: Warp::Container::All())
- container->FetchFunctions(*target, guids, allowedTags);
+ for (const auto& [platform, guids] : platformMappedGuids)
+ {
+ m_logger->LogDebugF("Fetching {} functions for platform {}", guids.size(), platform->GetName());
+ auto target = Warp::Target::FromPlatform(*platform);
+ for (const auto& container : Warp::Container::All())
+ container->FetchFunctions(*target, guids, allowedTags);
- std::lock_guard<std::mutex> lock(m_requestMutex);
- for (const auto &guid: guids)
- m_processedGuids.insert(guid);
- }
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ for (const auto& guid : guids)
+ m_processedGuids.insert(guid);
+ }
- m_requestInProgress = false;
- ExecuteCompletionCallback();
- const auto end_time = std::chrono::high_resolution_clock::now();
- const std::chrono::duration<double> elapsed_time = end_time - start_time;
- m_logger->LogDebug("Fetch batch took %f seconds", elapsed_time.count());
+ m_requestInProgress = false;
+ ExecuteCompletionCallback();
+ const auto end_time = std::chrono::high_resolution_clock::now();
+ const std::chrono::duration<double> elapsed_time = end_time - start_time;
+ m_logger->LogDebug("Fetch batch took %f seconds", elapsed_time.count());
}
void WarpFetcher::ClearProcessed()
{
- m_logger->LogInfoF("Clearing {} processed functions from cache...", m_processedGuids.size());
- m_processedGuids.clear();
+ m_logger->LogInfoF("Clearing {} processed functions from cache...", m_processedGuids.size());
+ m_processedGuids.clear();
}
diff --git a/plugins/warp/ui/shared/fetcher.h b/plugins/warp/ui/shared/fetcher.h
index 917ac912..52d0a0e2 100644
--- a/plugins/warp/ui/shared/fetcher.h
+++ b/plugins/warp/ui/shared/fetcher.h
@@ -12,43 +12,44 @@
enum WarpFetchCompletionStatus
{
- KeepCallback,
- RemoveCallback,
+ KeepCallback,
+ RemoveCallback,
};
// Responsible for fetching data from the containers, to later be queried from the container interface.
class WarpFetcher
{
- LoggerRef m_logger;
+ LoggerRef m_logger;
- std::mutex m_requestMutex;
- std::vector<FunctionRef> m_pendingRequests;
- std::unordered_set<Warp::FunctionGUID> m_processedGuids;
+ std::mutex m_requestMutex;
+ std::vector<FunctionRef> m_pendingRequests;
+ std::unordered_set<Warp::FunctionGUID> m_processedGuids;
- // List of callbacks to call when done fetching data, assume that others are using this as well.
- std::vector<std::function<WarpFetchCompletionStatus()> > m_completionCallbacks;
+ // List of callbacks to call when done fetching data, assume that others are using this as well.
+ std::vector<std::function<WarpFetchCompletionStatus()>> m_completionCallbacks;
public:
- explicit WarpFetcher();
+ explicit WarpFetcher();
- // The global fetcher instance, this is used for the fetch dialog and the sidebar.
- static std::shared_ptr<WarpFetcher> Global();
+ // The global fetcher instance, this is used for the fetch dialog and the sidebar.
+ static std::shared_ptr<WarpFetcher> Global();
- std::atomic<bool> m_requestInProgress = false;
+ std::atomic<bool> m_requestInProgress = false;
- void AddCompletionCallback(std::function<WarpFetchCompletionStatus()> cb)
- {
- std::lock_guard<std::mutex> lock(m_requestMutex);
- m_completionCallbacks.push_back(std::move(cb));
- }
+ void AddCompletionCallback(std::function<WarpFetchCompletionStatus()> cb)
+ {
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ m_completionCallbacks.push_back(std::move(cb));
+ }
- void AddPendingFunction(const FunctionRef &func);
+ void AddPendingFunction(const FunctionRef& func);
- void FetchPendingFunctions(const std::vector<Warp::SourceTag>& allowedTags);
+ void FetchPendingFunctions(const std::vector<Warp::SourceTag>& allowedTags);
+
+ void ClearProcessed();
- void ClearProcessed();
private:
- std::vector<FunctionRef> FlushPendingFunctions();
+ std::vector<FunctionRef> FlushPendingFunctions();
- void ExecuteCompletionCallback();
+ void ExecuteCompletionCallback();
};
diff --git a/plugins/warp/ui/shared/function.cpp b/plugins/warp/ui/shared/function.cpp
index e1609e0b..e177c285 100644
--- a/plugins/warp/ui/shared/function.cpp
+++ b/plugins/warp/ui/shared/function.cpp
@@ -9,342 +9,338 @@
#include "constraint.h"
#include "misc.h"
-WarpFunctionItem::WarpFunctionItem(Warp::Ref<Warp::Function> function,
- BinaryNinja::Ref<BinaryNinja::Function> analysisFunction)
+WarpFunctionItem::WarpFunctionItem(
+ Warp::Ref<Warp::Function> function, BinaryNinja::Ref<BinaryNinja::Function> analysisFunction)
{
- m_function = function;
+ m_function = function;
- BinaryNinja::Ref<BinaryNinja::Symbol> symbol = m_function->GetSymbol(*analysisFunction);
- std::string symbolName = symbol->GetShortName();
- setText(QString::fromStdString(symbolName));
+ BinaryNinja::Ref<BinaryNinja::Symbol> symbol = m_function->GetSymbol(*analysisFunction);
+ std::string symbolName = symbol->GetShortName();
+ setText(QString::fromStdString(symbolName));
- // Serialize the tokens to make it accessible via QModelIndex.
- // We will take these tokens and then user them in our custom item delegate.
- TokenData tokenData = TokenData(symbolName);
- if (BinaryNinja::Ref<BinaryNinja::Type> type = m_function->GetType(*analysisFunction))
- tokenData = TokenData(*type, symbolName);
- setData(QVariant::fromValue(tokenData), Qt::UserRole);
+ // Serialize the tokens to make it accessible via QModelIndex.
+ // We will take these tokens and then user them in our custom item delegate.
+ TokenData tokenData = TokenData(symbolName);
+ if (BinaryNinja::Ref<BinaryNinja::Type> type = m_function->GetType(*analysisFunction))
+ tokenData = TokenData(*type, symbolName);
+ setData(QVariant::fromValue(tokenData), Qt::UserRole);
}
-void WarpFunctionItem::SetContainer(const Warp::Ref<Warp::Container> &container)
+void WarpFunctionItem::SetContainer(const Warp::Ref<Warp::Container>& container)
{
- m_container = container;
+ m_container = container;
- // Add the container string to data so the filter model picks it up.
- auto containerName = m_container->GetName();
- setData(QString::fromStdString(containerName), Qt::UserRole + 2);
+ // Add the container string to data so the filter model picks it up.
+ auto containerName = m_container->GetName();
+ setData(QString::fromStdString(containerName), Qt::UserRole + 2);
}
void WarpFunctionItem::SetSource(Warp::Source source)
{
- m_source = source;
+ m_source = source;
- // Add the source string to data so the filter model picks it up.
- std::string sourceStr = m_source->ToString();
- setData(QString::fromStdString(sourceStr), Qt::UserRole + 1);
+ // Add the source string to data so the filter model picks it up.
+ std::string sourceStr = m_source->ToString();
+ setData(QString::fromStdString(sourceStr), Qt::UserRole + 1);
}
-WarpFunctionItemModel::WarpFunctionItemModel(const QStringList &labels, QObject *parent)
+WarpFunctionItemModel::WarpFunctionItemModel(const QStringList& labels, QObject* parent)
{
- this->setHorizontalHeaderLabels(labels);
+ this->setHorizontalHeaderLabels(labels);
}
-void WarpFunctionItemModel::AppendFunction(WarpFunctionItem *item)
+void WarpFunctionItemModel::AppendFunction(WarpFunctionItem* item)
{
- QList<QStandardItem *> row = {};
- row.insert(COL_FUNCTION_ITEM, item);
- appendRow(row);
+ QList<QStandardItem*> row = {};
+ row.insert(COL_FUNCTION_ITEM, item);
+ appendRow(row);
}
-void WarpFunctionItemModel::InsertFunction(uint64_t address, WarpFunctionItem *item)
+void WarpFunctionItemModel::InsertFunction(uint64_t address, WarpFunctionItem* item)
{
- // Update item if already available, this lets us keep the model
- const auto iter = m_insertableFunctionRows.find(address);
- if (iter != m_insertableFunctionRows.end())
- {
- setItem(iter->second, COL_FUNCTION_ITEM, item);
- return;
- }
+ // Update item if already available, this lets us keep the model
+ const auto iter = m_insertableFunctionRows.find(address);
+ if (iter != m_insertableFunctionRows.end())
+ {
+ setItem(iter->second, COL_FUNCTION_ITEM, item);
+ return;
+ }
- AppendFunction(item);
- m_insertableFunctionRows[address] = rowCount() - 1;
+ AppendFunction(item);
+ m_insertableFunctionRows[address] = rowCount() - 1;
}
-WarpFunctionItem *WarpFunctionItemModel::GetItem(const QModelIndex &index) const
+WarpFunctionItem* WarpFunctionItemModel::GetItem(const QModelIndex& index) const
{
- if (!index.isValid())
- return nullptr;
- return dynamic_cast<WarpFunctionItem *>(item(index.row(), COL_FUNCTION_ITEM));
+ if (!index.isValid())
+ return nullptr;
+ return dynamic_cast<WarpFunctionItem*>(item(index.row(), COL_FUNCTION_ITEM));
}
-std::optional<uint64_t> WarpFunctionItemModel::GetAddress(const QModelIndex &index) const
+std::optional<uint64_t> WarpFunctionItemModel::GetAddress(const QModelIndex& index) const
{
- if (!index.isValid())
- return std::nullopt;
- // TODO: This is a hack, this means we must enumerate all rows to get the address.
- for (const auto &[addr, row]: m_insertableFunctionRows)
- if (row == index.row())
- return addr;
- return std::nullopt;
+ if (!index.isValid())
+ return std::nullopt;
+ // TODO: This is a hack, this means we must enumerate all rows to get the address.
+ for (const auto& [addr, row] : m_insertableFunctionRows)
+ if (row == index.row())
+ return addr;
+ return std::nullopt;
}
-QVariant WarpFunctionItemModel::data(const QModelIndex &index, int role) const
+QVariant WarpFunctionItemModel::data(const QModelIndex& index, int role) const
{
- if (role == Qt::BackgroundRole)
- {
- auto itemFunction = GetItem(index);
- // Check if we have a valid item and it's the matched function
- if (m_matchedFunction && itemFunction)
- {
- // TODO: Why wont == go to the correct call???
- if (BNWARPFunctionsEqual(itemFunction->GetFunction()->m_object, m_matchedFunction->m_object))
- {
- // TODO: Better color?
- static QColor matchedColor = getThemeColor(BlueStandardHighlightColor);
- matchedColor.setAlpha(128);
- return matchedColor;
- }
- }
- }
+ if (role == Qt::BackgroundRole)
+ {
+ auto itemFunction = GetItem(index);
+ // Check if we have a valid item and it's the matched function
+ if (m_matchedFunction && itemFunction)
+ {
+ // TODO: Why wont == go to the correct call???
+ if (BNWARPFunctionsEqual(itemFunction->GetFunction()->m_object, m_matchedFunction->m_object))
+ {
+ // TODO: Better color?
+ static QColor matchedColor = getThemeColor(BlueStandardHighlightColor);
+ matchedColor.setAlpha(128);
+ return matchedColor;
+ }
+ }
+ }
- if (role == Qt::DisplayRole)
- {
- // We really only use this for searching as we have TokenData for our delegate.
- WarpFunctionItem *item = GetItem(index);
- if (!item)
- return QVariant();
- TokenData tokenData = item->data(Qt::UserRole).value<TokenData>();
- // Add the function guid so we can filter by that.
- QString text = tokenData.toString() + " " + QString::fromStdString(item->GetFunction()->GetGUID().ToString());
- if (auto source = item->GetSource(); source)
- {
- // Add the source guid so we can also filter by that.
- std::string sourceStr = source->ToString();
- text = text + " " + QString::fromStdString(sourceStr);
- }
- return text;
- }
+ if (role == Qt::DisplayRole)
+ {
+ // We really only use this for searching as we have TokenData for our delegate.
+ WarpFunctionItem* item = GetItem(index);
+ if (!item)
+ return QVariant();
+ TokenData tokenData = item->data(Qt::UserRole).value<TokenData>();
+ // Add the function guid so we can filter by that.
+ QString text = tokenData.toString() + " " + QString::fromStdString(item->GetFunction()->GetGUID().ToString());
+ if (auto source = item->GetSource(); source)
+ {
+ // Add the source guid so we can also filter by that.
+ std::string sourceStr = source->ToString();
+ text = text + " " + QString::fromStdString(sourceStr);
+ }
+ return text;
+ }
- return QStandardItemModel::data(index, role);
+ return QStandardItemModel::data(index, role);
}
-bool WarpFunctionFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+bool WarpFunctionFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
- const QString filterString = filterRegularExpression().pattern();
- if (filterString.isEmpty())
- return true;
+ const QString filterString = filterRegularExpression().pattern();
+ if (filterString.isEmpty())
+ return true;
- // Filter on the first column only, this contains our actual function.
- auto index = sourceModel()->index(sourceRow, 0, sourceParent);
- auto data = QRegularExpression::escape(index.data().toString());
- if (data.contains(filterString, Qt::CaseInsensitive))
- return true;
- return false;
+ // Filter on the first column only, this contains our actual function.
+ auto index = sourceModel()->index(sourceRow, 0, sourceParent);
+ auto data = QRegularExpression::escape(index.data().toString());
+ if (data.contains(filterString, Qt::CaseInsensitive))
+ return true;
+ return false;
}
-bool WarpFunctionFilterModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const
+bool WarpFunctionFilterModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const
{
- // TODO: When we make the stuff _actually_ sortable.
- return sourceLeft.row() < sourceRight.row();
+ // TODO: When we make the stuff _actually_ sortable.
+ return sourceLeft.row() < sourceRight.row();
}
-WarpFunctionTableWidget::WarpFunctionTableWidget(QWidget *parent) : QWidget(parent)
+WarpFunctionTableWidget::WarpFunctionTableWidget(QWidget* parent) : QWidget(parent)
{
- QGridLayout *layout = new QGridLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(2);
+ QGridLayout* layout = new QGridLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(2);
- m_table = new QTableView(this);
- m_model = new WarpFunctionItemModel({"Function"}, this);
- m_proxyModel = new WarpFunctionFilterModel(this);
- m_proxyModel->setSourceModel(m_model);
- m_table->setModel(m_proxyModel);
+ m_table = new QTableView(this);
+ m_model = new WarpFunctionItemModel({"Function"}, this);
+ m_proxyModel = new WarpFunctionFilterModel(this);
+ m_proxyModel->setSourceModel(m_model);
+ m_table->setModel(m_proxyModel);
- m_filterEdit = new FilterEdit(this);
- m_filterView = new FilteredView(this, m_table, this, m_filterEdit);
- m_filterView->setFilterPlaceholderText("Search functions (By GUID, name or source)");
+ m_filterEdit = new FilterEdit(this);
+ m_filterView = new FilteredView(this, m_table, this, m_filterEdit);
+ m_filterView->setFilterPlaceholderText("Search functions (By GUID, name or source)");
- layout->addWidget(m_filterEdit, 0, 0, 1, 5);
- layout->addWidget(m_table, 1, 0, 1, 5);
+ layout->addWidget(m_filterEdit, 0, 0, 1, 5);
+ layout->addWidget(m_table, 1, 0, 1, 5);
- // Make the table look nice.
- m_table->horizontalHeader()->setStretchLastSection(true);
- m_table->verticalHeader()->hide();
- m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_table->setSelectionMode(QAbstractItemView::SingleSelection);
- m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_table->setFocusPolicy(Qt::NoFocus);
- m_table->setShowGrid(false);
- m_table->setAlternatingRowColors(false);
- m_table->setSortingEnabled(true);
- // NOTE: We only have a single column right now, so disable header.
- m_table->horizontalHeader()->hide();
- // Decrease row height to make it look nice.
- m_table->verticalHeader()->setDefaultSectionSize(30);
+ // Make the table look nice.
+ m_table->horizontalHeader()->setStretchLastSection(true);
+ m_table->verticalHeader()->hide();
+ m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_table->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_table->setFocusPolicy(Qt::NoFocus);
+ m_table->setShowGrid(false);
+ m_table->setAlternatingRowColors(false);
+ m_table->setSortingEnabled(true);
+ // NOTE: We only have a single column right now, so disable header.
+ m_table->horizontalHeader()->hide();
+ // Decrease row height to make it look nice.
+ m_table->verticalHeader()->setDefaultSectionSize(30);
- // Make the highlight less bright.
- QPalette palette = m_table->palette();
- palette.setColor(QPalette::Highlight, getThemeColor(SelectionColor));
- m_table->setPalette(palette);
+ // Make the highlight less bright.
+ QPalette palette = m_table->palette();
+ palette.setColor(QPalette::Highlight, getThemeColor(SelectionColor));
+ m_table->setPalette(palette);
- TokenDataDelegate *tokenDelegate = new TokenDataDelegate(this);
- // NOTE: Column 0 is assumed to be the function with the token data.
- m_table->setItemDelegateForColumn(0, tokenDelegate);
+ TokenDataDelegate* tokenDelegate = new TokenDataDelegate(this);
+ // NOTE: Column 0 is assumed to be the function with the token data.
+ m_table->setItemDelegateForColumn(0, tokenDelegate);
- AddressColorDelegate *addressDelegate = new AddressColorDelegate(this);
- // NOTE: Column 1 is assumed to be the function address.
- m_table->setItemDelegateForColumn(1, addressDelegate);
+ AddressColorDelegate* addressDelegate = new AddressColorDelegate(this);
+ // NOTE: Column 1 is assumed to be the function address.
+ m_table->setItemDelegateForColumn(1, addressDelegate);
- // Add a dynamic context menu to the table.
- // NOTE: This is a bit stupid, I am sure there is a better way to do this in QT.
- m_contextMenu = new QMenu(this);
- RegisterContextMenuAction("Copy Name", [](WarpFunctionItem *item, std::optional<uint64_t>) {
- QClipboard *clipboard = QGuiApplication::clipboard();
- clipboard->setText(item->text());
- });
- RegisterContextMenuAction("Copy GUID", [](WarpFunctionItem *item, std::optional<uint64_t>) {
- QClipboard *clipboard = QGuiApplication::clipboard();
- Warp::Ref<Warp::Function> function = item->GetFunction();
- std::string guidStr = function->GetGUID().ToString();
- clipboard->setText(QString::fromStdString(guidStr));
- });
+ // Add a dynamic context menu to the table.
+ // NOTE: This is a bit stupid, I am sure there is a better way to do this in QT.
+ m_contextMenu = new QMenu(this);
+ RegisterContextMenuAction("Copy Name", [](WarpFunctionItem* item, std::optional<uint64_t>) {
+ QClipboard* clipboard = QGuiApplication::clipboard();
+ clipboard->setText(item->text());
+ });
+ RegisterContextMenuAction("Copy GUID", [](WarpFunctionItem* item, std::optional<uint64_t>) {
+ QClipboard* clipboard = QGuiApplication::clipboard();
+ Warp::Ref<Warp::Function> function = item->GetFunction();
+ std::string guidStr = function->GetGUID().ToString();
+ clipboard->setText(QString::fromStdString(guidStr));
+ });
- m_table->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(m_table, &QTableView::customContextMenuRequested, this, [&](QPoint pos) {
- const QModelIndex index = m_table->indexAt(pos);
- if (!index.isValid())
- return;
- const QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
- WarpFunctionItem *item = m_model->GetItem(sourceIndex);
- if (!item || !item->GetFunction())
- return;
+ m_table->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_table, &QTableView::customContextMenuRequested, this, [&](QPoint pos) {
+ const QModelIndex index = m_table->indexAt(pos);
+ if (!index.isValid())
+ return;
+ const QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
+ WarpFunctionItem* item = m_model->GetItem(sourceIndex);
+ if (!item || !item->GetFunction())
+ return;
- // Execute the menu and get the selected action
- const QAction *selectedAction = m_contextMenu->exec(m_table->viewport()->mapToGlobal(pos));
- if (!selectedAction)
- return;
+ // Execute the menu and get the selected action
+ const QAction* selectedAction = m_contextMenu->exec(m_table->viewport()->mapToGlobal(pos));
+ if (!selectedAction)
+ return;
- const auto name = selectedAction->text();
- const auto iter = m_contextMenuActions.find(name);
- if (iter != m_contextMenuActions.end())
- iter->second(item, m_model->GetAddress(sourceIndex));
- });
+ const auto name = selectedAction->text();
+ const auto iter = m_contextMenuActions.find(name);
+ if (iter != m_contextMenuActions.end())
+ iter->second(item, m_model->GetAddress(sourceIndex));
+ });
}
-void WarpFunctionTableWidget::RegisterContextMenuAction(const QString &name,
- const std::function<void(
- WarpFunctionItem *, std::optional<uint64_t>)> &callback)
+void WarpFunctionTableWidget::RegisterContextMenuAction(
+ const QString& name, const std::function<void(WarpFunctionItem*, std::optional<uint64_t>)>& callback)
{
- m_contextMenu->addAction(name);
- m_contextMenuActions[name] = callback;
+ m_contextMenu->addAction(name);
+ m_contextMenuActions[name] = callback;
}
-void WarpFunctionTableWidget::SetFunctions(QVector<WarpFunctionItem *> functions)
+void WarpFunctionTableWidget::SetFunctions(QVector<WarpFunctionItem*> functions)
{
- // Clear matches as they are no longer valid.
- m_model->clear();
- m_model->setRowCount(0);
+ // Clear matches as they are no longer valid.
+ m_model->clear();
+ m_model->setRowCount(0);
- // Temporarily disable sorting so we can add rows faster
- m_table->setModel(m_model);
- m_table->setSortingEnabled(false);
- m_table->setEnabled(false);
+ // Temporarily disable sorting so we can add rows faster
+ m_table->setModel(m_model);
+ m_table->setSortingEnabled(false);
+ m_table->setEnabled(false);
- for (const auto &function: functions)
- m_model->AppendFunction(function);
+ for (const auto& function : functions)
+ m_model->AppendFunction(function);
- // We are done, re-enable table.
- m_table->setEnabled(true);
- m_table->setModel(m_proxyModel);
- m_table->setSortingEnabled(true);
+ // We are done, re-enable table.
+ m_table->setEnabled(true);
+ m_table->setModel(m_proxyModel);
+ m_table->setSortingEnabled(true);
- // Update the filter text with the new count of functions.
- m_filterView->setFilterPlaceholderText(QString("Search %1 functions").arg(m_model->rowCount()));
+ // Update the filter text with the new count of functions.
+ m_filterView->setFilterPlaceholderText(QString("Search %1 functions").arg(m_model->rowCount()));
}
-void WarpFunctionTableWidget::InsertFunction(uint64_t address, WarpFunctionItem *function)
+void WarpFunctionTableWidget::InsertFunction(uint64_t address, WarpFunctionItem* function)
{
- m_model->InsertFunction(address, function);
+ m_model->InsertFunction(address, function);
}
-void WarpFunctionTableWidget::setFilter(const std::string &filter)
+void WarpFunctionTableWidget::setFilter(const std::string& filter)
{
- m_proxyModel->setFilterFixedString(QString::fromStdString(filter));
- m_filterView->showFilter(QString::fromStdString(filter));
+ m_proxyModel->setFilterFixedString(QString::fromStdString(filter));
+ m_filterView->showFilter(QString::fromStdString(filter));
}
-WarpFunctionInfoWidget::WarpFunctionInfoWidget(QWidget *parent)
- : QWidget(parent)
+WarpFunctionInfoWidget::WarpFunctionInfoWidget(QWidget* parent) : QWidget(parent)
{
- // Create a tab widget
- QTabWidget *tabWidget = new QTabWidget(this);
- tabWidget->setContentsMargins(0, 0, 0, 0);
+ // Create a tab widget
+ QTabWidget* tabWidget = new QTabWidget(this);
+ tabWidget->setContentsMargins(0, 0, 0, 0);
- // Create tables for the "Constraints", "Comments", and "Variables" tabs
- m_commentsTable = new QTableView(this);
- // m_variablesTable = new QTableView(this);
+ // Create tables for the "Constraints", "Comments", and "Variables" tabs
+ m_commentsTable = new QTableView(this);
+ // m_variablesTable = new QTableView(this);
- // TODO: On click navigate to where the constraint is located.
- m_constraintsTable = new WarpConstraintTableWidget(this);
- tabWidget->addTab(m_constraintsTable, "Constraints");
+ // TODO: On click navigate to where the constraint is located.
+ m_constraintsTable = new WarpConstraintTableWidget(this);
+ tabWidget->addTab(m_constraintsTable, "Constraints");
- // Set up comments tab
- m_commentsModel = new QStandardItemModel(this);
- m_commentsModel->setHorizontalHeaderLabels({"Offset", "Text"});
- m_commentsModel->setColumnCount(2);
- m_commentsTable->setModel(m_commentsModel);
- m_commentsTable->horizontalHeader()->setStretchLastSection(true);
- m_commentsTable->horizontalHeader()->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_commentsTable->horizontalHeader()->setSelectionMode(QAbstractItemView::SingleSelection);
- m_commentsTable->horizontalHeader()->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_commentsTable->verticalHeader()->hide();
- m_commentsTable->horizontalHeader()->hide();
- tabWidget->addTab(m_commentsTable, "Comments");
+ // Set up comments tab
+ m_commentsModel = new QStandardItemModel(this);
+ m_commentsModel->setHorizontalHeaderLabels({"Offset", "Text"});
+ m_commentsModel->setColumnCount(2);
+ m_commentsTable->setModel(m_commentsModel);
+ m_commentsTable->horizontalHeader()->setStretchLastSection(true);
+ m_commentsTable->horizontalHeader()->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_commentsTable->horizontalHeader()->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_commentsTable->horizontalHeader()->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_commentsTable->verticalHeader()->hide();
+ m_commentsTable->horizontalHeader()->hide();
+ tabWidget->addTab(m_commentsTable, "Comments");
- // Set up variables tab
- // m_variablesTable->setModel(new QStandardItemModel(this));
- // TODO: Add variables to data.
- // tabWidget->addTab(m_variablesTable, "Variables");
+ // Set up variables tab
+ // m_variablesTable->setModel(new QStandardItemModel(this));
+ // TODO: Add variables to data.
+ // tabWidget->addTab(m_variablesTable, "Variables");
- // Add the tab widget to this widget's layout
- QVBoxLayout *layout = new QVBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- layout->addWidget(tabWidget);
+ // Add the tab widget to this widget's layout
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->addWidget(tabWidget);
- setLayout(layout);
+ setLayout(layout);
}
void WarpFunctionInfoWidget::UpdateInfo()
{
- m_commentsModel->clear();
- m_commentsModel->setRowCount(0);
- m_constraintsTable->SetMatchedConstraints({});
- m_constraintsTable->SetConstraints({});
+ m_commentsModel->clear();
+ m_commentsModel->setRowCount(0);
+ m_constraintsTable->SetMatchedConstraints({});
+ m_constraintsTable->SetConstraints({});
- Warp::Ref<Warp::Function> function = GetFunction();
- if (!function)
- return;
+ Warp::Ref<Warp::Function> function = GetFunction();
+ if (!function)
+ return;
- // Set the analysis constraints if there is an analysis function.
- if (const auto analysisFunction = GetAnalysisFunction())
- {
- const auto analysisConstraints = Warp::Function::Get(*analysisFunction)->GetConstraints();
- m_constraintsTable->SetMatchedConstraints(analysisConstraints);
- }
+ // Set the analysis constraints if there is an analysis function.
+ if (const auto analysisFunction = GetAnalysisFunction())
+ {
+ const auto analysisConstraints = Warp::Function::Get(*analysisFunction)->GetConstraints();
+ m_constraintsTable->SetMatchedConstraints(analysisConstraints);
+ }
- // Add all the constraints for the current function to the model.
- QVector<WarpConstraintItem *> constraints;
- for (const auto &constraint: function->GetConstraints())
- constraints.push_back(new WarpConstraintItem(constraint));
- m_constraintsTable->SetConstraints(constraints);
+ // Add all the constraints for the current function to the model.
+ QVector<WarpConstraintItem*> constraints;
+ for (const auto& constraint : function->GetConstraints())
+ constraints.push_back(new WarpConstraintItem(constraint));
+ m_constraintsTable->SetConstraints(constraints);
- // Add all the comments to the model.
- for (const auto &comment: function->GetComments())
- {
- m_commentsModel->appendRow({
- new QStandardItem(QString("0x%1").arg(comment.offset, 0, 16)),
- new QStandardItem(QString::fromStdString(comment.text))
- });
- }
+ // Add all the comments to the model.
+ for (const auto& comment : function->GetComments())
+ {
+ m_commentsModel->appendRow({new QStandardItem(QString("0x%1").arg(comment.offset, 0, 16)),
+ new QStandardItem(QString::fromStdString(comment.text))});
+ }
}
diff --git a/plugins/warp/ui/shared/function.h b/plugins/warp/ui/shared/function.h
index 90d52092..5cfaff75 100644
--- a/plugins/warp/ui/shared/function.h
+++ b/plugins/warp/ui/shared/function.h
@@ -10,159 +10,148 @@
class WarpFunctionItem : public QStandardItem
{
- Warp::Ref<Warp::Function> m_function;
+ Warp::Ref<Warp::Function> m_function;
- // Optional attached data used to show/manage the function.
- Warp::Ref<Warp::Container> m_container;
- std::optional<Warp::Source> m_source;
+ // Optional attached data used to show/manage the function.
+ Warp::Ref<Warp::Container> m_container;
+ std::optional<Warp::Source> m_source;
public:
- WarpFunctionItem(Warp::Ref<Warp::Function> function,
- BinaryNinja::Ref<BinaryNinja::Function> analysisFunction);
+ WarpFunctionItem(Warp::Ref<Warp::Function> function, BinaryNinja::Ref<BinaryNinja::Function> analysisFunction);
- void SetContainer(const Warp::Ref<Warp::Container> &container);
+ void SetContainer(const Warp::Ref<Warp::Container>& container);
- void SetSource(Warp::Source source);
+ void SetSource(Warp::Source source);
- Warp::Ref<Warp::Function> GetFunction() { return m_function; }
- Warp::Ref<Warp::Container> GetContainer() { return m_container; }
- std::optional<Warp::Source> GetSource() { return m_source; }
+ Warp::Ref<Warp::Function> GetFunction() { return m_function; }
+ Warp::Ref<Warp::Container> GetContainer() { return m_container; }
+ std::optional<Warp::Source> GetSource() { return m_source; }
};
class WarpFunctionItemModel : public QStandardItemModel
{
- Q_OBJECT
+ Q_OBJECT
- // The current matched function, used to highlight currently.
- Warp::Ref<Warp::Function> m_matchedFunction;
+ // The current matched function, used to highlight currently.
+ Warp::Ref<Warp::Function> m_matchedFunction;
- // Mapping of function start address to the row index.
- // This is used to identify unique functions for updating instead of resetting the entire model.
- std::unordered_map<uint64_t, int> m_insertableFunctionRows;
+ // Mapping of function start address to the row index.
+ // This is used to identify unique functions for updating instead of resetting the entire model.
+ std::unordered_map<uint64_t, int> m_insertableFunctionRows;
public:
- WarpFunctionItemModel(const QStringList &labels, QObject *parent);
+ WarpFunctionItemModel(const QStringList& labels, QObject* parent);
- static constexpr int COL_FUNCTION_ITEM = 0;
- static constexpr int COL_ADDRESS_ITEM = 1;
+ static constexpr int COL_FUNCTION_ITEM = 0;
+ static constexpr int COL_ADDRESS_ITEM = 1;
- void AppendFunction(WarpFunctionItem *item);
+ void AppendFunction(WarpFunctionItem* item);
- void InsertFunction(uint64_t address, WarpFunctionItem *item);
+ void InsertFunction(uint64_t address, WarpFunctionItem* item);
- WarpFunctionItem *GetItem(const QModelIndex &index) const;
+ WarpFunctionItem* GetItem(const QModelIndex& index) const;
- std::optional<uint64_t> GetAddress(const QModelIndex &index) const;
+ std::optional<uint64_t> GetAddress(const QModelIndex& index) const;
- QVariant data(const QModelIndex &index, int role) const override;
+ QVariant data(const QModelIndex& index, int role) const override;
- void SetMatchedFunction(const Warp::Ref<Warp::Function> &matchedFunction)
- {
- Warp::Ref<Warp::Function> previousMatchedFunction = m_matchedFunction;
- m_matchedFunction = matchedFunction;
+ void SetMatchedFunction(const Warp::Ref<Warp::Function>& matchedFunction)
+ {
+ Warp::Ref<Warp::Function> previousMatchedFunction = m_matchedFunction;
+ m_matchedFunction = matchedFunction;
- // Make sure to refresh the highlights so we don't keep the highlights from the previous function.
- if (previousMatchedFunction)
- {
- const QModelIndex topLeft = index(0, 0);
- const QModelIndex bottomRight = index(rowCount() - 1, 0);
- emit dataChanged(topLeft, bottomRight);
- }
- }
+ // Make sure to refresh the highlights so we don't keep the highlights from the previous function.
+ if (previousMatchedFunction)
+ {
+ const QModelIndex topLeft = index(0, 0);
+ const QModelIndex bottomRight = index(rowCount() - 1, 0);
+ emit dataChanged(topLeft, bottomRight);
+ }
+ }
};
class WarpFunctionFilterModel : public QSortFilterProxyModel
{
- Q_OBJECT
+ Q_OBJECT
public:
- WarpFunctionFilterModel(QObject *parent): QSortFilterProxyModel(parent)
- {
- }
+ WarpFunctionFilterModel(QObject* parent) : QSortFilterProxyModel(parent) {}
- ~WarpFunctionFilterModel() override = default;
+ ~WarpFunctionFilterModel() override = default;
- bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
- bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
+ bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override;
};
class WarpFunctionTableWidget : public QWidget, public FilterTarget
{
- Q_OBJECT
+ Q_OBJECT
- QTableView *m_table;
- WarpFunctionItemModel *m_model;
- WarpFunctionFilterModel *m_proxyModel;
- FilterEdit *m_filterEdit;
- FilteredView *m_filterView;
- QMenu *m_contextMenu;
- std::map<QString, std::function<void(WarpFunctionItem *, std::optional<uint64_t>)> > m_contextMenuActions;
+ QTableView* m_table;
+ WarpFunctionItemModel* m_model;
+ WarpFunctionFilterModel* m_proxyModel;
+ FilterEdit* m_filterEdit;
+ FilteredView* m_filterView;
+ QMenu* m_contextMenu;
+ std::map<QString, std::function<void(WarpFunctionItem*, std::optional<uint64_t>)>> m_contextMenuActions;
public:
- explicit WarpFunctionTableWidget(QWidget *parent = nullptr);
+ explicit WarpFunctionTableWidget(QWidget* parent = nullptr);
- // TODO: Invert this and provide OnCallback functions that wrap the connect call.
- QTableView *GetTableView() const { return m_table; }
- WarpFunctionItemModel *GetModel() const { return m_model; }
- WarpFunctionFilterModel *GetProxyModel() const { return m_proxyModel; }
+ // TODO: Invert this and provide OnCallback functions that wrap the connect call.
+ QTableView* GetTableView() const { return m_table; }
+ WarpFunctionItemModel* GetModel() const { return m_model; }
+ WarpFunctionFilterModel* GetProxyModel() const { return m_proxyModel; }
- void RegisterContextMenuAction(const QString &name,
- const std::function<void(WarpFunctionItem *, std::optional<uint64_t>)> &callback);
+ void RegisterContextMenuAction(
+ const QString& name, const std::function<void(WarpFunctionItem*, std::optional<uint64_t>)>& callback);
- void SetFunctions(QVector<WarpFunctionItem *> functions);
+ void SetFunctions(QVector<WarpFunctionItem*> functions);
- void InsertFunction(uint64_t address, WarpFunctionItem *function);
+ void InsertFunction(uint64_t address, WarpFunctionItem* function);
- void setFilter(const std::string &) override;
+ void setFilter(const std::string&) override;
- void scrollToFirstItem() override
- {
- }
+ void scrollToFirstItem() override {}
- void scrollToCurrentItem() override
- {
- }
+ void scrollToCurrentItem() override {}
- void selectFirstItem() override
- {
- }
+ void selectFirstItem() override {}
- void activateFirstItem() override
- {
- }
+ void activateFirstItem() override {}
};
class WarpFunctionInfoWidget : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
- Warp::Ref<Warp::Function> m_function;
- BinaryNinja::Ref<BinaryNinja::Function> m_analysisFunction;
+ Warp::Ref<Warp::Function> m_function;
+ BinaryNinja::Ref<BinaryNinja::Function> m_analysisFunction;
- // Optionally provide this information to show the source information.
- Warp::Ref<Warp::Container> m_container;
- std::string source;
+ // Optionally provide this information to show the source information.
+ Warp::Ref<Warp::Container> m_container;
+ std::string source;
- WarpConstraintTableWidget *m_constraintsTable;
+ WarpConstraintTableWidget* m_constraintsTable;
- QTableView *m_commentsTable;
- QStandardItemModel *m_commentsModel;
+ QTableView* m_commentsTable;
+ QStandardItemModel* m_commentsModel;
- QTableView *m_variablesTable;
+ QTableView* m_variablesTable;
public:
- explicit WarpFunctionInfoWidget(QWidget *parent = nullptr);
+ explicit WarpFunctionInfoWidget(QWidget* parent = nullptr);
- Warp::Ref<Warp::Function> GetFunction() { return m_function; }
- void SetFunction(Warp::Ref<Warp::Function> function) { m_function = function; };
+ Warp::Ref<Warp::Function> GetFunction() { return m_function; }
+ void SetFunction(Warp::Ref<Warp::Function> function) { m_function = function; };
- void SetAnalysisFunction(BinaryNinja::Ref<BinaryNinja::Function> analysisFunction)
- {
- m_analysisFunction = analysisFunction;
- };
- BinaryNinja::Ref<BinaryNinja::Function> GetAnalysisFunction() { return m_analysisFunction; }
+ void SetAnalysisFunction(BinaryNinja::Ref<BinaryNinja::Function> analysisFunction)
+ {
+ m_analysisFunction = analysisFunction;
+ };
+ BinaryNinja::Ref<BinaryNinja::Function> GetAnalysisFunction() { return m_analysisFunction; }
- // TODO: Make this private?
- void UpdateInfo();
+ // TODO: Make this private?
+ void UpdateInfo();
};
diff --git a/plugins/warp/ui/shared/misc.cpp b/plugins/warp/ui/shared/misc.cpp
index bbe3ab24..f84237c9 100644
--- a/plugins/warp/ui/shared/misc.cpp
+++ b/plugins/warp/ui/shared/misc.cpp
@@ -8,133 +8,135 @@
#include "render.h"
#include "theme.h"
-TokenData::TokenData(const std::string &name)
+TokenData::TokenData(const std::string& name)
{
- tokens.emplace_back(255, TextToken, name);
+ tokens.emplace_back(255, TextToken, name);
}
-TokenData::TokenData(const BinaryNinja::Type &type, const std::string& name)
+TokenData::TokenData(const BinaryNinja::Type& type, const std::string& name)
{
- for (const auto &token: type.GetTokensBeforeName())
- tokens.emplace_back(token);
- tokens.emplace_back(255, TextToken, " ");
- tokens.emplace_back(255, TextToken, name);
- for (const auto &token: type.GetTokensAfterName())
- tokens.emplace_back(token);
+ for (const auto& token : type.GetTokensBeforeName())
+ tokens.emplace_back(token);
+ tokens.emplace_back(255, TextToken, " ");
+ tokens.emplace_back(255, TextToken, name);
+ for (const auto& token : type.GetTokensAfterName())
+ tokens.emplace_back(token);
}
-void TokenDataDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void TokenDataDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- painter->save();
+ painter->save();
- auto tokenData = index.data(Qt::UserRole).value<TokenData>();
+ auto tokenData = index.data(Qt::UserRole).value<TokenData>();
- // Draw either the selected row or background color.
- QVariant background = index.data(Qt::BackgroundRole);
- if (background.canConvert<QBrush>())
- painter->fillRect(option.rect, background.value<QBrush>());
- else if (option.state & QStyle::State_Selected)
- painter->fillRect(option.rect, option.palette.highlight());
- painter->translate(option.rect.topLeft());
+ // Draw either the selected row or background color.
+ QVariant background = index.data(Qt::BackgroundRole);
+ if (background.canConvert<QBrush>())
+ painter->fillRect(option.rect, background.value<QBrush>());
+ else if (option.state & QStyle::State_Selected)
+ painter->fillRect(option.rect, option.palette.highlight());
+ painter->translate(option.rect.topLeft());
- auto renderContext = RenderContext(const_cast<QWidget *>(option.widget));
- renderContext.init(*painter);
- HighlightTokenState highlightState;
- renderContext.drawDisassemblyLine(*painter, 5, 5, {tokenData.tokens.begin(), tokenData.tokens.end()},
- highlightState);
+ auto renderContext = RenderContext(const_cast<QWidget*>(option.widget));
+ renderContext.init(*painter);
+ HighlightTokenState highlightState;
+ renderContext.drawDisassemblyLine(
+ *painter, 5, 5, {tokenData.tokens.begin(), tokenData.tokens.end()}, highlightState);
- painter->restore();
+ painter->restore();
}
-QSize TokenDataDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QSize TokenDataDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- auto tokenData = index.data(Qt::UserRole).value<TokenData>();
- auto renderContext = RenderContext(const_cast<QWidget *>(option.widget));
- QFontMetrics fontMetrics = QFontMetrics(renderContext.getFont());
- QString line = "";
- for (const auto &token: tokenData.tokens)
- line += token.text;
- int width = qMax(0, fontMetrics.horizontalAdvance(line));
- return QSize(width, renderContext.getFontHeight());
+ auto tokenData = index.data(Qt::UserRole).value<TokenData>();
+ auto renderContext = RenderContext(const_cast<QWidget*>(option.widget));
+ QFontMetrics fontMetrics = QFontMetrics(renderContext.getFont());
+ QString line = "";
+ for (const auto& token : tokenData.tokens)
+ line += token.text;
+ int width = qMax(0, fontMetrics.horizontalAdvance(line));
+ return QSize(width, renderContext.getFontHeight());
}
-void AddressColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void AddressColorDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- QStyleOptionViewItem opt = option;
- initStyleOption(&opt, index);
+ QStyleOptionViewItem opt = option;
+ initStyleOption(&opt, index);
- opt.font = getMonospaceFont(qobject_cast<QWidget *>(parent()));
- opt.palette.setColor(QPalette::Text, getThemeColor(BNThemeColor::AddressColor));
- opt.displayAlignment = Qt::AlignCenter | Qt::AlignVCenter;
+ opt.font = getMonospaceFont(qobject_cast<QWidget*>(parent()));
+ opt.palette.setColor(QPalette::Text, getThemeColor(BNThemeColor::AddressColor));
+ opt.displayAlignment = Qt::AlignCenter | Qt::AlignVCenter;
- QStyledItemDelegate::paint(painter, opt, index);
+ QStyledItemDelegate::paint(painter, opt, index);
}
-bool GenericTextFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+bool GenericTextFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
- auto filterString = filterRegularExpression().pattern();
- if (filterString.isEmpty())
- return true;
+ auto filterString = filterRegularExpression().pattern();
+ if (filterString.isEmpty())
+ return true;
- for (int i = 0; i < sourceModel()->columnCount(); i++)
- {
- auto index = sourceModel()->index(sourceRow, i, sourceParent);
- auto data = QRegularExpression::escape(index.data().toString());
- if (data.contains(filterString, Qt::CaseInsensitive))
- return true;
- }
+ for (int i = 0; i < sourceModel()->columnCount(); i++)
+ {
+ auto index = sourceModel()->index(sourceRow, i, sourceParent);
+ auto data = QRegularExpression::escape(index.data().toString());
+ if (data.contains(filterString, Qt::CaseInsensitive))
+ return true;
+ }
- return false;
+ return false;
}
-bool GenericTextFilterModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const
+bool GenericTextFilterModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const
{
- auto leftData = sourceLeft.data().toString();
- auto rightData = sourceRight.data().toString();
- return QString::localeAwareCompare(leftData, rightData) < 0;
+ auto leftData = sourceLeft.data().toString();
+ auto rightData = sourceRight.data().toString();
+ return QString::localeAwareCompare(leftData, rightData) < 0;
}
-ParsedQuery::ParsedQuery(const QString &rawQuery)
+ParsedQuery::ParsedQuery(const QString& rawQuery)
{
- query = rawQuery;
- qualifiers = {};
+ query = rawQuery;
+ qualifiers = {};
- // Regex capturing: key, and value (bare, quoted and unquoted)
- static QRegularExpression re(R"((^|\s)([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(?:\"([^\"]*)\"|'([^']*)'|(\S+)))",
- QRegularExpression::CaseInsensitiveOption);
+ // Regex capturing: key, and value (bare, quoted and unquoted)
+ static QRegularExpression re(R"((^|\s)([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(?:\"([^\"]*)\"|'([^']*)'|(\S+)))",
+ QRegularExpression::CaseInsensitiveOption);
- // Collect matches to remove later (from end to start to keep indices stable)
- struct Span
- {
- qsizetype start;
- qsizetype length;
- QString key;
- QString value;
- };
- QVector<Span> spans;
+ // Collect matches to remove later (from end to start to keep indices stable)
+ struct Span
+ {
+ qsizetype start;
+ qsizetype length;
+ QString key;
+ QString value;
+ };
+ QVector<Span> spans;
- auto it = re.globalMatch(rawQuery);
- while (it.hasNext())
- {
- const auto m = it.next();
- const QString key = m.captured(2).toLower();
- // Value can be in group 3 (double quotes), 4 (single quotes), or 5 (bare)
- QString val = m.captured(3);
- if (val.isNull() || val.isEmpty()) val = m.captured(4);
- if (val.isNull() || val.isEmpty()) val = m.captured(5);
- spans.push_back(Span{m.capturedStart(0), m.capturedLength(0), key, val});
- }
+ auto it = re.globalMatch(rawQuery);
+ while (it.hasNext())
+ {
+ const auto m = it.next();
+ const QString key = m.captured(2).toLower();
+ // Value can be in group 3 (double quotes), 4 (single quotes), or 5 (bare)
+ QString val = m.captured(3);
+ if (val.isNull() || val.isEmpty())
+ val = m.captured(4);
+ if (val.isNull() || val.isEmpty())
+ val = m.captured(5);
+ spans.push_back(Span {m.capturedStart(0), m.capturedLength(0), key, val});
+ }
- // Keep only the last value per key (last occurrence wins, do not accumulate)
- for (const auto &s: spans)
- qualifiers[s.key] = s.value;
+ // Keep only the last value per key (last occurrence wins, do not accumulate)
+ for (const auto& s : spans)
+ qualifiers[s.key] = s.value;
- // Remove matched spans from the text (replace with a single space to preserve boundaries)
- std::sort(spans.begin(), spans.end(), [](const Span &a, const Span &b) { return a.start > b.start; });
- for (const auto &s: spans)
- query.replace(s.start, s.length, QStringLiteral(" "));
+ // Remove matched spans from the text (replace with a single space to preserve boundaries)
+ std::sort(spans.begin(), spans.end(), [](const Span& a, const Span& b) { return a.start > b.start; });
+ for (const auto& s : spans)
+ query.replace(s.start, s.length, QStringLiteral(" "));
- // Normalize whitespace
- query = query.simplified();
+ // Normalize whitespace
+ query = query.simplified();
}
diff --git a/plugins/warp/ui/shared/misc.h b/plugins/warp/ui/shared/misc.h
index 57d71070..9d187594 100644
--- a/plugins/warp/ui/shared/misc.h
+++ b/plugins/warp/ui/shared/misc.h
@@ -14,103 +14,93 @@
// Used to serialize into the item data for rendering with TokenDataDelegate.
struct TokenData
{
- QVector<BinaryNinja::InstructionTextToken> tokens{};
+ QVector<BinaryNinja::InstructionTextToken> tokens {};
- TokenData() = default;
+ TokenData() = default;
- TokenData(const std::string& name);
+ TokenData(const std::string& name);
- TokenData(const BinaryNinja::Type &type, const std::string& name);
+ TokenData(const BinaryNinja::Type& type, const std::string& name);
- TokenData(const std::vector<BinaryNinja::InstructionTextToken> &tokens)
- {
- for (const auto &token: tokens)
- this->tokens.push_back(token);
- }
+ TokenData(const std::vector<BinaryNinja::InstructionTextToken>& tokens)
+ {
+ for (const auto& token : tokens)
+ this->tokens.push_back(token);
+ }
- TokenData(const BinaryNinja::InstructionTextToken &token)
- {
- this->tokens.push_back(token);
- }
+ TokenData(const BinaryNinja::InstructionTextToken& token) { this->tokens.push_back(token); }
- QString toString() const
- {
- QStringList tokenStrings;
- for (const auto &token: tokens)
- {
- tokenStrings.append(QString::fromStdString(token.text));
- }
- return tokenStrings.join("");
- }
+ QString toString() const
+ {
+ QStringList tokenStrings;
+ for (const auto& token : tokens)
+ {
+ tokenStrings.append(QString::fromStdString(token.text));
+ }
+ return tokenStrings.join("");
+ }
};
Q_DECLARE_METATYPE(TokenData)
class TokenDataDelegate final : public QStyledItemDelegate
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit TokenDataDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent)
- {
- }
+ explicit TokenDataDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};
class AddressColorDelegate final : public QStyledItemDelegate
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit AddressColorDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent)
- {
- }
+ explicit AddressColorDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};
class GenericTextFilterModel : public QSortFilterProxyModel
{
- Q_OBJECT
+ Q_OBJECT
public:
- GenericTextFilterModel(QObject *parent) : QSortFilterProxyModel(parent)
- {
- }
+ GenericTextFilterModel(QObject* parent) : QSortFilterProxyModel(parent) {}
- ~GenericTextFilterModel() override = default;
+ ~GenericTextFilterModel() override = default;
- bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
- bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
+ bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override;
};
// Used to parse qualifiers out of a user-supplied string (or "query")
struct ParsedQuery
{
- // The actual query, without the qualifiers like source:<uuid>
- QString query;
- // The qualifiers used to build other optional parts of the query.
- QHash<QString, QString> qualifiers;
+ // The actual query, without the qualifiers like source:<uuid>
+ QString query;
+ // The qualifiers used to build other optional parts of the query.
+ QHash<QString, QString> qualifiers;
- ParsedQuery(QString query, const QHash<QString, QString> &qualifiers)
- : query(std::move(query)), qualifiers(qualifiers)
- {
- }
+ ParsedQuery(QString query, const QHash<QString, QString>& qualifiers) :
+ query(std::move(query)), qualifiers(qualifiers)
+ {}
- explicit ParsedQuery(const QString &rawQuery);
+ explicit ParsedQuery(const QString& rawQuery);
- [[nodiscard]] std::optional<QString> GetValue(const QString &key) const
- {
- const auto it = qualifiers.constFind(key);
- if (it == qualifiers.constEnd() || it->isEmpty())
- return std::nullopt;
- return it.value();
- }
+ [[nodiscard]] std::optional<QString> GetValue(const QString& key) const
+ {
+ const auto it = qualifiers.constFind(key);
+ if (it == qualifiers.constEnd() || it->isEmpty())
+ return std::nullopt;
+ return it.value();
+ }
};
constexpr const char* ALLOWED_TAGS_SETTING = "warp.fetcher.allowedSourceTags";
@@ -118,24 +108,24 @@ constexpr const char* BATCH_SIZE_SETTING = "warp.fetcher.fetchBatchSize";
inline std::vector<Warp::SourceTag> GetAllowedTagsFromView(const BinaryViewRef& view)
{
- auto settings = BinaryNinja::Settings::Instance();
- if (!settings->Contains(ALLOWED_TAGS_SETTING))
- return {};
- return settings->Get<std::vector<std::string>>(ALLOWED_TAGS_SETTING, view);
+ auto settings = BinaryNinja::Settings::Instance();
+ if (!settings->Contains(ALLOWED_TAGS_SETTING))
+ return {};
+ return settings->Get<std::vector<std::string>>(ALLOWED_TAGS_SETTING, view);
}
inline void SetTagsToView(const BinaryViewRef& view, const std::vector<Warp::SourceTag>& tags)
{
- auto settings = BinaryNinja::Settings::Instance();
- if (!settings->Contains(ALLOWED_TAGS_SETTING))
- return;
- settings->Set(ALLOWED_TAGS_SETTING, tags, view);
+ auto settings = BinaryNinja::Settings::Instance();
+ if (!settings->Contains(ALLOWED_TAGS_SETTING))
+ return;
+ settings->Set(ALLOWED_TAGS_SETTING, tags, view);
}
inline int GetBatchSizeFromView(const BinaryViewRef& view)
{
- auto settings = BinaryNinja::Settings::Instance();
- if (!settings->Contains(BATCH_SIZE_SETTING))
- return 100;
- return settings->Get<uint64_t>(BATCH_SIZE_SETTING, view);
+ auto settings = BinaryNinja::Settings::Instance();
+ if (!settings->Contains(BATCH_SIZE_SETTING))
+ return 100;
+ return settings->Get<uint64_t>(BATCH_SIZE_SETTING, view);
} \ No newline at end of file
diff --git a/plugins/warp/ui/shared/search.cpp b/plugins/warp/ui/shared/search.cpp
index 1431e9b6..a852605e 100644
--- a/plugins/warp/ui/shared/search.cpp
+++ b/plugins/warp/ui/shared/search.cpp
@@ -2,300 +2,312 @@
#include "misc.h"
#include "../../../../../ui/mainwindow.h"
-QVariant WarpSearchModel::data(const QModelIndex &index, int role) const
+QVariant WarpSearchModel::data(const QModelIndex& index, int role) const
{
- if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
- return {};
- const auto &it = m_items[index.row()];
+ if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
+ return {};
+ const auto& it = m_items[index.row()];
- // Provide tokenized type for functions via UserRole for TokenDataDelegate
- if (role == Qt::UserRole && index.column() == DisplayCol)
- {
- if (it && it->GetKind() == WARPContainerSearchItemKindFunction)
- if (auto itemType = it->GetType(nullptr))
- return QVariant::fromValue(TokenData(*itemType, it->GetName()));
- return {};
- }
+ // Provide tokenized type for functions via UserRole for TokenDataDelegate
+ if (role == Qt::UserRole && index.column() == DisplayCol)
+ {
+ if (it && it->GetKind() == WARPContainerSearchItemKindFunction)
+ if (auto itemType = it->GetType(nullptr))
+ return QVariant::fromValue(TokenData(*itemType, it->GetName()));
+ return {};
+ }
- if (role == Qt::DisplayRole)
- {
- // TODO: We might want to run the demangler here on the name.
- switch (index.column())
- {
- case DisplayCol: return QString::fromStdString(it->GetName());
- case KindCol:
- {
- switch (it->GetKind())
- {
- case WARPContainerSearchItemKindFunction: return "Function";
- case WARPContainerSearchItemKindType: return "Type";
- case WARPContainerSearchItemKindSource: return "Source";
- case WARPContainerSearchItemKindSymbol: return "Symbol";
- default: return {};
- }
- }
- case SourceCol: return QString::fromStdString(it->GetSource().ToString());
- default: return {};
- }
- }
- return {};
+ if (role == Qt::DisplayRole)
+ {
+ // TODO: We might want to run the demangler here on the name.
+ switch (index.column())
+ {
+ case DisplayCol:
+ return QString::fromStdString(it->GetName());
+ case KindCol:
+ {
+ switch (it->GetKind())
+ {
+ case WARPContainerSearchItemKindFunction:
+ return "Function";
+ case WARPContainerSearchItemKindType:
+ return "Type";
+ case WARPContainerSearchItemKindSource:
+ return "Source";
+ case WARPContainerSearchItemKindSymbol:
+ return "Symbol";
+ default:
+ return {};
+ }
+ }
+ case SourceCol:
+ return QString::fromStdString(it->GetSource().ToString());
+ default:
+ return {};
+ }
+ }
+ return {};
}
QVariant WarpSearchModel::headerData(int section, Qt::Orientation orientation, int role) const
{
- if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
- {
- switch (section)
- {
- case DisplayCol: return "Item";
- case KindCol: return "Kind";
- case SourceCol: return "Source";
- default: return {};
- }
- }
- return {};
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ {
+ switch (section)
+ {
+ case DisplayCol:
+ return "Item";
+ case KindCol:
+ return "Kind";
+ case SourceCol:
+ return "Source";
+ default:
+ return {};
+ }
+ }
+ return {};
}
-void WarpSearchDelegate::paint(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void WarpSearchDelegate::paint(QPainter* p, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- // TODO: We actually still want the function icon, I think? So this should not early return and instead replace the name.
- // If model provided TokenData (e.g., for function types), render via TokenDataDelegate
- if (index.data(Qt::UserRole).canConvert<TokenData>())
- {
- TokenDataDelegate(parent()).paint(p, option, index);
- return;
- }
+ // TODO: We actually still want the function icon, I think? So this should not early return and instead replace the
+ // name. If model provided TokenData (e.g., for function types), render via TokenDataDelegate
+ if (index.data(Qt::UserRole).canConvert<TokenData>())
+ {
+ TokenDataDelegate(parent()).paint(p, option, index);
+ return;
+ }
- QStyleOptionViewItem opt(option);
- initStyleOption(&opt, index);
+ QStyleOptionViewItem opt(option);
+ initStyleOption(&opt, index);
- // We will draw the background/selection via style, and custom-draw icon (left) + text.
- const QWidget *w = option.widget;
- QStyle *style = w ? w->style() : QApplication::style();
+ // We will draw the background/selection via style, and custom-draw icon (left) + text.
+ const QWidget* w = option.widget;
+ QStyle* style = w ? w->style() : QApplication::style();
- // Let style draw the item background/selection etc., but not the default text
- QString originalText = opt.text;
- opt.text.clear();
- style->drawControl(QStyle::CE_ItemViewItem, &opt, p, w);
+ // Let style draw the item background/selection etc., but not the default text
+ QString originalText = opt.text;
+ opt.text.clear();
+ style->drawControl(QStyle::CE_ItemViewItem, &opt, p, w);
- // Retrieve text for DisplayCol
- const QString &text = originalText;
+ // Retrieve text for DisplayCol
+ const QString& text = originalText;
- // Retrieve kind text from the hidden KindCol
- const QModelIndex kindIndex = index.sibling(index.row(), WarpSearchModel::KindCol);
- const QString kind = kindIndex.isValid() ? kindIndex.data(Qt::DisplayRole).toString() : QString();
+ // Retrieve kind text from the hidden KindCol
+ const QModelIndex kindIndex = index.sibling(index.row(), WarpSearchModel::KindCol);
+ const QString kind = kindIndex.isValid() ? kindIndex.data(Qt::DisplayRole).toString() : QString();
- // Map kind -> icon (emoji for simplicity; replace with QIcon/QPixmap if desired)
- const QString icon = kindToIcon(kind);
+ // Map kind -> icon (emoji for simplicity; replace with QIcon/QPixmap if desired)
+ const QString icon = kindToIcon(kind);
- // Layout rects
- const QRect r = opt.rect;
- const int marginH = 8;
- const int iconSide = 16;
- const int spacing = 8;
+ // Layout rects
+ const QRect r = opt.rect;
+ const int marginH = 8;
+ const int iconSide = 16;
+ const int spacing = 8;
- // Reserve space on the left for the icon if we have one
- QRect iconRect = QRect(r.left() + marginH, r.center().y() - iconSide / 2, iconSide, iconSide);
- QRect textRect = r.adjusted((icon.isEmpty() ? marginH : (marginH + iconSide + spacing)), 0, -marginH, 0);
+ // Reserve space on the left for the icon if we have one
+ QRect iconRect = QRect(r.left() + marginH, r.center().y() - iconSide / 2, iconSide, iconSide);
+ QRect textRect = r.adjusted((icon.isEmpty() ? marginH : (marginH + iconSide + spacing)), 0, -marginH, 0);
- // Draw icon first (without clipping), then text with clipping
- p->save();
- if (!icon.isEmpty())
- {
- QFont iconFont = opt.font;
- iconFont.setPointSizeF(iconFont.pointSizeF() + 2);
- p->setFont(iconFont);
- p->setPen(
- opt.palette.color(opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text));
- p->drawText(iconRect, Qt::AlignCenter, icon);
- }
- p->restore();
+ // Draw icon first (without clipping), then text with clipping
+ p->save();
+ if (!icon.isEmpty())
+ {
+ QFont iconFont = opt.font;
+ iconFont.setPointSizeF(iconFont.pointSizeF() + 2);
+ p->setFont(iconFont);
+ p->setPen(opt.palette.color(opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text));
+ p->drawText(iconRect, Qt::AlignCenter, icon);
+ }
+ p->restore();
- // Draw elided text, vertically centered (with clipping so long strings don't overflow)
- p->save();
- p->setClipRect(textRect);
- const QFontMetrics fm(opt.font);
- const QString elided = fm.elidedText(text, Qt::ElideRight, textRect.width());
- p->setPen(opt.palette.color(opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text));
- p->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, elided);
- p->restore();
+ // Draw elided text, vertically centered (with clipping so long strings don't overflow)
+ p->save();
+ p->setClipRect(textRect);
+ const QFontMetrics fm(opt.font);
+ const QString elided = fm.elidedText(text, Qt::ElideRight, textRect.width());
+ p->setPen(opt.palette.color(opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text));
+ p->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, elided);
+ p->restore();
}
void WarpSearchRunner::fetchPage(std::size_t offset, std::size_t limit)
{
- const auto session = currentSession();
- auto container = m_container;
- auto q = m_queryText;
- auto src = m_source;
+ const auto session = currentSession();
+ auto container = m_container;
+ auto q = m_queryText;
+ auto src = m_source;
- // Runs search on Qt threadpool then moves the result to the main thread to update the UI.
- using TaskResult = std::pair<std::optional<Warp::ContainerSearchResponse>, QString>;
- QFutureWatcher<TaskResult> *watcher = new QFutureWatcher<TaskResult>(this);
- const auto future = QtConcurrent::run([container, q, src, offset, limit]() -> TaskResult {
- const Warp::ContainerSearchQuery query(q.toStdString(), offset, limit, src);
- auto respOpt = container->Search(query);
- // TODO: We may want to provide better errors in the future, e.g. BNWARPGetError
- if (!respOpt.has_value())
- return {std::nullopt, QStringLiteral("No response from container")};
- return {std::move(respOpt), QString()};
- });
- connect(watcher, &QFutureWatcher<TaskResult>::finished, this, [this, watcher, session]() {
- const TaskResult result = watcher->result();
- watcher->deleteLater();
- if (const auto &err = result.second; !err.isEmpty())
- emit pageError(session, err);
- else if (const auto &resp = result.first; resp.has_value())
- emit pageReady(session, *resp);
- });
- watcher->setFuture(future);
+ // Runs search on Qt threadpool then moves the result to the main thread to update the UI.
+ using TaskResult = std::pair<std::optional<Warp::ContainerSearchResponse>, QString>;
+ QFutureWatcher<TaskResult>* watcher = new QFutureWatcher<TaskResult>(this);
+ const auto future = QtConcurrent::run([container, q, src, offset, limit]() -> TaskResult {
+ const Warp::ContainerSearchQuery query(q.toStdString(), offset, limit, src);
+ auto respOpt = container->Search(query);
+ // TODO: We may want to provide better errors in the future, e.g. BNWARPGetError
+ if (!respOpt.has_value())
+ return {std::nullopt, QStringLiteral("No response from container")};
+ return {std::move(respOpt), QString()};
+ });
+ connect(watcher, &QFutureWatcher<TaskResult>::finished, this, [this, watcher, session]() {
+ const TaskResult result = watcher->result();
+ watcher->deleteLater();
+ if (const auto& err = result.second; !err.isEmpty())
+ emit pageError(session, err);
+ else if (const auto& resp = result.first; resp.has_value())
+ emit pageReady(session, *resp);
+ });
+ watcher->setFuture(future);
}
-WarpSearchWidget::WarpSearchWidget(Warp::Ref<Warp::Container> container, QWidget *parent) : QWidget(parent)
+WarpSearchWidget::WarpSearchWidget(Warp::Ref<Warp::Container> container, QWidget* parent) : QWidget(parent)
{
- m_model = new WarpSearchModel(this);
- m_runner = new WarpSearchRunner(container, this);
- auto *layout = new QVBoxLayout(this);
- m_query = new QLineEdit(this);
- m_status = new QLabel(this);
- m_view = new QTableView(this);
+ m_model = new WarpSearchModel(this);
+ m_runner = new WarpSearchRunner(container, this);
+ auto* layout = new QVBoxLayout(this);
+ m_query = new QLineEdit(this);
+ m_status = new QLabel(this);
+ m_view = new QTableView(this);
- // TODO: I am not necessarily a fan with how this looks.
- m_query->setPlaceholderText("Search… (Optionally filter with source:<uuid>)");
+ // TODO: I am not necessarily a fan with how this looks.
+ m_query->setPlaceholderText("Search… (Optionally filter with source:<uuid>)");
- // This is where we make the table not look like a table but instead a list.
- m_view->setShowGrid(false);
- m_view->verticalHeader()->setVisible(false);
- m_view->horizontalHeader()->setVisible(false);
- m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
- m_view->setSelectionMode(QAbstractItemView::SingleSelection);
- m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_view->setFocusPolicy(Qt::NoFocus);
+ // This is where we make the table not look like a table but instead a list.
+ m_view->setShowGrid(false);
+ m_view->verticalHeader()->setVisible(false);
+ m_view->horizontalHeader()->setVisible(false);
+ m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_view->setFocusPolicy(Qt::NoFocus);
- layout->addWidget(m_query);
- layout->addWidget(m_status);
- layout->addWidget(m_view);
+ layout->addWidget(m_query);
+ layout->addWidget(m_status);
+ layout->addWidget(m_view);
- m_view->setModel(m_model);
+ m_view->setModel(m_model);
- // Use a delegate to draw the DisplayCol text with an icon (optionally) aligned to the left.
- m_view->setItemDelegateForColumn(WarpSearchModel::DisplayCol, new WarpSearchDelegate(m_view));
+ // Use a delegate to draw the DisplayCol text with an icon (optionally) aligned to the left.
+ m_view->setItemDelegateForColumn(WarpSearchModel::DisplayCol, new WarpSearchDelegate(m_view));
- // Hide extra columns: only show the combined "Item" column; do not display source GUID.
- m_view->setColumnHidden(WarpSearchModel::KindCol, true);
- m_view->setColumnHidden(WarpSearchModel::SourceCol, true);
- m_view->horizontalHeader()->setSectionResizeMode(WarpSearchModel::DisplayCol, QHeaderView::Stretch);
+ // Hide extra columns: only show the combined "Item" column; do not display source GUID.
+ m_view->setColumnHidden(WarpSearchModel::KindCol, true);
+ m_view->setColumnHidden(WarpSearchModel::SourceCol, true);
+ m_view->horizontalHeader()->setSectionResizeMode(WarpSearchModel::DisplayCol, QHeaderView::Stretch);
- // Debounce user input
- m_debounce.setSingleShot(true);
- m_debounce.setInterval(SEARCH_DEBOUNCE_MS);
- connect(m_query, &QLineEdit::textChanged, this, [this](const QString &) { m_debounce.start(); });
+ // Debounce user input
+ m_debounce.setSingleShot(true);
+ m_debounce.setInterval(SEARCH_DEBOUNCE_MS);
+ connect(m_query, &QLineEdit::textChanged, this, [this](const QString&) { m_debounce.start(); });
- connect(&m_debounce, &QTimer::timeout, this, [this]() {
- const QString raw = m_query->text();
+ connect(&m_debounce, &QTimer::timeout, this, [this]() {
+ const QString raw = m_query->text();
- // Parse generic qualifiers and clean the free-text query
- const auto parsed = ParsedQuery(raw);
+ // Parse generic qualifiers and clean the free-text query
+ const auto parsed = ParsedQuery(raw);
- std::optional<Warp::Source> inlineSource = std::nullopt;
- if (const auto val = parsed.GetValue("source"); val.has_value())
- inlineSource = Warp::Source::FromString(val.value().toStdString());
- const auto effectiveSource = inlineSource.has_value() ? inlineSource : m_source;
- // TODO: Filter for tags and function guid.
+ std::optional<Warp::Source> inlineSource = std::nullopt;
+ if (const auto val = parsed.GetValue("source"); val.has_value())
+ inlineSource = Warp::Source::FromString(val.value().toStdString());
+ const auto effectiveSource = inlineSource.has_value() ? inlineSource : m_source;
+ // TODO: Filter for tags and function guid.
- m_runner->startSession(parsed.query, effectiveSource);
- m_model->beginNewSearch(SEARCH_PAGE_SIZE);
- });
+ m_runner->startSession(parsed.query, effectiveSource);
+ m_model->beginNewSearch(SEARCH_PAGE_SIZE);
+ });
- // Infinite scroll trigger
- connect(m_model, &WarpSearchModel::fetchMoreRequested, this, [this](std::size_t offset, std::size_t limit) {
- m_status->setText(QStringLiteral("Loading… (%1/%2)").arg(m_model->currentCount()).arg(m_model->total()));
- m_runner->fetchPage(offset, limit);
- });
+ // Infinite scroll trigger
+ connect(m_model, &WarpSearchModel::fetchMoreRequested, this, [this](std::size_t offset, std::size_t limit) {
+ m_status->setText(QStringLiteral("Loading… (%1/%2)").arg(m_model->currentCount()).arg(m_model->total()));
+ m_runner->fetchPage(offset, limit);
+ });
- // Append results if session still valid
- connect(m_runner, &WarpSearchRunner::pageReady, this,
- [this](std::uint64_t, const Warp::ContainerSearchResponse &resp) {
- m_model->appendResponse(resp);
- m_status->setText(
- QStringLiteral("Showing %1 of %2").arg(m_model->currentCount()).arg(m_model->total()));
- });
+ // Append results if session still valid
+ connect(
+ m_runner, &WarpSearchRunner::pageReady, this, [this](std::uint64_t, const Warp::ContainerSearchResponse& resp) {
+ m_model->appendResponse(resp);
+ m_status->setText(QStringLiteral("Showing %1 of %2").arg(m_model->currentCount()).arg(m_model->total()));
+ });
- // In cases like if the network container server goes down.
- connect(m_runner, &WarpSearchRunner::pageError, this,
- [this](std::uint64_t, const QString &msg) {
- m_status->setText(QStringLiteral("Error: %1").arg(msg));
- });
+ // In cases like if the network container server goes down.
+ connect(m_runner, &WarpSearchRunner::pageError, this, [this](std::uint64_t, const QString& msg) {
+ m_status->setText(QStringLiteral("Error: %1").arg(msg));
+ });
- // Add a context menu so that we can actually do actionable things with what we find.
- m_view->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(m_view, &QTableView::customContextMenuRequested, this, [this](const QPoint &pos) {
- const QModelIndex idx = m_view->indexAt(pos);
- if (!idx.isValid())
- return;
+ // Add a context menu so that we can actually do actionable things with what we find.
+ m_view->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_view, &QTableView::customContextMenuRequested, this, [this](const QPoint& pos) {
+ const QModelIndex idx = m_view->indexAt(pos);
+ if (!idx.isValid())
+ return;
- // TODO: Getting the current view here is really awful, but i dont care right now.
- auto ctx = MainWindow::activeContext();
- auto view = ctx->getCurrentView();
- auto binaryView = view->getData();
- auto viewFrame = ctx->getCurrentViewFrame();
- auto viewLocation = viewFrame->getViewLocation();
- auto func = viewLocation.getFunction();
+ // TODO: Getting the current view here is really awful, but i dont care right now.
+ auto ctx = MainWindow::activeContext();
+ auto view = ctx->getCurrentView();
+ auto binaryView = view->getData();
+ auto viewFrame = ctx->getCurrentViewFrame();
+ auto viewLocation = viewFrame->getViewLocation();
+ auto func = viewLocation.getFunction();
- // Retrieve the current architecture from the current function or try the current view.
- auto arch = binaryView->GetDefaultArchitecture();
- if (func)
- arch = func->GetArchitecture();
+ // Retrieve the current architecture from the current function or try the current view.
+ auto arch = binaryView->GetDefaultArchitecture();
+ if (func)
+ arch = func->GetArchitecture();
- const int row = idx.row();
- const auto item = m_model->itemAt(row);
- const auto itemType = item->GetType(arch);
- const auto itemFunc = item->GetFunction();
+ const int row = idx.row();
+ const auto item = m_model->itemAt(row);
+ const auto itemType = item->GetType(arch);
+ const auto itemFunc = item->GetFunction();
- QMenu menu(this);
- QAction *copySourceId = menu.addAction(tr("Copy Source"));
- QAction *searchSource = menu.addAction(tr("Search Source"));
- QAction *applyType = menu.addAction(tr("Apply Type"));
- QAction *applyFunction = menu.addAction(tr("Apply to Current Function"));
+ QMenu menu(this);
+ QAction* copySourceId = menu.addAction(tr("Copy Source"));
+ QAction* searchSource = menu.addAction(tr("Search Source"));
+ QAction* applyType = menu.addAction(tr("Apply Type"));
+ QAction* applyFunction = menu.addAction(tr("Apply to Current Function"));
- // We let users apply the type for types and functions (assuming the function has one)
- // if the user applies a function, we actually will set the user type for the current view location function.
- // For types, we will just throw it in the user types.
- applyType->setEnabled(itemType != nullptr);
- applyType->setVisible(applyType->isEnabled());
+ // We let users apply the type for types and functions (assuming the function has one)
+ // if the user applies a function, we actually will set the user type for the current view location function.
+ // For types, we will just throw it in the user types.
+ applyType->setEnabled(itemType != nullptr);
+ applyType->setVisible(applyType->isEnabled());
- applyFunction->setEnabled(func != nullptr && itemFunc);
- applyFunction->setVisible(applyFunction->isEnabled());
+ applyFunction->setEnabled(func != nullptr && itemFunc);
+ applyFunction->setVisible(applyFunction->isEnabled());
- QAction *chosen = menu.exec(m_view->viewport()->mapToGlobal(pos));
- if (!chosen)
- return;
- if (chosen == copySourceId)
- QApplication::clipboard()->setText(QString::fromStdString(item->GetSource().ToString()));
- else if (chosen == searchSource)
- {
- const QString sourceId = QString::fromStdString(item->GetSource().ToString());
- // TODO: This does not preserve the query that existed prior, doing so may result in duplicate source qualifiers.
- m_query->setText(QStringLiteral("source:\"%1\"").arg(sourceId));
- } else if (chosen == applyType)
- {
- if (func && item->GetKind() == WARPContainerSearchItemKindFunction)
- {
- func->SetUserType(itemType);
- binaryView->UpdateAnalysis();
- }
- else
- binaryView->DefineUserType(item->GetName(), itemType);
- } else if (chosen == applyFunction)
- {
- itemFunc->Apply(*func);
- binaryView->UpdateAnalysis();
- }
- });
+ QAction* chosen = menu.exec(m_view->viewport()->mapToGlobal(pos));
+ if (!chosen)
+ return;
+ if (chosen == copySourceId)
+ QApplication::clipboard()->setText(QString::fromStdString(item->GetSource().ToString()));
+ else if (chosen == searchSource)
+ {
+ const QString sourceId = QString::fromStdString(item->GetSource().ToString());
+ // TODO: This does not preserve the query that existed prior, doing so may result in duplicate source
+ // qualifiers.
+ m_query->setText(QStringLiteral("source:\"%1\"").arg(sourceId));
+ }
+ else if (chosen == applyType)
+ {
+ if (func && item->GetKind() == WARPContainerSearchItemKindFunction)
+ {
+ func->SetUserType(itemType);
+ binaryView->UpdateAnalysis();
+ }
+ else
+ binaryView->DefineUserType(item->GetName(), itemType);
+ }
+ else if (chosen == applyFunction)
+ {
+ itemFunc->Apply(*func);
+ binaryView->UpdateAnalysis();
+ }
+ });
- // This will start searching with an empty query once the widget is constructed. This is a decent behavior considering
- // we should be heavily caching queries such as an empty one.
- m_debounce.start();
+ // This will start searching with an empty query once the widget is constructed. This is a decent behavior
+ // considering we should be heavily caching queries such as an empty one.
+ m_debounce.start();
}
diff --git a/plugins/warp/ui/shared/search.h b/plugins/warp/ui/shared/search.h
index 86c90942..8510edcc 100644
--- a/plugins/warp/ui/shared/search.h
+++ b/plugins/warp/ui/shared/search.h
@@ -29,206 +29,201 @@ constexpr auto SEARCH_DEBOUNCE_MS = 350;
// Table model showing a paginated list of SearchItem.
class WarpSearchModel final : public QAbstractTableModel
{
- Q_OBJECT
+ Q_OBJECT
public:
- enum Columns : int
- {
- DisplayCol = 0,
- KindCol,
- SourceCol,
- ColumnCount
- };
+ enum Columns : int
+ {
+ DisplayCol = 0,
+ KindCol,
+ SourceCol,
+ ColumnCount
+ };
- explicit WarpSearchModel(QObject *parent = nullptr)
- : QAbstractTableModel(parent)
- {
- }
+ explicit WarpSearchModel(QObject* parent = nullptr) : QAbstractTableModel(parent) {}
- int rowCount(const QModelIndex &parent) const override
- {
- if (parent.isValid()) return 0;
- return m_items.size();
- }
+ int rowCount(const QModelIndex& parent) const override
+ {
+ if (parent.isValid())
+ return 0;
+ return m_items.size();
+ }
- int columnCount(const QModelIndex &parent) const override
- {
- Q_UNUSED(parent);
- return ColumnCount;
- }
+ int columnCount(const QModelIndex& parent) const override
+ {
+ Q_UNUSED(parent);
+ return ColumnCount;
+ }
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
- // Begin a new search session: clears all current items and resets counters.
- Q_INVOKABLE void beginNewSearch(std::size_t pageSize = SEARCH_PAGE_SIZE)
- {
- beginResetModel();
- m_items.clear();
- m_total = 0;
- m_pageSize = pageSize;
- endResetModel();
- emit cleared();
- // Immediately ask for the first page from offset 0
- emit fetchMoreRequested(0, m_pageSize);
- }
+ // Begin a new search session: clears all current items and resets counters.
+ Q_INVOKABLE void beginNewSearch(std::size_t pageSize = SEARCH_PAGE_SIZE)
+ {
+ beginResetModel();
+ m_items.clear();
+ m_total = 0;
+ m_pageSize = pageSize;
+ endResetModel();
+ emit cleared();
+ // Immediately ask for the first page from offset 0
+ emit fetchMoreRequested(0, m_pageSize);
+ }
- // Append results from a Warp::ContainerSearchResponse (infinite scroll, no replacement).
- void appendResponse(const Warp::ContainerSearchResponse &resp)
- {
- // Update total first (so canFetchMore reflects new value)
- m_total = resp.total;
- if (resp.items.empty())
- {
- emit responseUpdated(currentCount(), m_total);
- return;
- }
- const int begin = m_items.size();
- const int end = begin + static_cast<int>(resp.items.size()) - 1;
- beginInsertRows(QModelIndex(), begin, end);
- for (const auto &refItem: resp.items)
- m_items.push_back(refItem);
- endInsertRows();
- emit responseUpdated(currentCount(), m_total);
- }
+ // Append results from a Warp::ContainerSearchResponse (infinite scroll, no replacement).
+ void appendResponse(const Warp::ContainerSearchResponse& resp)
+ {
+ // Update total first (so canFetchMore reflects new value)
+ m_total = resp.total;
+ if (resp.items.empty())
+ {
+ emit responseUpdated(currentCount(), m_total);
+ return;
+ }
+ const int begin = m_items.size();
+ const int end = begin + static_cast<int>(resp.items.size()) - 1;
+ beginInsertRows(QModelIndex(), begin, end);
+ for (const auto& refItem : resp.items)
+ m_items.push_back(refItem);
+ endInsertRows();
+ emit responseUpdated(currentCount(), m_total);
+ }
- // Qt's infinite scroll hooks: the view will call these when near the end.
- bool canFetchMore(const QModelIndex &parent) const override
- {
- Q_UNUSED(parent);
- return static_cast<std::size_t>(m_items.size()) < m_total;
- }
+ // Qt's infinite scroll hooks: the view will call these when near the end.
+ bool canFetchMore(const QModelIndex& parent) const override
+ {
+ Q_UNUSED(parent);
+ return static_cast<std::size_t>(m_items.size()) < m_total;
+ }
- void fetchMore(const QModelIndex &parent) override
- {
- Q_UNUSED(parent);
- if (!canFetchMore({}))
- return;
- const std::size_t nextOffset = m_items.size();
- emit fetchMoreRequested(nextOffset, m_pageSize);
- }
+ void fetchMore(const QModelIndex& parent) override
+ {
+ Q_UNUSED(parent);
+ if (!canFetchMore({}))
+ return;
+ const std::size_t nextOffset = m_items.size();
+ emit fetchMoreRequested(nextOffset, m_pageSize);
+ }
- // Convenience accessors.
- std::size_t total() const { return m_total; }
- int currentCount() const { return m_items.size(); }
- void setPageSize(std::size_t pageSize) { m_pageSize = pageSize; }
+ // Convenience accessors.
+ std::size_t total() const { return m_total; }
+ int currentCount() const { return m_items.size(); }
+ void setPageSize(std::size_t pageSize) { m_pageSize = pageSize; }
- Q_INVOKABLE Warp::Ref<Warp::ContainerSearchItem> itemAt(int row) const
- {
- if (row < 0 || row >= m_items.size())
- return {};
- return m_items[row];
- }
+ Q_INVOKABLE Warp::Ref<Warp::ContainerSearchItem> itemAt(int row) const
+ {
+ if (row < 0 || row >= m_items.size())
+ return {};
+ return m_items[row];
+ }
signals:
- // Emitted when model is cleared for a new query.
- void cleared();
+ // Emitted when model is cleared for a new query.
+ void cleared();
- // Emitted after items are appended or totals updated.
- void responseUpdated(int currentCount, std::size_t total);
+ // Emitted after items are appended or totals updated.
+ void responseUpdated(int currentCount, std::size_t total);
- // Request the next page; connect this to your async search runner.
- void fetchMoreRequested(std::size_t offset, std::size_t limit);
+ // Request the next page; connect this to your async search runner.
+ void fetchMoreRequested(std::size_t offset, std::size_t limit);
private:
- QVector<Warp::Ref<Warp::ContainerSearchItem> > m_items;
- std::size_t m_total = 0;
- std::size_t m_pageSize = SEARCH_PAGE_SIZE;
+ QVector<Warp::Ref<Warp::ContainerSearchItem>> m_items;
+ std::size_t m_total = 0;
+ std::size_t m_pageSize = SEARCH_PAGE_SIZE;
};
// A delegate to render the DisplayCol text with an icon (mapped from KindCol) on the right.
class WarpSearchDelegate final : public QStyledItemDelegate
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit WarpSearchDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent)
- {
- }
+ explicit WarpSearchDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
- {
- // Base text size + space for an icon on the right
- const QSize base = QStyledItemDelegate::sizeHint(option, index);
- const int iconSide = 16;
- return QSize(base.width(), qMax(base.height(), iconSide + 4)); // keep row height >= icon
- }
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
+ {
+ // Base text size + space for an icon on the right
+ const QSize base = QStyledItemDelegate::sizeHint(option, index);
+ const int iconSide = 16;
+ return QSize(base.width(), qMax(base.height(), iconSide + 4)); // keep row height >= icon
+ }
- void paint(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ void paint(QPainter* p, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
private:
- static QString kindToIcon(const QString &kind)
- {
- // Example mapping; extend as needed
- if (kind.compare(QStringLiteral("Function"), Qt::CaseInsensitive) == 0)
- return QStringLiteral("ƒ");
- if (kind.compare(QStringLiteral("Type"), Qt::CaseInsensitive) == 0)
- return QStringLiteral("𝑇");
- if (kind.compare(QStringLiteral("Source"), Qt::CaseInsensitive) == 0)
- return QStringLiteral("📦");
- // Default: no icon
- return {};
- }
+ static QString kindToIcon(const QString& kind)
+ {
+ // Example mapping; extend as needed
+ if (kind.compare(QStringLiteral("Function"), Qt::CaseInsensitive) == 0)
+ return QStringLiteral("ƒ");
+ if (kind.compare(QStringLiteral("Type"), Qt::CaseInsensitive) == 0)
+ return QStringLiteral("𝑇");
+ if (kind.compare(QStringLiteral("Source"), Qt::CaseInsensitive) == 0)
+ return QStringLiteral("📦");
+ // Default: no icon
+ return {};
+ }
};
class WarpSearchRunner : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit WarpSearchRunner(Warp::Ref<Warp::Container> container, QObject *parent = nullptr)
- : QObject(parent), m_container(std::move(container))
- {
- }
+ explicit WarpSearchRunner(Warp::Ref<Warp::Container> container, QObject* parent = nullptr) :
+ QObject(parent), m_container(std::move(container))
+ {}
signals:
- // Emitted on the UI thread after the worker finishes
- void pageReady(std::uint64_t sessionId, Warp::ContainerSearchResponse resp);
+ // Emitted on the UI thread after the worker finishes
+ void pageReady(std::uint64_t sessionId, Warp::ContainerSearchResponse resp);
- void pageError(std::uint64_t sessionId, QString message);
+ void pageError(std::uint64_t sessionId, QString message);
public slots:
- // Start a new logical search session (new query or new filters)
- void startSession(QString queryText, const std::optional<Warp::Source> &source)
- {
- m_queryText = std::move(queryText);
- m_source = source;
- m_sessionId.fetchAndAddRelaxed(1);
- }
+ // Start a new logical search session (new query or new filters)
+ void startSession(QString queryText, const std::optional<Warp::Source>& source)
+ {
+ m_queryText = std::move(queryText);
+ m_source = source;
+ m_sessionId.fetchAndAddRelaxed(1);
+ }
- // Fetch a page for the current session. Safe to call multiple times (infinite scroll).
- void fetchPage(std::size_t offset, std::size_t limit);
+ // Fetch a page for the current session. Safe to call multiple times (infinite scroll).
+ void fetchPage(std::size_t offset, std::size_t limit);
private:
- std::uint64_t currentSession() const { return m_sessionId.loadRelaxed(); }
+ std::uint64_t currentSession() const { return m_sessionId.loadRelaxed(); }
- Warp::Ref<Warp::Container> m_container;
- QAtomicInteger<quint64> m_sessionId{0};
- QString m_queryText;
- std::optional<Warp::Source> m_source;
+ Warp::Ref<Warp::Container> m_container;
+ QAtomicInteger<quint64> m_sessionId {0};
+ QString m_queryText;
+ std::optional<Warp::Source> m_source;
};
class WarpSearchWidget : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit WarpSearchWidget(Warp::Ref<Warp::Container> container, QWidget *parent = nullptr);
+ explicit WarpSearchWidget(Warp::Ref<Warp::Container> container, QWidget* parent = nullptr);
- void setSourceFilter(const std::optional<Warp::Source> &src)
- {
- m_source = src;
- m_debounce.start();
- }
+ void setSourceFilter(const std::optional<Warp::Source>& src)
+ {
+ m_source = src;
+ m_debounce.start();
+ }
private:
- WarpSearchModel *m_model;
- WarpSearchRunner *m_runner;
- QLineEdit *m_query;
- QLabel *m_status;
- QTableView *m_view;
- QTimer m_debounce;
- // Source to filter for if no source is provided in the search.
- std::optional<Warp::Source> m_source;
+ WarpSearchModel* m_model;
+ WarpSearchRunner* m_runner;
+ QLineEdit* m_query;
+ QLabel* m_status;
+ QTableView* m_view;
+ QTimer m_debounce;
+ // Source to filter for if no source is provided in the search.
+ std::optional<Warp::Source> m_source;
};