0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 04:42:18 +02:00
obs-studio/UI/scene-tree.cpp
gxalpha 860b309db8 UI: Remove spacing from scene and source tree
Due to QTBUG-106395, sources or scenes that are drag-and-dropped into
the spacing between other sources and scenes would currently go to the
bottom of the list, leaving users confused. Until that is fixed, we have
to remove this spacing.
The call in scene-tree.cpp was redundant anyways, should this commit get
reverted in the future it doesn't need to be re-added.
2022-09-10 16:32:46 -07:00

258 lines
5.9 KiB
C++

#include "obs.hpp"
#include "scene-tree.hpp"
#include "obs-app.hpp"
#include <QSizePolicy>
#include <QScrollBar>
#include <QDropEvent>
#include <QPushButton>
#include <QTimer>
SceneTree::SceneTree(QWidget *parent_) : QListWidget(parent_)
{
installEventFilter(this);
setDragDropMode(InternalMove);
setMovement(QListView::Snap);
}
void SceneTree::SetGridMode(bool grid)
{
config_set_bool(App()->GlobalConfig(), "BasicWindow", "gridMode", grid);
parent()->setProperty("gridMode", grid);
gridMode = grid;
if (gridMode) {
setResizeMode(QListView::Adjust);
setViewMode(QListView::IconMode);
setUniformItemSizes(true);
setStyleSheet("*{padding: 0; margin: 0;}");
} else {
setViewMode(QListView::ListMode);
setResizeMode(QListView::Fixed);
setStyleSheet("");
}
QResizeEvent event(size(), size());
resizeEvent(&event);
}
bool SceneTree::GetGridMode()
{
return gridMode;
}
void SceneTree::SetGridItemWidth(int width)
{
maxWidth = width;
}
void SceneTree::SetGridItemHeight(int height)
{
itemHeight = height;
}
int SceneTree::GetGridItemWidth()
{
return maxWidth;
}
int SceneTree::GetGridItemHeight()
{
return itemHeight;
}
bool SceneTree::eventFilter(QObject *obj, QEvent *event)
{
return QObject::eventFilter(obj, event);
}
void SceneTree::resizeEvent(QResizeEvent *event)
{
if (gridMode) {
int scrollWid = verticalScrollBar()->sizeHint().width();
const QRect lastItem = visualItemRect(item(count() - 1));
const int h = lastItem.y() + lastItem.height();
if (h < height()) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollWid = 0;
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
int wid = contentsRect().width() - scrollWid - 1;
int items = (int)ceil((float)wid / maxWidth);
int itemWidth = wid / items;
setGridSize(QSize(itemWidth, itemHeight));
for (int i = 0; i < count(); i++) {
item(i)->setSizeHint(QSize(itemWidth, itemHeight));
}
} else {
setGridSize(QSize());
for (int i = 0; i < count(); i++) {
item(i)->setData(Qt::SizeHintRole, QVariant());
}
}
QListWidget::resizeEvent(event);
}
void SceneTree::startDrag(Qt::DropActions supportedActions)
{
QListWidget::startDrag(supportedActions);
}
void SceneTree::dropEvent(QDropEvent *event)
{
if (event->source() != this) {
QListWidget::dropEvent(event);
return;
}
if (gridMode) {
int scrollWid = verticalScrollBar()->sizeHint().width();
const QRect firstItem = visualItemRect(item(0));
const QRect lastItem = visualItemRect(item(count() - 1));
const int h = lastItem.y() + lastItem.height();
const int firstItemY = abs(firstItem.y());
if (h < height()) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollWid = 0;
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
float wid = contentsRect().width() - scrollWid - 1;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPoint point = event->position().toPoint();
#else
QPoint point = event->pos();
#endif
int x = (float)point.x() / wid * ceil(wid / maxWidth);
int y = (point.y() + firstItemY) / itemHeight;
int r = x + y * ceil(wid / maxWidth);
QListWidgetItem *item = takeItem(selectedIndexes()[0].row());
insertItem(r, item);
setCurrentItem(item);
resize(size());
}
QListWidget::dropEvent(event);
// We must call resizeEvent to correctly place all grid items.
// We also do this in rowsInserted.
QResizeEvent resEvent(size(), size());
SceneTree::resizeEvent(&resEvent);
QTimer::singleShot(100, [this]() { emit scenesReordered(); });
}
void SceneTree::RepositionGrid(QDragMoveEvent *event)
{
int scrollWid = verticalScrollBar()->sizeHint().width();
const QRect firstItem = visualItemRect(item(0));
const QRect lastItem = visualItemRect(item(count() - 1));
const int h = lastItem.y() + lastItem.height();
const int firstItemY = abs(firstItem.y());
if (h < height()) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollWid = 0;
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
float wid = contentsRect().width() - scrollWid - 1;
if (event) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPoint point = event->position().toPoint();
#else
QPoint point = event->pos();
#endif
int x = (float)point.x() / wid * ceil(wid / maxWidth);
int y = (point.y() + firstItemY) / itemHeight;
int r = x + y * ceil(wid / maxWidth);
int orig = selectedIndexes()[0].row();
for (int i = 0; i < count(); i++) {
auto *wItem = item(i);
if (wItem->isSelected())
continue;
QModelIndex index = indexFromItem(wItem);
int off = (i >= r ? 1 : 0) -
(i > orig && i > r ? 1 : 0) -
(i > orig && i == r ? 2 : 0);
int xPos = (i + off) % (int)ceil(wid / maxWidth);
int yPos = (i + off) / (int)ceil(wid / maxWidth);
QSize g = gridSize();
QPoint position(xPos * g.width(), yPos * g.height());
setPositionForIndex(position, index);
}
} else {
for (int i = 0; i < count(); i++) {
auto *wItem = item(i);
if (wItem->isSelected())
continue;
QModelIndex index = indexFromItem(wItem);
int xPos = i % (int)ceil(wid / maxWidth);
int yPos = i / (int)ceil(wid / maxWidth);
QSize g = gridSize();
QPoint position(xPos * g.width(), yPos * g.height());
setPositionForIndex(position, index);
}
}
}
void SceneTree::dragMoveEvent(QDragMoveEvent *event)
{
if (gridMode) {
RepositionGrid(event);
}
QListWidget::dragMoveEvent(event);
}
void SceneTree::dragLeaveEvent(QDragLeaveEvent *event)
{
if (gridMode) {
RepositionGrid();
}
QListWidget::dragLeaveEvent(event);
}
void SceneTree::rowsInserted(const QModelIndex &parent, int start, int end)
{
QResizeEvent event(size(), size());
SceneTree::resizeEvent(&event);
QListWidget::rowsInserted(parent, start, end);
}
// Workaround for QTBUG-105870. Remove once that is solved upstream.
void SceneTree::selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected)
{
if (selected.count() == 0 && deselected.count() > 0)
setCurrentRow(deselected.indexes().front().row());
}