summaryrefslogtreecommitdiff
path: root/ui/sidebarcontainer.h
blob: 99b42b890d2170ef264eab04f15a67dd1a69dae8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#pragma once

#include <QtWidgets/QWidget>
#include <QtWidgets/QStackedWidget>
#include <QtWidgets/QWidget>
#include "splitter.h"
#include "sidebarwidget.h"

class Sidebar;
class SplitPaneWidget;

/*!
    \ingroup sidebar
*/
class BINARYNINJAUIAPI FloatingSidebarStackedWidget: public QWidget
{
	Q_OBJECT

	SidebarWidgetType* m_type;
	bool m_isWindowed;
	QSize m_savedSize;
	std::optional<QPoint> m_savedPosition;
	bool m_visible = false;

public:
	FloatingSidebarStackedWidget(
		SidebarWidgetType* type, QStackedWidget* stackedWidget, const QString& title, bool windowed);
	bool isWindowed() const;
	void setWindowed(bool windowed);
	void setVisible(bool visible) override;

	QRect savedGeometry() const;
	void setSavedGeometry(const QRect& rect);

protected:
	void closeEvent(QCloseEvent* event) override;

Q_SIGNALS:
	void floatingWidgetClosed(SidebarWidgetType* type);
};

/*!
    \ingroup sidebar
*/
struct BINARYNINJAUIAPI SidebarStackedWidget
{
	bool floating;
	QStackedWidget* stackedWidget;
	FloatingSidebarStackedWidget* floatingWidget;
};

/*!
    \ingroup sidebar
*/
enum SidebarContainerLocation
{
	LeftSideContainer,
	LeftBottomContainer,
	RightSideContainer,
	RightBottomContainer
};

/*!
    \ingroup sidebar
*/
struct BINARYNINJAUIAPI SidebarFloatingWidgetState
{
	bool floating, windowed;
	QRect rect;
};

/*!
    \ingroup sidebar
*/
class BINARYNINJAUIAPI SidebarWidgetContainer : public QWidget
{
	Q_OBJECT

	Sidebar* m_sidebar;
	SidebarContainerLocation m_location;

	Splitter* m_contentSplitter;
	std::map<SplitPaneWidget*, std::map<QString, QVariantMap>> m_priorContentSplitterState;

	std::set<SidebarWidgetType*> m_active, m_docked;
	std::map<SidebarWidgetType*, SidebarStackedWidget> m_stackedWidgets;
	std::map<SplitPaneWidget*,
		std::map<ViewFrame*, std::map<QString, std::map<SidebarWidgetType*, SidebarWidgetAndHeader*>>>>
		m_widgets;
	std::map<SplitPaneWidget*,
		std::map<ViewFrame*, std::map<QString, std::map<SidebarWidgetType*, SidebarContentClassifier*>>>>
		m_contentClassifiers;
	std::map<SplitPaneWidget*, std::map<QString, std::set<SidebarWidgetType*>>> m_priorWidgets;

	std::map<SidebarWidgetType*, SidebarFloatingWidgetState> m_savedFloatingWidgetState;

	SidebarWidgetType* m_focusedType = nullptr;

	SidebarStackedWidget& stackedWidgetForType(SidebarWidgetType* type);
	std::vector<SidebarWidgetAndHeader*> widgetsForContext() const;
	std::vector<SidebarContentClassifier*> contentClassifiersForContext() const;
	void insertWidgetIntoContainer(SidebarWidgetType* type, QStackedWidget* widget);
	void updateContentsVisibility();

private Q_SLOTS:
	void floatingWidgetClosed(SidebarWidgetType* type);
	void childContentClassificationChanged();

public:
	SidebarWidgetContainer(Sidebar* sidebar, SidebarContainerLocation location);
	virtual ~SidebarWidgetContainer();

	Sidebar* sidebar() const { return m_sidebar; }
	Splitter* contentSplitter() const { return m_contentSplitter; }
	SidebarContainerLocation location() const { return m_location; }

	void savePriorContext();
	void setActiveContext(SplitPaneWidget* panes, const QString& dataType);
	void destroyContext(ViewFrame* frame);
	void destroyContext(SplitPaneWidget* panes);
	void destroyViewsForContext(SplitPaneWidget* panes);

	bool isContentActive() const { return !m_docked.empty(); }
	bool isActive(SidebarWidgetType* type) const { return m_active.count(type) != 0; }
	const std::set<SidebarWidgetType*>& activeTypes() const { return m_active; }
	const std::set<SidebarWidgetType*>& dockedTypes() const { return m_docked; }

	void activate(SidebarWidgetType* type);
	void deactivate(SidebarWidgetType* type);

	void moveSidebarWidgetType(SidebarWidgetType* type);
	void transferSidebarWidgetType(SidebarWidgetType* type, SidebarWidgetContainer* target);

	SidebarWidget* widget(SidebarWidgetType* type) const;
	SidebarWidget* widget(const QString& name) const;
	SidebarWidgetAndHeader* widgetAndHeader(SidebarWidgetType* type) const;

	void addWidget(SidebarWidgetType* type, SidebarWidget* widget, bool canClose = false);
	void removeWidget(SidebarWidgetType* type, SidebarWidget* widget);
	SidebarWidget* widgetWithTitle(SidebarWidgetType* type, const QString& title) const;
	bool hasWidgetWithTitle(SidebarWidgetType* type, const QString& title) const;
	bool activateWidgetWithTitle(SidebarWidgetType* type, const QString& title) const;
	SidebarContentClassification contentClassification(SidebarWidgetType* type);
	bool hasContent(SidebarWidgetType* type);
	bool shouldHide(SidebarWidgetType* type);

	SidebarContentClassifier* contentClassifier(SidebarWidgetType* type);

	virtual QSize sizeHint() const override;

	void updateTheme();
	void updateFonts();

	void saveSizes(QSettings& settings, const QString& windowStateName);
	void restoreSizes(const QSettings& settings, const QString& windowStateName);
	std::optional<SidebarFloatingWidgetState> floatingWidgetState(SidebarWidgetType* type) const;
	void restoreFloatingWidgetState(SidebarWidgetType* type, const SidebarFloatingWidgetState& state);

	void updateViewLocation(View* view, const ViewLocation& viewLocation);
	void viewChanged();

	void moveContextToContainer(SplitPaneWidget* panes, SidebarWidgetContainer* target);

	void dockWidget(SidebarWidgetType* type);
	void floatWidget(SidebarWidgetType* type);
	void windowedWidget(SidebarWidgetType* type);
	bool isDocked(SidebarWidgetType* type);
	bool isFloating(SidebarWidgetType* type);
	bool isWindowed(SidebarWidgetType* type);

	void focusChanged(SidebarWidgetAndHeader* widget);
	SidebarWidgetType* focusedType() const { return m_focusedType; }

Q_SIGNALS:
	void showContents();
	void hideContents();
	void contentClassificationChanged();
};