summaryrefslogtreecommitdiff
path: root/ui/settingsview.h
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2021-12-28 15:59:31 -0500
committerGlenn Smith <glenn@vector35.com>2022-01-17 20:42:22 -0500
commite88ed98d60b046cbeb5f4c96fc374c7576d7b57a (patch)
treee937ffccba9868cb259e4ec817157b255dc74652 /ui/settingsview.h
parentdc2a99e1159c3951b91935490ec8d2da5fc8e1e7 (diff)
OptionsDialog/SettingsView + ProgressTask fixes
Diffstat (limited to 'ui/settingsview.h')
-rw-r--r--ui/settingsview.h390
1 files changed, 390 insertions, 0 deletions
diff --git a/ui/settingsview.h b/ui/settingsview.h
new file mode 100644
index 00000000..6a11ee17
--- /dev/null
+++ b/ui/settingsview.h
@@ -0,0 +1,390 @@
+#pragma once
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QItemSelection>
+#include <QtCore/QModelIndex>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QSize>
+#include <QtCore/QSortFilterProxyModel>
+#include <QtCore/QTimer>
+#include <QtCore/QVariant>
+#include <QtGui/QMouseEvent>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QSpinBox>
+#include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QTreeView>
+
+#include <map>
+#include <optional>
+#include <set>
+#include <utility>
+#include <vector>
+#include "binaryninjaapi.h"
+#include "json/json.h"
+#include "render.h"
+#include "menus.h"
+#include "clickablelabel.h"
+
+
+struct SettingsEntry
+{
+ SettingsEntry(int p, const QString& h, const QString& g, std::vector<void*>&& j) : parent(p), heading(h), group(g), jsonDefs(j) { }
+ int parent;
+ QString heading;
+ QString group;
+ std::vector<void*> jsonDefs;
+ std::vector<QString> subgroups;
+};
+
+
+class BINARYNINJAUIAPI SettingsTreeModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+private:
+ Json::Value m_schema;
+ std::vector<SettingsEntry> m_store;
+ std::map<std::string, QString> m_filterText;
+
+public:
+ SettingsTreeModel(std::string schema, QObject* parent = 0);
+ ~SettingsTreeModel();
+
+ QVariant data(const QModelIndex& index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex& index) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+
+ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex& index) const override;
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
+
+ bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
+
+ void updateModel();
+};
+
+
+class BINARYNINJAUIAPI SettingsFilterProxyModel: public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+ int m_scopeFilter = SettingsAutoScope;
+ std::map<std::string, int> m_itemScope;
+ mutable QRegularExpression m_regExp;
+ mutable std::map<QString, std::set<QString>> m_subgroupFilterCache;
+
+public:
+ SettingsFilterProxyModel(QObject* parent = 0);
+
+ int scopeFilter() { return m_scopeFilter; }
+ void setScopeFilter(int scope) { m_scopeFilter = scope; invalidateFilter(); m_subgroupFilterCache.clear(); }
+
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
+ bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
+
+public Q_SLOTS:
+ void updateScope(const std::string& key, int scope) { m_itemScope[key] = scope; }
+};
+
+
+class BINARYNINJAUIAPI SettingsOutlineProxyModel: public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ SettingsOutlineProxyModel(QObject* parent = 0);
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
+};
+
+
+class BINARYNINJAUIAPI SettingsEditor: public QWidget
+{
+ Q_OBJECT
+
+private:
+ SettingsRef m_settings;
+ Json::Value m_setting;
+ std::string m_settingKey;
+ BinaryViewRef m_view = nullptr;
+ BNSettingsScope m_scope = SettingsAutoScope;
+
+ QLabel* m_title = nullptr;
+ ClickableLabel* m_description = nullptr;
+ QLabel* m_settingKeyText = nullptr;
+ QLabel* m_settingSep = nullptr;
+ QLabel* m_message = nullptr;
+
+ BNSettingsScope m_currSettingScope = SettingsDefaultScope;
+ QLabel* m_scopeText = nullptr;
+ QCheckBox* m_checkBox = nullptr;
+ QLineEdit* m_settingText = nullptr;
+ QDoubleSpinBox* m_doubleSpinBox = nullptr;
+ QSpinBox* m_spinBox = nullptr;
+ QComboBox* m_comboBox = nullptr;
+ QLineEdit* m_arrayText = nullptr;
+ std::set<QString> m_validComboSelections;
+ Json::StreamWriterBuilder m_builder;
+
+ bool m_optional = false;
+ bool m_readOnly = false;
+ bool m_requiresRestart = false;
+ bool m_settingModified = false;
+
+public:
+ SettingsEditor(QWidget* parent, SettingsRef settings, BinaryViewRef view, BNSettingsScope scope, const Json::Value* setting);
+ ~SettingsEditor();
+
+ QSize sizeHint() const override;
+ void setSetting(const Json::Value* value, bool updateSchema = false);
+
+Q_SIGNALS:
+ void geometryChanged();
+ void settingChanged();
+ void allSettingsChanged();
+ void showIdentifiers(bool enable);
+ void notifyScope(const std::string& key, int scope);
+ void notifySettingChanged(QString);
+ void notifyNeedsRestart();
+
+private:
+ void notifySettingUpdate(); // TODO core notification callbacks
+
+private Q_SLOTS:
+ void toggleBoolSetting();
+ void updateBoolSetting(bool enabled);
+ void updateEnumStringSetting(const QString& text);
+ void updateStringSetting();
+ void updateFormatedNumberSetting();
+ void updateDoubleNumberSetting(double value);
+ void updateIntNumberSetting(int value);
+ void updateArraySetting();
+ void addArrayStringSetting(const QString& text);
+ void resetSetting();
+ void resetAllSettings(BNSettingsScope scope);
+
+ // TODO GUI plugins
+ void selectFont();
+ void selectUiFont();
+ void selectInterpreter();
+ void selectVirtualEnv();
+
+public Q_SLOTS:
+ void updateScope(BinaryViewRef, BNSettingsScope);
+ void updateSize();
+ void updateViewMode(bool enabled);
+
+private:
+ void contextMenu();
+
+protected:
+ bool eventFilter(QObject* obj, QEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
+ void paintEvent(QPaintEvent *event) override;
+};
+
+
+class BINARYNINJAUIAPI SettingsDelegate: public QStyledItemDelegate
+{
+ Q_OBJECT
+
+private:
+ SettingsRef m_settings;
+ SettingsFilterProxyModel* m_filterModel;
+ BinaryViewRef m_view = nullptr;
+ BNSettingsScope m_scope = SettingsAutoScope;
+ QFont m_groupFont;
+ QFont m_subgroupFont;
+ QFont m_monoFont;
+ int m_monoFontHeight;
+ QTimer* m_updateModelTimer;
+
+ QTreeView* m_treeView;
+ std::function<void(const QModelIndex& index)> m_hoverAction = nullptr;
+ std::function<void()> m_defaultSelectionAction = nullptr;
+
+public:
+ SettingsDelegate(QWidget* parent, SettingsRef settings, SettingsFilterProxyModel* filterModel, const std::function<void(const QModelIndex& index)>& hoverAction = nullptr);
+ ~SettingsDelegate();
+
+ void setDefaultSelection(const std::function<void()>& selectionAction);
+
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+
+ QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ void setEditorData(QWidget* editor, const QModelIndex& index) const override;
+ void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
+ void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+
+protected:
+ bool eventFilter(QObject* object, QEvent* event) override;
+
+public:
+Q_SIGNALS:
+ void refreshAllSettings() const;
+ void scopeChanged(BinaryViewRef, BNSettingsScope);
+ void sizeChanged();
+ void viewModeChanged(bool enabled) const;
+ void notifyNeedsRestart() const;
+ void notifySettingChanged(QString settingId) const;
+
+public Q_SLOTS:
+ void updateFonts();
+ void updateModel();
+ void updateScope(BinaryViewRef, BNSettingsScope);
+ void updateSize();
+ void updateViewMode(bool enabled) const;
+
+private Q_SLOTS:
+ void commitEditorData();
+ void editorGeometryChanged();
+};
+
+
+class BINARYNINJAUIAPI SettingsTreeView: public QTreeView
+{
+ Q_OBJECT
+
+public:
+ explicit SettingsTreeView(QWidget* parent);
+ ~SettingsTreeView();
+
+protected:
+ virtual void resizeEvent(QResizeEvent* event) override;
+
+
+public Q_SLOTS:
+ void modelChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
+};
+
+
+class BINARYNINJAUIAPI BinaryViewScopeLabel: public MenuHelper
+{
+ Q_OBJECT
+
+ BNSettingsScope m_scope;
+ QString m_scopeName;
+ std::vector<QString> m_actionNames;
+ std::vector<std::pair<BinaryViewRef, QString>> m_views;
+ QString m_curName;
+ BinaryViewRef m_curView = nullptr;
+
+ UIActionHandler m_actionHandler;
+
+public:
+ BinaryViewScopeLabel(QWidget* parent, const QString& name = "", BNSettingsScope scope = SettingsAutoScope);
+
+ void refresh();
+ const QString& currentSelection() { return m_curName; }
+ BinaryViewRef currentBinaryView() { return m_curView; }
+
+Q_SIGNALS:
+ void itemSelected(BinaryViewRef, BNSettingsScope);
+
+protected:
+ virtual void showEvent(QShowEvent* event) override;
+ virtual void showMenu() override;
+};
+
+
+class BINARYNINJAUIAPI SettingsScopeBar: public QWidget
+{
+ Q_OBJECT
+
+ QPushButton* m_userLabel;
+ BinaryViewScopeLabel* m_projectLabel;
+ BinaryViewScopeLabel* m_resourceLabel;
+ ClickableLabel* m_openProjectLabel;
+ QLabel* m_desc;
+
+ void setScopeHighlight(unsigned long highlightIdx);
+
+public:
+ SettingsScopeBar(QWidget* parent = nullptr);
+
+ void refresh();
+
+Q_SIGNALS:
+ void scopeChanged(BinaryViewRef, BNSettingsScope);
+};
+
+
+class BINARYNINJAUIAPI SearchFilter: public QLineEdit
+{
+ Q_OBJECT
+
+ std::map<QString, int> m_filterTags;
+ QRegularExpression m_regexTagExtract;
+ QTimer* m_filterDelayTimer = nullptr;
+ int m_delay;
+
+public:
+ SearchFilter(QWidget* parent = nullptr);
+
+ void addTag(const QString& tagName, int tag);
+ void setDelay(int msec = 100) { m_delay = msec; }
+ void setFilter();
+
+ std::pair<QString, std::vector<int>> getSearchParams();
+
+protected:
+ void keyPressEvent(QKeyEvent* event) override;
+
+Q_SIGNALS:
+ void delayedTextChanged();
+};
+
+
+class BINARYNINJAUIAPI SettingsView: public QWidget
+{
+ Q_OBJECT
+
+private:
+ QWidget* m_owner = nullptr;
+ SettingsRef m_settings;
+ SettingsFilterProxyModel* m_proxyModel = nullptr;
+ SettingsOutlineProxyModel* m_outlineProxyModel = nullptr;
+ QTreeView* m_outlineView = nullptr;
+ SettingsTreeView* m_settingsTreeView = nullptr;
+ SettingsDelegate* m_delegate = nullptr;
+ SettingsScopeBar* m_scopeBar = nullptr;
+ QCheckBox* m_viewMode = nullptr;
+ SearchFilter* m_search = nullptr;
+ bool m_outlineNavEnabled = true;
+
+public:
+ SettingsView(QWidget* parent);
+ SettingsView(QWidget* parent, SettingsRef settings);
+ ~SettingsView();
+
+ void init(std::string schema, bool uiScopeSelection);
+ void refreshCurrentScope();
+ void setData(BinaryViewRef view, const QString& name = "");
+ void setDefaultGroupSelection(const QString& group);
+
+public Q_SLOTS:
+ void updateFonts();
+ void updateTheme();
+
+private Q_SLOTS:
+ void outlineSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
+ void updateScopeFilter();
+ void updateTextFilter();
+
+Q_SIGNALS:
+ void fontsChanged();
+ void notifyNeedsRestart();
+ void notifySettingChanged(QString settingId) const;
+};