forked from Vector35/binaryninja-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpane.h
486 lines (381 loc) · 11.8 KB
/
pane.h
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
#pragma once
#include <QtWidgets/QWidget>
#include <QtWidgets/QStackedWidget>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QRubberBand>
#include "uicontext.h"
#include "clickablelabel.h"
#include "splitter.h"
class ViewFrame;
class FeatureMap;
class PaneHeader;
class PaneHeaderContainer;
class PaneHeaderFade;
class CloseButton;
class TabDragIndicator;
class SyncGroup;
/*!
\defgroup pane Pane
\ingroup uiapi
*/
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI Pane : public QWidget
{
Q_OBJECT
QWidget* m_widget;
PaneHeaderContainer* m_headerContainer = nullptr;
PaneHeaderFade* m_headerFade = nullptr;
PaneHeader* m_header = nullptr;
CloseButton* m_closeButton = nullptr;
bool m_active = false;
QVBoxLayout* m_layout = nullptr;
public:
Pane(QWidget* widget);
QWidget* widget() const { return m_widget; }
virtual bool canSplitPane() const { return false; }
virtual Pane* createSplitPane() { return nullptr; }
virtual void updateStatus();
virtual void focus();
virtual QString title() = 0;
void closePane();
Pane* splitPane(Qt::Orientation orientation);
void splitPane(Pane* pane, Qt::Edge edge);
void moveToNewWindow();
virtual void setIsSinglePane(bool isSinglePane);
virtual void setIsActivePane(bool active);
virtual Qt::Orientation defaultSplitDirection() const { return Qt::Horizontal; }
virtual void setDefaultSplitDirection(Qt::Orientation orientation);
void setWidget(QWidget* widget);
protected:
void init(PaneHeader* header);
Q_SIGNALS:
void paneCloseRequested();
void paneSplitRequested(Pane* newPane, Qt::Edge edge);
void movePane(Pane* target, Qt::Edge edge);
void newWindowForPane(QScreen* screen, QPoint pos);
void notifyViewChanged(ViewFrame* frame);
public Q_SLOTS:
void splitButtonClicked(Qt::Orientation orientation);
void closeButtonClicked();
void headerClicked();
void headerResized(QSize size);
void movePaneRequested(Pane* target, Qt::Edge edge);
void newWindowForPaneRequested(QScreen* screen, QPoint pos);
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI SplitButton : public ClickableIcon
{
Q_OBJECT
Qt::Orientation m_defaultOrientation;
bool m_mouseInside = false;
bool m_inverted = false;
void setIconForOrientation(Qt::Orientation orientation);
void splitHorizontal();
void splitVertical();
public:
SplitButton();
void setDefaultOrientation(Qt::Orientation orientation);
Qt::Orientation orientation() const;
Qt::Orientation defaultOrientation() const { return m_defaultOrientation; }
protected:
virtual void enterEvent(QEnterEvent* event) override;
virtual void leaveEvent(QEvent* event) override;
virtual bool eventFilter(QObject* obj, QEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override;
Q_SIGNALS:
void splitWithDirection(Qt::Orientation orientation);
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI PaneHeader : public QWidget
{
Q_OBJECT
Pane* m_owner = nullptr;
std::optional<QPoint> m_dragStart;
TabDragIndicator* m_dragIndicator = nullptr;
bool m_dragNewWindow = false;
Pane* m_dropTarget = nullptr;
Qt::Edge m_dropEdge = Qt::RightEdge;
QRubberBand* m_dropIndicator = nullptr;
public:
PaneHeader();
void setOwner(Pane* pane) { m_owner = pane; }
protected:
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override;
Q_SIGNALS:
void paneCloseRequested();
void paneSplitRequested(Qt::Orientation orientation);
void movePane(Pane* target, Qt::Edge edge);
void newWindowForPane(QScreen* screen, QPoint pos);
void headerClicked();
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI PaneHeaderContainer : public QWidget
{
Q_OBJECT
public:
PaneHeaderContainer() {}
protected:
virtual void resizeEvent(QResizeEvent* event) override;
Q_SIGNALS:
void resize(QSize size);
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI PaneHeaderFade : public QWidget
{
Q_OBJECT
bool m_active = false;
public:
PaneHeaderFade(QWidget* parent);
void setActive(bool active);
protected:
virtual void paintEvent(QPaintEvent* event) override;
};
class ViewFrame;
class ViewPaneHeader;
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI ViewPane : public Pane
{
Q_OBJECT
ViewFrame* m_frame;
UIActionHandler m_actionHandler;
ViewPaneHeader* m_header;
public:
ViewPane(ViewFrame* frame);
ViewFrame* viewFrame() const { return m_frame; }
virtual bool canSplitPane() const override { return true; }
virtual Pane* createSplitPane() override;
virtual void updateStatus() override;
virtual Qt::Orientation defaultSplitDirection() const override;
virtual void setDefaultSplitDirection(Qt::Orientation orientation) override;
virtual void focus() override;
virtual QString title() override;
#ifndef BINARYNINJAUI_BINDINGS
void recreateViewFrame(std::map<SyncGroup*, ViewLocation>& locations);
#endif
void sendViewChange();
private Q_SLOTS:
void viewChanged(ViewFrame* frame);
void viewChangeRequested(QString type);
};
class DataTypeList;
class ViewList;
class SyncGroupWidget;
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI ViewPaneHeaderSubtypeWidget : public QWidget
{
Q_OBJECT
public:
ViewPaneHeaderSubtypeWidget() {}
virtual void updateStatus() = 0;
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI ViewPaneHeader : public PaneHeader
{
Q_OBJECT
ViewPane* m_owner;
DataTypeList* m_dataTypeList;
ViewList* m_viewList;
SyncGroupWidget* m_syncGroup;
View* m_subtypeView = nullptr;
ViewPaneHeaderSubtypeWidget* m_subtypeWidget = nullptr;
QWidget* m_optionsWidget = nullptr;
QStackedWidget* m_subtypeWidgetContainer;
QStackedWidget* m_optionsWidgetContainer;
SplitButton* m_splitButton;
public:
ViewPaneHeader(ViewPane* owner, UIActionHandler* handler);
void updateStatus();
Qt::Orientation defaultSplitDirection() const;
void setDefaultSplitDirection(Qt::Orientation orientation);
void setViewFrame(ViewFrame* frame);
Q_SIGNALS:
void viewChanged(QString type);
private Q_SLOTS:
void splitButtonClicked();
void splitButtonClickedWithDirection(Qt::Orientation orientation);
void viewChangeRequested(QString type);
void updateViewType(ViewFrame* frame);
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI WidgetPane : public Pane
{
Q_OBJECT
QString m_title;
public:
WidgetPane(QWidget* widget, QString title);
virtual QString title() override { return m_title; }
virtual void updateStatus() override;
Q_SIGNALS:
void updateWidgetStatus();
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI WidgetPaneHeader : public PaneHeader
{
Q_OBJECT
QString m_title;
public:
WidgetPaneHeader(const QString& title);
protected:
virtual void paintEvent(QPaintEvent* event) override;
};
class SplitPaneWidget;
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI SplitPaneContainer : public QWidget
{
Q_OBJECT
Pane* m_pane = nullptr;
Splitter* m_splitter = nullptr;
SplitPaneContainer* m_parent = nullptr;
std::vector<SplitPaneContainer*> m_children;
Pane* m_currentChild = nullptr;
ViewPane* m_currentViewPane = nullptr;
QVBoxLayout* m_layout;
FileContext* m_fileContext = nullptr;
SplitPaneContainer(const std::vector<SplitPaneContainer*>& children, Qt::Orientation orientation);
void removeChild(SplitPaneContainer* child);
void promoteChild(SplitPaneContainer* child);
void updateDefaultSplitDirectionForColumnCount(uint64_t count);
void removePaneForRelocation();
void emitNewWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
void openForColumnCount(Pane* pane, Qt::Orientation primaryDirection, uint64_t count);
void deactivateIfCurrent(Pane* pane);
void notifyCurrentChanged(Pane* pane);
public:
SplitPaneContainer(Pane* initial);
Pane* currentPane() const { return m_currentChild; }
ViewPane* currentViewPane() const { return m_currentViewPane; }
void notifyFocused();
void updateStatus();
void enumeratePanes(const std::function<void(Pane*)>& func);
void enumerateViewPanes(const std::function<void(ViewPane*)>& func);
bool isSinglePane();
bool canSplitCurrentPane();
void closeCurrentPane();
Pane* splitCurrentPane(Qt::Orientation orientation);
Qt::Orientation defaultSplitDirection() const;
void nextPane();
void prevPane();
void focusPaneForEdge(Qt::Edge edge);
void newWindowForCurrentPane();
bool canMoveCurrentPaneToNewWindow();
SplitPaneContainer* root();
static SplitPaneContainer* containerForWidget(QWidget* widget);
FileContext* fileContext() const { return m_fileContext; }
void setFileContext(FileContext* fileContext) { m_fileContext = fileContext; }
void open(Pane* pane, Qt::Orientation primaryDirection = Qt::Vertical);
QVariantMap layoutPersistenceInfo() const;
void applyPersistedLayout(const QVariantMap&);
#ifndef BINARYNINJAUI_BINDINGS
QVariantMap serializeLayout();
void deserializeLayout(const QVariantMap& layout, std::map<ViewFrame*, ViewLocation>& locations);
void aboutToCloseViewFrames();
void recreateViewFrames(std::map<SyncGroup*, ViewLocation>& locations);
#endif
Q_SIGNALS:
void paneClosed(Pane* pane);
void currentChanged(Pane* pane);
void layoutChanged();
void notifyViewChanged(ViewFrame* frame);
void lastPaneClosed();
void newWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
private Q_SLOTS:
void paneCloseRequested();
void paneSplitRequested(Pane* newPane, Qt::Edge edge);
void movePane(Pane* target, Qt::Edge edge);
void newWindowForPaneRequested(QScreen* screen, QPoint pos);
void paneViewChanged(ViewFrame* frame);
void childPaneClosed(Pane* pane);
void childLayoutChanged();
void childViewChanged(ViewFrame* frame);
};
/*!
\ingroup pane
*/
class BINARYNINJAUIAPI SplitPaneWidget : public QWidget
{
Q_OBJECT
SplitPaneContainer* m_container;
QStackedWidget* m_featureMapContainer;
std::map<BinaryViewRef, FeatureMap*> m_featureMaps;
Splitter* m_featureMapSplitter;
bool m_rightSideFeatureMap = true;
UIActionHandler m_actionHandler;
std::map<ViewFrame*, ViewLocation> m_locations;
void bindActions();
public:
SplitPaneWidget(Pane* initial, FileContext* fileContext);
Pane* currentPane() const;
ViewPane* currentViewPane() const;
ViewFrame* currentViewFrame() const;
SplitPaneContainer* container() const { return m_container; }
FileContext* fileContext() const { return m_container->fileContext(); }
void enumeratePanes(const std::function<void(Pane*)>& func);
void enumerateViewPanes(const std::function<void(ViewPane*)>& func);
Pane* paneAt(const QPoint& pos);
void createFeatureMap();
void recreateFeatureMaps();
void refreshFeatureMap();
void updateFeatureMapLocation(const ViewLocation& location);
BinaryViewRef getCurrentBinaryView();
void updateStatus();
bool isSinglePane();
bool canSplitCurrentPane();
void closeCurrentPane();
Pane* splitCurrentPane(Qt::Orientation orientation);
Qt::Orientation defaultSplitDirection() const;
void nextPane();
void prevPane();
void focusPaneForEdge(Qt::Edge edge);
void newWindowForCurrentPane();
bool canMoveCurrentPaneToNewWindow();
QString getTabName();
void open(Pane* pane, Qt::Orientation primaryDirection = Qt::Vertical);
bool closeRequest();
void closing();
#ifndef BINARYNINJAUI_BINDINGS
bool hasInitialLocationState() { return !m_locations.empty(); }
void applyInitialLocationState();
QVariantMap serializeLayout();
void deserializeLayout(const QVariantMap& layout);
void recreateViewFrames(std::map<SyncGroup*, ViewLocation>& locations);
#endif
static void registerActions();
Q_SIGNALS:
void paneClosed(Pane* pane);
void currentChanged(Pane* pane);
void layoutChanged();
void notifyViewChanged(ViewFrame* frame);
void newWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
private Q_SLOTS:
void containerPaneClosed(Pane* pane);
void containerCurrentChanged(Pane* pane);
void containerLayoutChanged();
void containerNotifyViewChanged(ViewFrame* frame);
void containerLastPaneClosed();
void containerNewWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
void featureMapSplitterMoved();
};