#pragma once #include #include #include "binaryninjaapi.h" #include "constraint.h" #include "filter.h" #include "misc.h" #include "warp.h" class WarpFunctionItem : public QStandardItem { Warp::Ref m_function; // Optional attached data used to show/manage the function. Warp::Ref m_container; std::optional m_source; public: WarpFunctionItem(Warp::Ref function, BinaryNinja::Ref analysisFunction); void SetContainer(const Warp::Ref& container); void SetSource(Warp::Source source); Warp::Ref GetFunction() { return m_function; } Warp::Ref GetContainer() { return m_container; } std::optional GetSource() { return m_source; } }; class WarpFunctionItemModel : public QStandardItemModel { Q_OBJECT // The current matched function, used to highlight currently. Warp::Ref 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 m_insertableFunctionRows; public: WarpFunctionItemModel(const QStringList& labels, QObject* parent); static constexpr int COL_FUNCTION_ITEM = 0; static constexpr int COL_ADDRESS_ITEM = 1; void AppendFunction(WarpFunctionItem* item); void InsertFunction(uint64_t address, WarpFunctionItem* item); void RemoveFunction(uint64_t address); WarpFunctionItem* GetItem(const QModelIndex& index) const; std::optional GetAddress(const QModelIndex& index) const; QVariant data(const QModelIndex& index, int role) const override; void SetMatchedFunction(const Warp::Ref& matchedFunction) { Warp::Ref 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); } } Warp::Ref GetMatchedFunction() const { return m_matchedFunction; } }; class WarpFunctionFilterModel : public QSortFilterProxyModel { Q_OBJECT public: WarpFunctionFilterModel(QObject* parent) : QSortFilterProxyModel(parent) {} ~WarpFunctionFilterModel() override = default; bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override; }; class WarpFunctionTableWidget : public QWidget, public FilterTarget { Q_OBJECT QTableView* m_table; WarpFunctionItemModel* m_model; WarpFunctionFilterModel* m_proxyModel; FilterEdit* m_filterEdit; FilteredView* m_filterView; QMenu* m_contextMenu; std::map)>> m_contextMenuActions; std::map)>> m_contextMenuIsValid; public: 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; } void RegisterContextMenuAction( const QString& name, const std::function)>& callback); void RegisterContextMenuAction(const QString& name, const std::function)>& callback, const std::function)>& isValid); void SetFunctions(QVector functions); void InsertFunction(uint64_t address, WarpFunctionItem* function); void RemoveFunction(uint64_t address); void setFilter(const std::string&, FilterOptions options) override; void scrollToFirstItem() override {} void scrollToCurrentItem() override {} void ensureSelection() override {} void activateSelection() override {} }; class WarpFunctionInfoWidget : public QWidget { Q_OBJECT Warp::Ref m_function; BinaryNinja::Ref m_analysisFunction; // Optionally provide this information to show the source information. Warp::Ref m_container; std::string source; WarpConstraintTableWidget* m_constraintsTable; QTableView* m_commentsTable; QStandardItemModel* m_commentsModel; QTableView* m_variablesTable; public: explicit WarpFunctionInfoWidget(QWidget* parent = nullptr); Warp::Ref GetFunction() { return m_function; } void SetFunction(Warp::Ref function) { m_function = function; }; void SetAnalysisFunction(BinaryNinja::Ref analysisFunction) { m_analysisFunction = analysisFunction; }; BinaryNinja::Ref GetAnalysisFunction() { return m_analysisFunction; } // TODO: Make this private? void UpdateInfo(); };