diff options
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/commandpalette.h | 215 | ||||
| -rw-r--r-- | ui/flowgraphwidget.h | 1 | ||||
| -rw-r--r-- | ui/linearview.h | 1 | ||||
| -rw-r--r-- | ui/tokenizedtextview.h | 1 | ||||
| -rw-r--r-- | ui/viewframe.h | 16 |
5 files changed, 210 insertions, 24 deletions
diff --git a/ui/commandpalette.h b/ui/commandpalette.h index fcb27b31..8fb20cd6 100644 --- a/ui/commandpalette.h +++ b/ui/commandpalette.h @@ -5,6 +5,7 @@ #include <QtWidgets/QLineEdit> #include <QtWidgets/QFrame> #include <QtCore/QPointer> +#include <QtCore/QThread> #include <QtWidgets/QStyledItemDelegate> #include <vector> #include "action.h" @@ -21,14 +22,132 @@ */ struct BINARYNINJAUIAPI CommandListItem { + enum CommandListItemType + { + // Index is serialized so only to add to the end + Help, + UIAction, + OpenTab, + NavigationHistory, + RecentFile, + RecentProject, + ProjectFile, + Expression, + RecentExpression, + Function, + Symbol, + Type, + String, + DerivedString, + LastItemType + }; + + CommandListItemType type; QString name; + QString secondary; QString shortcut; - QString action; + QString extraSearchableText; + QVariant action; + Qt::TextElideMode secondaryElide = Qt::ElideRight; + bool addToRecents = true; + bool includeUnfiltered = true; + int score = 0; +}; + + +/*! + + \ingroup commandpalette +*/ +struct BINARYNINJAUIAPI CommandListItemSearchInfo +{ + std::unordered_set<CommandListItem::CommandListItemType> types; + QString name; + QString searchName; + std::string prefix; + QKeySequence shortcut; + + static std::vector<CommandListItemSearchInfo> GetSearchTypes(); }; + class CommandPalette; class CommandListFilter; +class CommandListGenerateWorker : public QObject +{ + Q_OBJECT + + BinaryViewRef m_view; + bool m_aborted; + int m_request; + std::shared_ptr<std::atomic_int> m_latestRequest; + + bool m_pending; + std::vector<CommandListItem> m_pendingItems; + std::mutex m_pendingItemsMutex; + +public: + explicit CommandListGenerateWorker(QObject* parent, std::shared_ptr<std::atomic_int> request, const UIActionContext& context); + virtual ~CommandListGenerateWorker(); + +Q_SIGNALS: + void dataFetched(int request, const std::vector<CommandListItem>& items); + void noMoreDataToFetch(int request); + void workFinished(int request); + +public Q_SLOTS: + void fetchMore(); + void start(); + void abort(); +}; + + +class CommandListScoreWorker : public QObject +{ +public: + enum OrderStrategy + { + DefaultOrder, + ScoreOrder + }; + +private: + Q_OBJECT + + bool m_aborted; + int m_request; + std::shared_ptr<std::atomic_int> m_latestRequest; + QString m_filter; + std::shared_ptr<std::vector<CommandListItem>> m_items; + std::vector<int> m_oldItemScores; + OrderStrategy m_strategy; + + bool m_pending; + std::vector<std::pair<CommandListItem*, int>> m_pendingItems; + std::mutex m_pendingItemsMutex; + +public: + explicit CommandListScoreWorker( + QObject* parent, + std::shared_ptr<std::atomic_int> request, + QString filter, + std::shared_ptr<std::vector<CommandListItem>> items, + OrderStrategy orderStrategy + ); + virtual ~CommandListScoreWorker(); + +Q_SIGNALS: + void dataFetched(int request, const std::vector<std::pair<CommandListItem*, int>>& items); + void noMoreDataToFetch(int request); + void workFinished(int request); + +public Q_SLOTS: + void fetchMore(); + void start(); + void abort(); +}; + /*! @@ -54,17 +173,40 @@ class BINARYNINJAUIAPI CommandListModel : public QAbstractItemModel { Q_OBJECT - std::vector<CommandListItem> m_items; - std::vector<CommandListItem> m_allItems; + UIActionHandler* m_handler; + UIActionContext m_context; + + std::shared_ptr<std::vector<CommandListItem>> m_allItems; + std::vector<CommandListItem*> m_displayItems; // pointers into m_allItems + QString m_filterText; + bool m_updatesPaused; - std::vector<QString> m_recentItems; - size_t m_maxRecentItems; + std::vector<CommandListItem> m_recentItems; - bool isFilterMatch(const QString& name, const QString& filter); - int getFilterMatchScore(const QString& name, const QString& filter); + QThread m_generateWorkerThread; + CommandListGenerateWorker* m_generateWorker; + std::shared_ptr<std::atomic_int> m_generateWorkerRequest; + QTimer m_generateFetchTimer; + bool m_generateMoreToFetch; - public: - CommandListModel(QWidget* parent, const std::vector<CommandListItem>& items); + QTimer m_scoreTimer; + QMetaObject::Connection m_scoreTimerConnection; + + QThread m_scoreWorkerThread; + CommandListScoreWorker* m_scoreWorker; + std::shared_ptr<std::atomic_int> m_scoreWorkerRequest; + QTimer m_scoreFetchTimer; + bool m_scoreMoreToFetch; + + void loadRecentItems(); + std::vector<CommandListItem> generateFastCommandList(); + void sortCommandList(std::vector<CommandListItem>& list); + void mergeCommandList(std::vector<CommandListItem>& output, std::vector<CommandListItem>&& input); + void startScoreListThread(); + +public: + CommandListModel(QWidget* parent); + ~CommandListModel(); virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override; virtual QModelIndex parent(const QModelIndex& i) const override; @@ -73,10 +215,33 @@ class BINARYNINJAUIAPI CommandListModel : public QAbstractItemModel virtual int columnCount(const QModelIndex& parent) const override; virtual QVariant data(const QModelIndex& i, int role) const override; - QString getActionForItem(int row); + CommandListItem getItem(int row); void setFilterText(const QString& text); - size_t getRecentPosition(const QString& name) const; - void addRecentItem(const QString& name); + size_t getRecentPosition(const CommandListItem& item) const; + void addRecentItem(const CommandListItem& item); + + void clearCommandList(); + void generateCommandList(UIActionHandler* handler, const UIActionContext& context); + void cancelGenerateCommandList(); + + void scoreCommandList(CommandListScoreWorker::OrderStrategy strategy); + void cancelScoreCommandList(); + + void pauseCommandListUpdates(); + void unpauseCommandListUpdates(); + + void updateDisplayedItems(); + +private Q_SLOTS: + void generateFetch(); + void itemsGenerated(int request, const std::vector<CommandListItem>& items); + void itemsFinishedGenerating(int request); + void generateWorkFinished(int request); + + void scoreFetch(); + void itemsScored(int request, const std::vector<std::pair<CommandListItem*, int>>& items); + void itemsFinishedScoring(int request); + void scoreWorkFinished(int request); }; /*! @@ -92,14 +257,21 @@ class BINARYNINJAUIAPI CommandList : public QListView CommandListFilter* m_filter; public: - CommandList(CommandPalette* parent, const std::vector<CommandListItem>& items); + CommandList(CommandPalette* parent); void setFilter(CommandListFilter* filter) { m_filter = filter; } void setFilterText(const QString& text); - QString getActionForItem(int row); + CommandListItem getItem(int row); QModelIndex index(int row, int col, const QModelIndex& parent = QModelIndex()) const; - void addRecentItem(const QString& name); + void addRecentItem(const CommandListItem& item); + + void clearCommandList(); + void generateCommandList(UIActionHandler* handler, const UIActionContext& context); + void cancelGenerateCommandList(); + + void pauseCommandListUpdates(); + void unpauseCommandListUpdates(); protected: virtual void keyPressEvent(QKeyEvent* event) override; @@ -126,7 +298,9 @@ class BINARYNINJAUIAPI CommandListFilter : public QLineEdit protected: bool event(QEvent* event) override; virtual void keyPressEvent(QKeyEvent* event) override; + virtual void focusInEvent(QFocusEvent* event) override; virtual void focusOutEvent(QFocusEvent* event) override; + virtual void paintEvent(QPaintEvent* event) override; }; /*! @@ -139,26 +313,31 @@ class BINARYNINJAUIAPI CommandPalette : public QFrame UIActionHandler* m_handler; UIActionContext m_context; + QPointer<QWidget> m_previousWidget; CommandListFilter* m_filter; CommandList* m_list; + std::optional<CommandListItem> m_savedTop; bool m_executing; - std::vector<CommandListItem> getCommandList(); void init(); public: - CommandPalette(QWidget* parent, UIActionHandler* handler); - CommandPalette(QWidget* parent, UIActionHandler* handler, const UIActionContext& context); + CommandPalette(QWidget* parent); + void openWithInput(const QString& text); void focusInput(); + void clearCommandList(); + void generateCommandList(UIActionHandler* handler, const UIActionContext& context); + //! Activate the focused item, or topmost item if there is no selection. void activateFocusedItem(); void selectFirstItem(); void close(bool restoreFocus = true); + void activateItem(const CommandListItem& item); private Q_SLOTS: void itemClicked(const QModelIndex& idx); diff --git a/ui/flowgraphwidget.h b/ui/flowgraphwidget.h index 90b86000..056dc7ac 100644 --- a/ui/flowgraphwidget.h +++ b/ui/flowgraphwidget.h @@ -63,6 +63,7 @@ class BINARYNINJAUIAPI FlowGraphHistoryEntry : public HistoryEntry void setCurrentAddress(uint64_t a) { m_addr = a; } void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; } + virtual QString getDescription() const override; virtual Json::Value serialize() const override; virtual bool deserialize(const Json::Value& value) override; }; diff --git a/ui/linearview.h b/ui/linearview.h index 0067a3e1..df01a3b2 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -111,6 +111,7 @@ public: void setInFunction(bool inFunc) { m_inFunc = inFunc; } void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; } + virtual QString getDescription() const override; virtual Json::Value serialize() const override; virtual bool deserialize(const Json::Value& value) override; }; diff --git a/ui/tokenizedtextview.h b/ui/tokenizedtextview.h index 26a96555..708673bb 100644 --- a/ui/tokenizedtextview.h +++ b/ui/tokenizedtextview.h @@ -33,6 +33,7 @@ class BINARYNINJAUIAPI TokenizedTextViewHistoryEntry : public HistoryEntry void setCursorLine(size_t line) { m_cursorLine = line; } void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; } + virtual QString getDescription() const override; virtual Json::Value serialize() const override; virtual bool deserialize(const Json::Value& value) override; }; diff --git a/ui/viewframe.h b/ui/viewframe.h index 055e27c0..08d4add6 100644 --- a/ui/viewframe.h +++ b/ui/viewframe.h @@ -85,6 +85,8 @@ class BINARYNINJAUIAPI HistoryEntry : public BinaryNinja::RefCountObject QString getViewType() const { return m_viewType; } void setViewType(const QString& type) { m_viewType = type; } + virtual QString getDescription() const; + /*! Serialize to json representation \return Json representation of history entry. In the Python api, this must be a dict. @@ -392,12 +394,6 @@ class BINARYNINJAUIAPI ViewFrame : public QWidget bool gestureEvent(QGestureEvent* event); void setView(QWidget* view); - /*! - Load one history entry from json representation - \param json Json rep of history entry - \return Entry, if successful, else nullptr - */ - BinaryNinja::Ref<HistoryEntry> deserializeHistoryEntry(const Json::Value& json); bool tryMainSymbolsNavigation(); @@ -464,6 +460,14 @@ class BINARYNINJAUIAPI ViewFrame : public QWidget void updateFonts(); void updateTheme(); + std::vector<BinaryNinja::Ref<HistoryEntry>> getBackHistory(); + std::vector<BinaryNinja::Ref<HistoryEntry>> getForwardHistory(); + /*! + Load one history entry from json representation + \param json Json rep of history entry + \return Entry, if successful, else nullptr + */ + BinaryNinja::Ref<HistoryEntry> deserializeHistoryEntry(const Json::Value& json); void addHistoryEntry(); /*! Parse history entries from the raw data associated with a BinaryView, loading them into the back/forward |
