diff options
| author | Josh Ferrell <josh@vector35.com> | 2024-05-08 16:19:26 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2024-05-14 14:31:46 -0400 |
| commit | cb407be11b08c1c427fcf33a49974155e522e14a (patch) | |
| tree | 4c99b4230e375517a4742a6ac3d4bc95c9e6bd23 | |
| parent | 3c28d7e6eaa84041ec0fe5352a618759c13e6cb3 (diff) | |
Ref count undo objects
| -rw-r--r-- | binaryninjaapi.h | 38 | ||||
| -rw-r--r-- | binaryninjacore.h | 48 | ||||
| -rw-r--r-- | database.cpp | 28 | ||||
| -rw-r--r-- | filemetadata.cpp | 94 | ||||
| -rw-r--r-- | ui/historyview.h | 54 | ||||
| -rw-r--r-- | ui/uitypes.h | 2 | ||||
| -rw-r--r-- | undoaction.cpp | 62 |
7 files changed, 187 insertions, 139 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a9aba0af..791acf07 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2330,7 +2330,7 @@ namespace BinaryNinja { const BNInstructionTextToken* tokens, size_t count); }; - struct UndoEntry; + class UndoEntry; /*! @@ -2399,8 +2399,8 @@ namespace BinaryNinja { DataBuffer GetFileContents(); DataBuffer GetFileContentsHash(); DataBuffer GetUndoData(); - std::vector<UndoEntry> GetUndoEntries(); - std::vector<UndoEntry> GetUndoEntries(const std::function<bool(size_t, size_t)>& progress); + std::vector<Ref<UndoEntry>> GetUndoEntries(); + std::vector<Ref<UndoEntry>> GetUndoEntries(const std::function<bool(size_t, size_t)>& progress); Ref<KeyValueStore> ReadData(); Ref<KeyValueStore> ReadData(const std::function<bool(size_t, size_t)>& progress); bool StoreData(const Ref<KeyValueStore>& data, const std::function<bool(size_t, size_t)>& progress); @@ -2744,31 +2744,31 @@ namespace BinaryNinja { void EndBulkOperation(); }; - /*! \ingroup undo */ - struct UndoAction + class UndoAction : public CoreRefCountObject<BNUndoAction, BNNewUndoActionReference, BNFreeUndoAction> { - BNActionType actionType; - std::string summaryText; - std::vector<InstructionTextToken> summaryTokens; + public: + UndoAction(BNUndoAction* action); - UndoAction() {}; - UndoAction(const BNUndoAction& action); + std::string GetSummaryText(); + std::vector<InstructionTextToken> GetSummary(); }; /*! \ingroup undo */ - struct UndoEntry + class UndoEntry : public CoreRefCountObject<BNUndoEntry, BNNewUndoEntryReference, BNFreeUndoEntry> { - Ref<User> user; - std::string id; - std::vector<UndoAction> actions; - uint64_t timestamp; + public: + UndoEntry(BNUndoEntry* entry); + + std::string GetId(); + std::vector<Ref<UndoAction>> GetActions(); + uint64_t GetTimestamp(); }; /*! @@ -2995,10 +2995,10 @@ namespace BinaryNinja { bool Redo(); std::vector<Ref<User>> GetUsers(); - std::vector<UndoEntry> GetUndoEntries(); - std::vector<UndoEntry> GetRedoEntries(); - std::optional<UndoEntry> GetLastUndoEntry(); - std::optional<UndoEntry> GetLastRedoEntry(); + std::vector<Ref<UndoEntry>> GetUndoEntries(); + std::vector<Ref<UndoEntry>> GetRedoEntries(); + Ref<UndoEntry> GetLastUndoEntry(); + Ref<UndoEntry> GetLastRedoEntry(); std::optional<std::string> GetLastUndoEntryTitle(); std::optional<std::string> GetLastRedoEntryTitle(); void ClearUndoEntries(); diff --git a/binaryninjacore.h b/binaryninjacore.h index 2eee74e9..04612d43 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -293,6 +293,8 @@ extern "C" typedef struct BNAnalysisMergeConflict BNAnalysisMergeConflict; typedef struct BNTypeArchiveMergeConflict BNTypeArchiveMergeConflict; typedef struct BNCollaborationLazyT BNCollaborationLazyT; + typedef struct BNUndoAction BNUndoAction; + typedef struct BNUndoEntry BNUndoEntry; //! Console log levels typedef enum BNLogLevel @@ -2193,24 +2195,6 @@ extern "C" uint64_t addr; } BNTagReference; - typedef struct BNUndoAction - { - BNActionType actionType; - char* summaryText; - BNInstructionTextToken* summaryTokens; - size_t summaryTokenCount; - } BNUndoAction; - - typedef struct BNUndoEntry - { - bool valid; - BNUser* user; - char* id; - BNUndoAction* actions; - uint64_t actionCount; - uint64_t timestamp; - } BNUndoEntry; - typedef struct BNCallingConventionWithConfidence { BNCallingConvention* convention; @@ -3649,13 +3633,27 @@ extern "C" BINARYNINJACOREAPI BNKeyValueStore* BNReadSnapshotDataWithProgress( BNSnapshot* snapshot, void* ctxt, bool (*progress)(void* ctxt, size_t progress, size_t total)); BINARYNINJACOREAPI BNDataBuffer* BNGetSnapshotUndoData(BNSnapshot* snapshot); - BINARYNINJACOREAPI BNUndoEntry* BNGetSnapshotUndoEntries(BNSnapshot* snapshot, size_t* count); - BINARYNINJACOREAPI BNUndoEntry* BNGetSnapshotUndoEntriesWithProgress( + BINARYNINJACOREAPI BNUndoEntry** BNGetSnapshotUndoEntries(BNSnapshot* snapshot, size_t* count); + BINARYNINJACOREAPI BNUndoEntry** BNGetSnapshotUndoEntriesWithProgress( BNSnapshot* snapshot, void* ctxt, bool (*progress)(void* ctxt, size_t progress, size_t total), size_t* count); BINARYNINJACOREAPI bool BNSnapshotHasAncestor(BNSnapshot* snapshot, BNSnapshot* other); BINARYNINJACOREAPI bool BNSnapshotStoreData(BNSnapshot* snapshot, BNKeyValueStore* data, void* ctxt, BNProgressFunction progress); + // Undo actions + BINARYNINJACOREAPI BNUndoAction* BNNewUndoActionReference(BNUndoAction* action); + BINARYNINJACOREAPI void BNFreeUndoAction(BNUndoAction* action); + BINARYNINJACOREAPI void BNFreeUndoActionList(BNUndoAction** actions, size_t count); + BINARYNINJACOREAPI char* BNUndoActionGetSummaryText(BNUndoAction* action); + BINARYNINJACOREAPI BNInstructionTextToken* BNUndoActionGetSummary(BNUndoAction* action, size_t* tokenCount); + + // Undo entries + BINARYNINJACOREAPI BNUndoEntry* BNNewUndoEntryReference(BNUndoEntry* entry); + BINARYNINJACOREAPI void BNFreeUndoEntry(BNUndoEntry* entry); + BINARYNINJACOREAPI void BNFreeUndoEntryList(BNUndoEntry** entrys, size_t count); + BINARYNINJACOREAPI char* BNUndoEntryGetId(BNUndoEntry* entry); + BINARYNINJACOREAPI BNUndoAction** BNUndoEntryGetActions(BNUndoEntry* entry, size_t* count); + BINARYNINJACOREAPI uint64_t BNUndoEntryGetTimestamp(BNUndoEntry* entry); BINARYNINJACOREAPI bool BNRebase(BNBinaryView* data, uint64_t address); BINARYNINJACOREAPI bool BNRebaseWithProgress( @@ -3683,13 +3681,13 @@ extern "C" BINARYNINJACOREAPI bool BNCanRedo(BNFileMetadata* file); BINARYNINJACOREAPI bool BNRedo(BNFileMetadata* file); - BINARYNINJACOREAPI BNUndoEntry* BNGetUndoEntries(BNFileMetadata* file, size_t* count); - BINARYNINJACOREAPI BNUndoEntry* BNGetRedoEntries(BNFileMetadata* file, size_t* count); - BINARYNINJACOREAPI BNUndoEntry BNGetLastUndoEntry(BNFileMetadata* file); - BINARYNINJACOREAPI BNUndoEntry BNGetLastRedoEntry(BNFileMetadata* file); + BINARYNINJACOREAPI BNUndoEntry** BNGetUndoEntries(BNFileMetadata* file, size_t* count); + BINARYNINJACOREAPI BNUndoEntry** BNGetRedoEntries(BNFileMetadata* file, size_t* count); + BINARYNINJACOREAPI BNUndoEntry* BNGetLastUndoEntry(BNFileMetadata* file); + BINARYNINJACOREAPI BNUndoEntry* BNGetLastRedoEntry(BNFileMetadata* file); BINARYNINJACOREAPI char* BNGetLastUndoEntryTitle(BNFileMetadata* file); BINARYNINJACOREAPI char* BNGetLastRedoEntryTitle(BNFileMetadata* file); - BINARYNINJACOREAPI void BNFreeUndoEntries(BNUndoEntry* entries, size_t count); + BINARYNINJACOREAPI void BNFreeUndoEntries(BNUndoEntry** entries, size_t count); BINARYNINJACOREAPI void BNClearUndoEntries(BNFileMetadata* file); BINARYNINJACOREAPI BNUser* BNNewUserReference(BNUser* user); diff --git a/database.cpp b/database.cpp index 26802f29..f3a6072f 100644 --- a/database.cpp +++ b/database.cpp @@ -298,41 +298,31 @@ DataBuffer Snapshot::GetUndoData() } -vector<UndoEntry> Snapshot::GetUndoEntries() +vector<Ref<UndoEntry>> Snapshot::GetUndoEntries() { return GetUndoEntries([](size_t, size_t) { return true; }); } -vector<UndoEntry> Snapshot::GetUndoEntries(const std::function<bool(size_t, size_t)>& progress) +vector<Ref<UndoEntry>> Snapshot::GetUndoEntries(const std::function<bool(size_t, size_t)>& progress) { ProgressContext pctxt; pctxt.callback = progress; - size_t numEntries; - BNUndoEntry* entries = BNGetSnapshotUndoEntriesWithProgress(m_object, &pctxt, ProgressCallback, &numEntries); + size_t count; + BNUndoEntry** entries = BNGetSnapshotUndoEntriesWithProgress(m_object, &pctxt, ProgressCallback, &count); if (entries == nullptr) { - throw DatabaseException("BNGetSnapshotUndoEntries"); + throw DatabaseException("BNGetSnapshotUndoEntriesWithProgress"); } - vector<UndoEntry> result; - result.reserve(numEntries); - for (size_t i = 0; i < numEntries; i++) + vector<Ref<UndoEntry>> result; + for (size_t i = 0; i < count; i++) { - UndoEntry temp; - temp.timestamp = entries[i].timestamp; - temp.id = entries[i].id; - temp.user = new User(BNNewUserReference(entries[i].user)); - size_t actionCount = entries[i].actionCount; - for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) - { - temp.actions.emplace_back(entries[i].actions[actionIndex]); - } - result.push_back(temp); + result.push_back(new UndoEntry(BNNewUndoEntryReference(entries[i]))); } + BNFreeUndoEntryList(entries, count); - BNFreeUndoEntries(entries, numEntries); return result; } diff --git a/filemetadata.cpp b/filemetadata.cpp index 656fbce7..6aca379c 100644 --- a/filemetadata.cpp +++ b/filemetadata.cpp @@ -368,101 +368,55 @@ vector<Ref<User>> FileMetadata::GetUsers() } -vector<UndoEntry> FileMetadata::GetUndoEntries() +vector<Ref<UndoEntry>> FileMetadata::GetUndoEntries() { - size_t numEntries; - BNUndoEntry* entries = BNGetUndoEntries(m_object, &numEntries); + size_t count; + BNUndoEntry** entries = BNGetUndoEntries(m_object, &count); - vector<UndoEntry> result; - result.reserve(numEntries); - for (size_t i = 0; i < numEntries; i++) + vector<Ref<UndoEntry>> result; + for (size_t i = 0; i < count; i++) { - if (!entries[i].valid) - continue; - UndoEntry temp; - temp.timestamp = entries[i].timestamp; - temp.id = entries[i].id; - temp.user = new User(BNNewUserReference(entries[i].user)); - size_t actionCount = entries[i].actionCount; - for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) - { - temp.actions.emplace_back(entries[i].actions[actionIndex]); - } - result.push_back(temp); + result.push_back(new UndoEntry(BNNewUndoEntryReference(entries[i]))); } - - // BNFreeUndoEntries(entries, count); + BNFreeUndoEntryList(entries, count); return result; } -vector<UndoEntry> FileMetadata::GetRedoEntries() +vector<Ref<UndoEntry>> FileMetadata::GetRedoEntries() { - size_t numEntries; - BNUndoEntry* entries = BNGetRedoEntries(m_object, &numEntries); + size_t count; + BNUndoEntry** entries = BNGetRedoEntries(m_object, &count); - vector<UndoEntry> result; - result.reserve(numEntries); - for (size_t i = 0; i < numEntries; i++) + vector<Ref<UndoEntry>> result; + for (size_t i = 0; i < count; i++) { - if (!entries[i].valid) - continue; - UndoEntry temp; - temp.timestamp = entries[i].timestamp; - temp.id = entries[i].id; - temp.user = new User(BNNewUserReference(entries[i].user)); - size_t actionCount = entries[i].actionCount; - for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) - { - temp.actions.emplace_back(entries[i].actions[actionIndex]); - } - result.push_back(temp); + result.push_back(new UndoEntry(BNNewUndoEntryReference(entries[i]))); } - - // BNFreeUndoEntries(entries, count); + BNFreeUndoEntryList(entries, count); return result; } -std::optional<UndoEntry> FileMetadata::GetLastUndoEntry() +Ref<UndoEntry> FileMetadata::GetLastUndoEntry() { - BNUndoEntry bnEntry = BNGetLastUndoEntry(m_object); - - if (!bnEntry.valid) - return {}; + BNUndoEntry* bnEntry = BNGetLastUndoEntry(m_object); - UndoEntry entry; - entry.timestamp = bnEntry.timestamp; - entry.id = bnEntry.id; - entry.user = new User(BNNewUserReference(bnEntry.user)); - size_t actionCount = bnEntry.actionCount; - for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) - { - entry.actions.emplace_back(bnEntry.actions[actionIndex]); - } + if (bnEntry == nullptr) + return nullptr; - return entry; + return new UndoEntry(bnEntry); } -std::optional<UndoEntry> FileMetadata::GetLastRedoEntry() +Ref<UndoEntry> FileMetadata::GetLastRedoEntry() { - BNUndoEntry bnEntry = BNGetLastRedoEntry(m_object); + BNUndoEntry* bnEntry = BNGetLastRedoEntry(m_object); - if (!bnEntry.valid) - return {}; - - UndoEntry entry; - entry.timestamp = bnEntry.timestamp; - entry.id = bnEntry.id; - entry.user = new User(BNNewUserReference(bnEntry.user)); - size_t actionCount = bnEntry.actionCount; - for (size_t actionIndex = 0; actionIndex < actionCount; actionIndex++) - { - entry.actions.emplace_back(bnEntry.actions[actionIndex]); - } + if (bnEntry == nullptr) + return nullptr; - return entry; + return new UndoEntry(bnEntry); } diff --git a/ui/historyview.h b/ui/historyview.h new file mode 100644 index 00000000..06f6561d --- /dev/null +++ b/ui/historyview.h @@ -0,0 +1,54 @@ +#pragma once + +#include "filter.h" +#include "sidebarwidget.h" +#include <qsortfilterproxymodel.h> +#include <qstandarditemmodel.h> +#include <qtreeview.h> + + +class BINARYNINJAUIAPI HistorySidebarWidget : public SidebarWidget, public FilterTarget +{ + Q_OBJECT + QTreeView* m_tree; + QStandardItemModel* m_model; + QSortFilterProxyModel* m_proxyModel; + + QWidget* m_header; + FilteredView* m_libFilter; + BinaryViewRef m_data; + ContextMenuManager* m_contextMenuManager; + Menu m_contextMenu; + bool m_updating = false; + + std::unordered_map<std::string, QPersistentModelIndex> m_idIndices; + + virtual void scrollToFirstItem() override; + virtual void scrollToCurrentItem() override; + virtual void selectFirstItem() override; + virtual void activateFirstItem() override; + virtual void setFilter(const std::string& filter) override; + + virtual void contextMenuEvent(QContextMenuEvent*) override; + + void itemDoubleClicked(const QModelIndex& index); + void scrollBarRangeChanged(int min, int max); + + void populateTree(); + + public: + HistorySidebarWidget(BinaryViewRef data); + + void notifyFontChanged() override; + QWidget* headerWidget() override { return m_header; } +}; + + +class BINARYNINJAUIAPI HistorySidebarWidgetType : public SidebarWidgetType +{ + public: + HistorySidebarWidgetType(); + SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override; + SidebarWidgetLocation defaultLocation() const override { return SidebarWidgetLocation::RightBottom; } + SidebarContextSensitivity contextSensitivity() const override { return PerViewTypeSidebarContext; } +}; diff --git a/ui/uitypes.h b/ui/uitypes.h index 68022642..511e5aa9 100644 --- a/ui/uitypes.h +++ b/ui/uitypes.h @@ -115,6 +115,8 @@ typedef BinaryNinja::Ref<BinaryNinja::RepoPlugin> RepoPluginRef; typedef BinaryNinja::Ref<BinaryNinja::Repository> RepositoryRef; typedef BinaryNinja::Ref<BinaryNinja::RepositoryManager> RepositoryManagerRef; typedef BinaryNinja::Ref<BinaryNinja::Logger> LoggerRef; +typedef BinaryNinja::Ref<BinaryNinja::UndoAction> UndoActionRef; +typedef BinaryNinja::Ref<BinaryNinja::UndoEntry> UndoEntryRef; typedef BinaryNinja::Ref<BinaryNinja::Collaboration::Remote> RemoteRef; typedef BinaryNinja::Ref<BinaryNinja::Collaboration::RemoteProject> RemoteProjectRef; diff --git a/undoaction.cpp b/undoaction.cpp index 5d2e5268..8b596888 100644 --- a/undoaction.cpp +++ b/undoaction.cpp @@ -25,13 +25,63 @@ using namespace Json; using namespace std; -UndoAction::UndoAction(const BNUndoAction& action) +UndoAction::UndoAction(BNUndoAction* action) { - actionType = action.actionType; - summaryText = action.summaryText; - summaryTokens.reserve(action.summaryTokenCount); - for (size_t i = 0; i < action.summaryTokenCount; i++) + m_object = action; +} + + +std::string UndoAction::GetSummaryText() +{ + char* summary = BNUndoActionGetSummaryText(m_object); + std::string result = summary; + BNFreeString(summary); + return result; +} + + +vector<InstructionTextToken> UndoAction::GetSummary() +{ + size_t count = 0; + BNInstructionTextToken* result = BNUndoActionGetSummary(m_object, &count); + vector<InstructionTextToken> newTokens; + return InstructionTextToken::ConvertAndFreeInstructionTextTokenList(result, count); +} + + +UndoEntry::UndoEntry(BNUndoEntry* entry) +{ + m_object = entry; +} + + +std::string UndoEntry::GetId() +{ + char* id = BNUndoEntryGetId(m_object); + std::string result = id; + BNFreeString(id); + return result; +} + + +std::vector<Ref<UndoAction>> UndoEntry::GetActions() +{ + size_t count; + + BNUndoAction** actions = BNUndoEntryGetActions(m_object, &count); + std::vector<Ref<UndoAction>> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) { - summaryTokens.push_back(action.summaryTokens[i]); + result.push_back(new UndoAction(BNNewUndoActionReference(actions[i]))); } + + BNFreeUndoActionList(actions, count); + return result; +} + + +uint64_t UndoEntry::GetTimestamp() +{ + return BNUndoEntryGetTimestamp(m_object); } |
