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