diff options
| author | Josh Ferrell <josh@vector35.com> | 2024-02-09 12:34:28 -0500 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2024-02-09 12:40:02 -0500 |
| commit | f35c47dffaa152eea6614a787bf8f2c76221162a (patch) | |
| tree | c5e423e4324987915b03dfae9950d3c0748fd9a1 | |
| parent | d349ef152d6d9b5939a2fd1de2281b1a720fc297 (diff) | |
Expose projectbrowser.h
| -rw-r--r-- | ui/projectbrowser.h | 333 | ||||
| -rw-r--r-- | ui/uicontext.h | 2 |
2 files changed, 335 insertions, 0 deletions
diff --git a/ui/projectbrowser.h b/ui/projectbrowser.h new file mode 100644 index 00000000..886d683d --- /dev/null +++ b/ui/projectbrowser.h @@ -0,0 +1,333 @@ +#pragma once + +#include <QtWidgets/QLabel> +#include <QtGui/QStandardItemModel> +#include <qabstractitemmodel.h> +#include <qboxlayout.h> +#include <qfileiconprovider.h> +#include <qfilesystemwatcher.h> +#include <qlineedit.h> +#include <qmimedatabase.h> +#include <qnamespace.h> +#include <qplaintextedit.h> +#include <qsettings.h> +#include <qsortfilterproxymodel.h> +#include <qstandarditemmodel.h> +#include <qstyleditemdelegate.h> +#include <qtextbrowser.h> +#include <qtmetamacros.h> +#include <qtoolbutton.h> +#include <qtreeview.h> +#include <qlistwidget.h> +#include <qwidget.h> +#include <qpushbutton.h> +#include <unordered_map> + +#include "binaryninjaapi.h" +#include "clickablelabel.h" +#include "filter.h" +#include "menus.h" +#include "uitypes.h" + + +class BINARYNINJAUIAPI ProjectStatusWidget: public MenuHelper +{ +protected: + virtual void showMenu() override; +public: + ProjectStatusWidget(QWidget* parent, const QString& text); +}; + + +class BINARYNINJAUIAPI ProjectItemModel: public QStandardItemModel, public BinaryNinja::ProjectNotification +{ + Q_OBJECT + + ProjectRef m_project; + + QMimeDatabase m_mimeDatabase; + QFileIconProvider m_iconProvider; + QSettings m_qsettings; + QLocale m_locale; + + QFileSystemWatcher* m_fsWatcher; + + std::unordered_map<std::string, QPersistentModelIndex> m_idIndexMap; + + QHash<QString, QString> m_pathMimeTypeCache; + QHash<QString, size_t> m_pathSizeCache; + QHash<QString, QIcon> m_pathIconCache; + QHash<QString, int64_t> m_idUploadProgress; + + bool OnBeforeProjectMetadataWritten(BinaryNinja::Project*, std::string& key, BinaryNinja::Metadata* value) override; + void OnAfterProjectFileCreated(BinaryNinja::Project*, BinaryNinja::ProjectFile*) override; + void OnAfterProjectFileUpdated(BinaryNinja::Project*, BinaryNinja::ProjectFile*) override; + void OnAfterProjectFileDeleted(BinaryNinja::Project*, BinaryNinja::ProjectFile*) override; + void OnAfterProjectFolderCreated(BinaryNinja::Project*, BinaryNinja::ProjectFolder*) override; + void OnAfterProjectFolderUpdated(BinaryNinja::Project*, BinaryNinja::ProjectFolder*) override; + void OnAfterProjectFolderDeleted(BinaryNinja::Project*, BinaryNinja::ProjectFolder*) override; + + void AddFolder(ProjectFolderRef folder); + void RemoveFolder(ProjectFolderRef folder); + + void AddFile(ProjectFileRef file); + void RemoveFile(ProjectFileRef file); + + void CachePathInformation(const QString& path); + void RemoveCachedPathInformation(const QString& path); + void WatchEvent(const QString& path); + +public: + ProjectItemModel(ProjectRef project, QObject* parent = nullptr); + ~ProjectItemModel(); + + QStandardItem* ItemForId(const std::string& id); + + void reloadData(const std::function<bool(size_t, size_t)>& progress = [](size_t, size_t){ return true; }); + + virtual QMimeData* mimeData(const QModelIndexList& indexes) const override; + virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; + virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + + enum { + TypeRole = Qt::UserRole, + IdRole, + DiskPathRole, + SortRole, + }; + + enum { + FileType, + FolderType, + }; + + enum { + COL_NAME = 0, + COL_TYPE, + COL_SIZE_ON_DISK, + COL_CREATED, + COL_LAST_OPENED, + COL_STATUS, + COLUMN_COUNT, + }; + +Q_SIGNALS: + void itemsDropped(Qt::DropAction action, const QList<QString> fileIds, const QList<QString> folderIds, const QList<QUrl> newUrls, ProjectFolderRef newParentFolder); + +private Q_SLOTS: + void fileChanged(const QString& path); + void directoryChanged(const QString& path); +}; + + +class BINARYNINJAUIAPI SortFilterProjectItemModel: public QSortFilterProxyModel +{ + bool m_acceptAllFolders = false; + +protected: + virtual bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override; + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + +public: + SortFilterProjectItemModel(QObject* parent = nullptr): QSortFilterProxyModel(parent) {}; + + void setAcceptAllFolders(bool accept) { m_acceptAllFolders = accept; } + bool acceptAllFolders() const { return m_acceptAllFolders; } +}; + + +class BINARYNINJAUIAPI ProjectTreeStyle: public QProxyStyle +{ +public: + ProjectTreeStyle(QStyle* style) : QProxyStyle(style) {}; + + void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override; +}; + + +class BINARYNINJAUIAPI ProjectTree: public QTreeView, public FilterTarget +{ + Q_OBJECT + + QSet<QString> m_expandedIds; + + virtual void scrollToFirstItem() override; + virtual void scrollToCurrentItem() override; + virtual void selectFirstItem() override; + virtual void activateFirstItem() override; + virtual void setFilter(const std::string& filter) override; + +protected: + void mousePressEvent(QMouseEvent* event) override; + void keyPressEvent(QKeyEvent* event) override; + void rowsInserted(const QModelIndex& parent, int start, int end) override; + +public: + ProjectTree(QWidget* parent = nullptr); + +Q_SIGNALS: + void filterChanged(const QString& filter); +}; + + +class BINARYNINJAUIAPI RecentsList: public QListWidget, public FilterTarget +{ + Q_OBJECT + + virtual void scrollToFirstItem() override; + virtual void scrollToCurrentItem() override; + virtual void selectFirstItem() override; + virtual void activateFirstItem() override; + virtual void setFilter(const std::string& filter) override; + +public: + + enum { + FileIdRole = Qt::UserRole, + NameRole, + PathRole + }; + + RecentsList(QWidget* parent = nullptr) : QListWidget(parent) {} +}; + + +class BINARYNINJAUIAPI RecentFileItem: public QWidget +{ + Q_OBJECT + + ProjectFileRef m_projectFile; + + QIcon m_icon; + QLabel* m_fileNameLabel; + QLabel* m_filePathLabel; + +public: + RecentFileItem(ProjectFileRef file, QWidget* parent = nullptr); + +Q_SIGNALS: + void showInProject(ProjectFileRef file); +}; + + +class BINARYNINJAUIAPI InfoWidget: public QWidget +{ + std::unordered_map<std::string, ProjectFileRef> m_files; + std::unordered_map<std::string, ProjectFolderRef> m_folders; + + QVBoxLayout* m_layout; + QLabel* m_descriptionTitleLabel; + QTextEdit* m_descriptionText; + QLabel* m_selectedItemNameLabel; + QLabel* m_selectedItemDetailsLabel; + + QHBoxLayout* m_descriptionButtonLayout; + QWidget* m_descriptionButtonWidget; + QPushButton* m_descriptionSaveButton; + QPushButton* m_descriptionCancelButton; + + bool HasDescriptionChanged() const; + + void descriptionChanged(); + void cancelChangeDescription(); + void saveDescription(); + +public: + InfoWidget(QWidget* parent = nullptr); + + bool ContainsFile(const std::string& id); + bool ContainsFolder(const std::string& id); + + void UpdateInfo(); + + void PromptSave(); + + void AddFile(ProjectFileRef file); + void RemoveFile(ProjectFileRef file); + + void AddFolder(ProjectFolderRef folder); + void RemoveFolder(ProjectFolderRef folder); +}; + + +class BINARYNINJAUIAPI ProjectBrowser: public QWidget, public UIContextNotification, public BinaryNinja::ProjectNotification +{ + Q_OBJECT + + ProjectRef m_project; + + FilterEdit* m_projectFilterEdit; + FilteredView* m_filteredTreeView; + + FilterEdit* m_recentsFilterEdit; + FilteredView* m_filteredRecentsView; + + QTabBar* m_tabBar; + + ProjectItemModel* m_projectModel; + SortFilterProjectItemModel* m_sortFilterProjectModel; + QLabel* m_nameLabel; + QLabel* m_descriptionLabel; + ProjectTree* m_projectTree; + InfoWidget* m_infoWidget; + QWidget* m_projectContainer; + + RecentsList* m_recentFilesList; + + ClickableIcon* m_refreshButton; + ClickableIcon* m_editDetailsButton; + + UIActionHandler m_projectActionHandler; + ContextMenuManager* m_projectContextMenuManager = nullptr; + Menu m_projectMenu; + + ProjectFolderRef GetFolderContainingIndex(const QModelIndex& index) const; + + virtual void OnAfterOpenProjectFile(UIContext* context, ProjectFileRef projectFile, ViewFrame* frame) override; + + void updateWindowTitle(); + void updateRecentFileList(); + void AddRecentProjectFile(ProjectFileRef projectFile); + + void UpdateDetails(); + void LoadProjectData(); + + virtual void OnAfterProjectMetadataWritten(BinaryNinja::Project* project, std::string& key, BinaryNinja::Metadata* value) override; + + void storeTreeState(); + void restoreTreeState(); + + void initActions(); + +private slots: + void itemDoubleClicked(const QModelIndex& index); + void openProjectFile(ProjectFileRef file, bool openWithOptions = false); + void itemSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); + void itemChanged(QStandardItem* item); + void handleItemsDropped(Qt::DropAction action, const QList<QString> fileIds, const QList<QString> folderIds, const QList<QUrl> newUrls, ProjectFolderRef newParentFolder); + void onTreeFilterChanged(const QString& filter); + +protected: + void SelectItems(std::vector<ProjectFileRef> files, std::vector<ProjectFolderRef> folders); + void SelectItemsById(std::vector<std::string> fileIds, std::vector<std::string> folderIds); + void PromptImportFile(ProjectFolderRef folder = nullptr); + void PromptImportFolder(ProjectFolderRef parent = nullptr); + void MakeNewFolder(ProjectFolderRef parent = nullptr); + void PromptDeleteSelected(); + void PromptOpenSelected(bool withOptions = false); + void PromptExportSelected(); + void PromptAnalyzeSelected(); + void PromptEditProjectDetails(); + void Refresh(); + +public: + ProjectBrowser(QWidget* parent, ProjectRef project); + ~ProjectBrowser(); + + ProjectRef GetProject() const { return m_project; }; + + static void registerActions(); +}; diff --git a/ui/uicontext.h b/ui/uicontext.h index fee474ce..9d65ac90 100644 --- a/ui/uicontext.h +++ b/ui/uicontext.h @@ -23,6 +23,7 @@ class Sidebar; class SidebarWidgetContainer; class GlobalArea; class Pane; +class ProjectStatusWidget; struct SelectionInfoForXref; /*! @@ -457,6 +458,7 @@ public: virtual std::vector<ViewFrame*> getAllViewFramesForTab(QWidget* tab) const = 0; virtual ProjectRef getProject(); + virtual ProjectStatusWidget* getProjectStatusWidget(); virtual bool openFilename(const QString& path, bool openOptions = false); virtual ProjectRef openProject(const QString& path); |
