1 #include "obs.hpp"
2 #include "scene-tree.hpp"
3 #include "obs-app.hpp"
4
5 #include <QSizePolicy>
6 #include <QScrollBar>
7 #include <QDropEvent>
8 #include <QPushButton>
9 #include <QTimer>
10
SceneTree(QWidget * parent_)11 SceneTree::SceneTree(QWidget *parent_) : QListWidget(parent_)
12 {
13 installEventFilter(this);
14 setDragDropMode(InternalMove);
15 setMovement(QListView::Snap);
16 }
17
SetGridMode(bool grid)18 void SceneTree::SetGridMode(bool grid)
19 {
20 config_set_bool(App()->GlobalConfig(), "BasicWindow", "gridMode", grid);
21 parent()->setProperty("gridMode", grid);
22 gridMode = grid;
23
24 if (gridMode) {
25 setResizeMode(QListView::Adjust);
26 setViewMode(QListView::IconMode);
27 setUniformItemSizes(true);
28 setStyleSheet("*{padding: 0; margin: 0;}");
29 } else {
30 setViewMode(QListView::ListMode);
31 setResizeMode(QListView::Fixed);
32 setStyleSheet("");
33 }
34
35 QResizeEvent event(size(), size());
36 resizeEvent(&event);
37 }
38
GetGridMode()39 bool SceneTree::GetGridMode()
40 {
41 return gridMode;
42 }
43
SetGridItemWidth(int width)44 void SceneTree::SetGridItemWidth(int width)
45 {
46 maxWidth = width;
47 }
48
SetGridItemHeight(int height)49 void SceneTree::SetGridItemHeight(int height)
50 {
51 itemHeight = height;
52 }
53
GetGridItemWidth()54 int SceneTree::GetGridItemWidth()
55 {
56 return maxWidth;
57 }
58
GetGridItemHeight()59 int SceneTree::GetGridItemHeight()
60 {
61 return itemHeight;
62 }
63
eventFilter(QObject * obj,QEvent * event)64 bool SceneTree::eventFilter(QObject *obj, QEvent *event)
65 {
66 return QObject::eventFilter(obj, event);
67 }
68
resizeEvent(QResizeEvent * event)69 void SceneTree::resizeEvent(QResizeEvent *event)
70 {
71 if (gridMode) {
72 int scrollWid = verticalScrollBar()->sizeHint().width();
73 int h = visualItemRect(item(count() - 1)).bottom();
74
75 if (h < height()) {
76 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
77 scrollWid = 0;
78 } else {
79 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
80 }
81
82 int wid = contentsRect().width() - scrollWid - 1;
83 int items = (int)ceil((float)wid / maxWidth);
84 int itemWidth = wid / items;
85
86 setGridSize(QSize(itemWidth, itemHeight));
87
88 for (int i = 0; i < count(); i++) {
89 item(i)->setSizeHint(QSize(itemWidth, itemHeight));
90 }
91 } else {
92 setGridSize(QSize());
93 setSpacing(0);
94 for (int i = 0; i < count(); i++) {
95 item(i)->setData(Qt::SizeHintRole, QVariant());
96 }
97 }
98
99 QListWidget::resizeEvent(event);
100 }
101
startDrag(Qt::DropActions supportedActions)102 void SceneTree::startDrag(Qt::DropActions supportedActions)
103 {
104 QListWidget::startDrag(supportedActions);
105 }
106
dropEvent(QDropEvent * event)107 void SceneTree::dropEvent(QDropEvent *event)
108 {
109 if (event->source() != this) {
110 QListWidget::dropEvent(event);
111 return;
112 }
113
114 if (gridMode) {
115 int scrollWid = verticalScrollBar()->sizeHint().width();
116 int h = visualItemRect(item(count() - 1)).bottom();
117
118 if (h < height()) {
119 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
120 scrollWid = 0;
121 } else {
122 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
123 }
124
125 float wid = contentsRect().width() - scrollWid - 1;
126
127 QPoint point = event->pos();
128
129 int x = (float)point.x() / wid * ceil(wid / maxWidth);
130 int y = point.y() / itemHeight;
131
132 int r = x + y * ceil(wid / maxWidth);
133
134 QListWidgetItem *item = takeItem(selectedIndexes()[0].row());
135 insertItem(r, item);
136 setCurrentItem(item);
137 resize(size());
138 }
139
140 QListWidget::dropEvent(event);
141
142 QTimer::singleShot(100, [this]() { emit scenesReordered(); });
143 }
144
RepositionGrid(QDragMoveEvent * event)145 void SceneTree::RepositionGrid(QDragMoveEvent *event)
146 {
147 int scrollWid = verticalScrollBar()->sizeHint().width();
148 int h = visualItemRect(item(count() - 1)).bottom();
149
150 if (h < height()) {
151 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
152 scrollWid = 0;
153 } else {
154 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
155 }
156
157 float wid = contentsRect().width() - scrollWid - 1;
158
159 if (event) {
160 QPoint point = event->pos();
161
162 int x = (float)point.x() / wid * ceil(wid / maxWidth);
163 int y = point.y() / itemHeight;
164
165 int r = x + y * ceil(wid / maxWidth);
166 int orig = selectedIndexes()[0].row();
167
168 for (int i = 0; i < count(); i++) {
169 auto *wItem = item(i);
170
171 if (wItem->isSelected())
172 continue;
173
174 QModelIndex index = indexFromItem(wItem);
175
176 int off = (i >= r ? 1 : 0) -
177 (i > orig && i > r ? 1 : 0) -
178 (i > orig && i == r ? 2 : 0);
179
180 int xPos = (i + off) % (int)ceil(wid / maxWidth);
181 int yPos = (i + off) / (int)ceil(wid / maxWidth);
182 QSize g = gridSize();
183
184 QPoint position(xPos * g.width(), yPos * g.height());
185 setPositionForIndex(position, index);
186 }
187 } else {
188 for (int i = 0; i < count(); i++) {
189 auto *wItem = item(i);
190
191 if (wItem->isSelected())
192 continue;
193
194 QModelIndex index = indexFromItem(wItem);
195
196 int xPos = i % (int)ceil(wid / maxWidth);
197 int yPos = i / (int)ceil(wid / maxWidth);
198 QSize g = gridSize();
199
200 QPoint position(xPos * g.width(), yPos * g.height());
201 setPositionForIndex(position, index);
202 }
203 }
204 }
205
dragMoveEvent(QDragMoveEvent * event)206 void SceneTree::dragMoveEvent(QDragMoveEvent *event)
207 {
208 if (gridMode) {
209 RepositionGrid(event);
210 }
211
212 QListWidget::dragMoveEvent(event);
213 }
214
dragLeaveEvent(QDragLeaveEvent * event)215 void SceneTree::dragLeaveEvent(QDragLeaveEvent *event)
216 {
217 if (gridMode) {
218 RepositionGrid();
219 }
220
221 QListWidget::dragLeaveEvent(event);
222 }
223
rowsInserted(const QModelIndex & parent,int start,int end)224 void SceneTree::rowsInserted(const QModelIndex &parent, int start, int end)
225 {
226 QResizeEvent event(size(), size());
227 SceneTree::resizeEvent(&event);
228
229 QListWidget::rowsInserted(parent, start, end);
230 }
231