#pragma once #include #include #include "sidebarwidget.h" #include "sidebarcontainer.h" #include "sidebaricons.h" #include "splitter.h" class ViewFrame; /*! \ingroup sidebar */ struct BINARYNINJAUIAPI SidebarMetrics { int iconWidth, iconHeight; int paddingX, paddingY; int separatorPadding; int iconTotalWidth, iconTotalHeight; int dragIconPadding; int dropIconPadding; int focusRectPadding; int focusRectRadius; }; /*! \ingroup sidebar */ class BINARYNINJAUIAPI Sidebar : public QObject { Q_OBJECT struct SavedTypeOrderingInfo { QString typeName; bool isDefaultArea; }; SidebarIconsWidget* m_left; SidebarIconsWidget* m_right; Splitter* m_parentSideSplitter = nullptr; Splitter* m_parentExtendedSideSplitter = nullptr; Splitter* m_parentBottomSplitter = nullptr; Splitter* m_parentBottomSeparatorSplitter = nullptr; SplitPaneWidget* m_panes = nullptr; ViewFrame* m_frame = nullptr; QString m_dataType; BinaryViewRef m_data; std::map> m_priorParentSideSplitterSizes; std::map> m_priorParentExtendedSideSplitterSizes; std::map> m_priorParentBottomSplitterSizes; std::map> m_priorParentBottomSeparatorSplitterSizes; std::map>>> m_currentViewLocation; std::set m_toggledWidgets; static std::map> m_types; static std::map> m_savedTypeOrdering; static std::set m_instances; static std::set m_defaultTypes; static std::optional m_metrics; static std::map m_iconVisibility; private Q_SLOTS: void containerUpdated(); public: Sidebar(QWidget* parent); virtual ~Sidebar(); SidebarIconsWidget* left() const { return m_left; } SidebarIconsWidget* right() const { return m_right; } static SidebarWidgetLocation locationForType(SidebarWidgetType* type); static SidebarLocation sideForLocation(SidebarWidgetLocation location); static SidebarContainerLocation containerLocationForWidgetLocation(SidebarWidgetLocation location); SidebarWidgetContainer* containerForLocation(SidebarWidgetLocation location) const; static Qt::Orientation primaryOrientationForLocation(SidebarWidgetLocation location); void forAllContainers(const std::function& func) const; void setSplitters(Splitter* sideSplitter, Splitter* extendedSideSplitter, Splitter* bottomSplitter, Splitter* bottomSeparatorSplitter); void setActiveContext(SplitPaneWidget* panes, ViewFrame* frame, const QString& dataType, BinaryViewRef data); void destroyContext(ViewFrame* frame); void destroyContext(SplitPaneWidget* panes); void destroyViewsForContext(SplitPaneWidget* panes); void moveContextToContainer(SplitPaneWidget* panes, Sidebar* target); SplitPaneWidget* currentPanes(SidebarWidgetType* type = nullptr) const; ViewFrame* currentFrame(SidebarWidgetType* type = nullptr) const; const QString& currentDataType(SidebarWidgetType* type = nullptr) const; BinaryViewRef currentData(SidebarWidgetType* type = nullptr) const; std::optional> currentViewLocation() const; SidebarWidget* widget(SidebarWidgetType* type); SidebarWidget* widget(const QString& name); SidebarWidgetAndHeader* widgetAndHeader(SidebarWidgetType* type); SidebarWidgetAndHeader* widgetAndHeader(const QString& name); void addWidget(SidebarWidgetType* type, SidebarWidget* widget, bool canClose = false); void addWidget(const QString& name, SidebarWidget* widget, bool canClose = false); void removeWidget(SidebarWidgetType* type, SidebarWidget* widget); void removeWidget(const QString& typeName, SidebarWidget* widget); SidebarWidget* widgetWithTitle(SidebarWidgetType* type, const QString& title) const; SidebarWidget* widgetWithTitle(const QString& typeName, const QString& title) const; bool hasWidgetWithTitle(SidebarWidgetType* type, const QString& title) const; bool hasWidgetWithTitle(const QString& typeName, const QString& title) const; void focusWidgetWithTitle(SidebarWidgetType* type, const QString& title); void focusWidgetWithTitle(const QString& typeName, const QString& title); void activate(SidebarWidgetType* type, bool alwaysAllowMultipleOpen = true); void activate(const QString& name, bool alwaysAllowMultipleOpen = true); void activateDefaultTypes(); void deactivate(SidebarWidgetType* type); void deactivate(const QString& name); void focus(SidebarWidgetType* type); void focus(const QString& name); void toggle(SidebarWidgetType* type); void toggle(const QString& name); bool isActive(SidebarWidgetType* type) const; bool isActive(const QString& name) const; bool isContentActive() const; bool isSideContentActive() const; bool isBottomContentActive() const; bool allIconsVisible() const; std::vector hiddenIcons() const; void updateTheme(); void updateFonts(); void updateVisibility(); void toggleSidebar(); void updateViewLocation(View* view, const ViewLocation& viewLocation); void viewChanged(); void saveState(QSettings& settings, const QString& windowStateName, bool globalStateOnly = false); QVariant saveActiveState(); void restoreState(const QSettings& settings, const QString& windowStateName, bool globalStateOnly = false); bool restoreActiveState(const QVariant& state); void focusChanged(SidebarWidgetAndHeader* widget); static void addSidebarWidgetType(SidebarWidgetType* type); static void moveSidebarWidgetType(SidebarWidgetType* type, SidebarWidgetLocation newLocation, size_t newIndex); static SidebarWidgetType* typeFromName(const QString& name); static bool isTypeRegistered(const QString& name); static std::vector types(); static const std::vector& typesForLocation(SidebarWidgetLocation location); static std::vector typesForContainerLocation(SidebarContainerLocation location); static void initSavedTypeOrdering(); static void saveTypeOrdering(); static void initIconVisibility(); static void saveIconVisibility(); static SidebarMetrics metrics(); static void refreshMetrics(); static std::set defaultTypes() { return m_defaultTypes; } static void setDefaultTypes(const std::set& types) { m_defaultTypes = types; } static SidebarIconVisibility iconVisibility(SidebarWidgetType* type); static SidebarIconVisibility iconVisibility(const QString& name); static void setIconVisibility(SidebarWidgetType* type, SidebarIconVisibility visibility); static void setIconVisibility(const QString& name, SidebarIconVisibility visibility); static Sidebar* current() { UIContext* context = UIContext::activeContext(); if (!context) return nullptr; return context->sidebar(); } template static T* widget(SidebarWidgetType* type) { Sidebar* sidebar = current(); if (!type || !sidebar || !sidebar->isActive(type)) return (T*)nullptr; QWidget* widget = sidebar->widget(type); if (!widget) return (T*)nullptr; return qobject_cast(widget); } template static T* widget(const QString& name) { return widget(Sidebar::typeFromName(name)); } template static T* activateWidget(SidebarWidgetType* type) { Sidebar* sidebar = current(); if (!type || !sidebar) return (T*)nullptr; sidebar->activate(type); QWidget* widget = sidebar->widget(type); if (!widget) return (T*)nullptr; T* result = qobject_cast(widget); if (!result) return (T*)nullptr; return result; } template static T* activateWidget(const QString& name) { return activateWidget(Sidebar::typeFromName(name)); } template static UIAction globalSidebarAction(const QString& name, const std::function& activate) { return globalSidebarAction( name, [=](T* obj, const UIActionContext&) { activate(obj); }, [=](T*, const UIActionContext&) { return true; }); } template static UIAction globalSidebarAction( const QString& name, const std::function& activate) { return globalSidebarAction(name, activate, [](T*, const UIActionContext&) { return true; }); } template static UIAction globalSidebarAction( const QString& name, const std::function& activate, const std::function& isValid) { return globalSidebarAction( name, [=](T* obj, const UIActionContext&) { activate(obj); }, [=](T* obj, const UIActionContext&) { return isValid(obj); }); } template static UIAction globalSidebarAction(const QString& name, const std::function& activate, const std::function& isValid) { return globalSidebarAction(Sidebar::typeFromName(name), activate, isValid); } template static UIAction globalSidebarAction(SidebarWidgetType* type, const std::function& activate) { return globalSidebarAction( type, [=](T* obj, const UIActionContext&) { activate(obj); }, [=](T*, const UIActionContext&) { return true; }); } template static UIAction globalSidebarAction( SidebarWidgetType* type, const std::function& activate) { return globalSidebarAction(type, activate, [](T*, const UIActionContext&) { return true; }); } template static UIAction globalSidebarAction(SidebarWidgetType* type, const std::function& activate, const std::function& isValid) { return globalSidebarAction( type, [=](T* obj, const UIActionContext&) { activate(obj); }, [=](T* obj, const UIActionContext&) { return isValid(obj); }); } template static UIAction globalSidebarAction(SidebarWidgetType* type, const std::function& activate, const std::function& isValid) { std::function lookup = [=](const UIActionContext& ctxt) { if (!type || !ctxt.context) return (T*)nullptr; Sidebar* sidebar = ctxt.context->sidebar(); if (!sidebar->isActive(type)) return (T*)nullptr; QWidget* widget = sidebar->widget(type); if (!widget) return (T*)nullptr; return qobject_cast(widget); }; return UIAction( [=](const UIActionContext& ctxt) { T* obj = lookup(ctxt); if (obj) activate(obj, ctxt); }, [=](const UIActionContext& ctxt) { T* obj = lookup(ctxt); if (obj) return isValid(obj, ctxt); return false; }); } template static std::function globalSidebarActionChecked( const QString& name, const std::function& isChecked) { return globalSidebarActionChecked(name, [=](T* obj, const UIActionContext&) { return isChecked(obj); }); } template static std::function globalSidebarActionChecked( const QString& name, const std::function& isChecked) { return globalSidebarActionChecked(Sidebar::typeFromName(name), isChecked); } template static std::function globalSidebarActionChecked( SidebarWidgetType* type, const std::function& isChecked) { return globalSidebarActionChecked(type, [=](T* obj, const UIActionContext&) { return isChecked(obj); }); } template static std::function globalSidebarActionChecked( SidebarWidgetType* type, const std::function& isChecked) { return [=](const UIActionContext& ctxt) { if (!type || !ctxt.context) return false; Sidebar* sidebar = ctxt.context->sidebar(); if (!sidebar->isActive(type)) return false; QWidget* widget = sidebar->widget(type); if (!widget) return false; T* obj = qobject_cast(widget); if (obj) return isChecked(obj, ctxt); return false; }; } };