SceneTree.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "SceneTree.hpp"
  2. #include <QScrollBar>
  3. #include <QTimer>
  4. #include "moc_SceneTree.cpp"
  5. SceneTree::SceneTree(QWidget *parent_) : QListWidget(parent_)
  6. {
  7. installEventFilter(this);
  8. setDragDropMode(InternalMove);
  9. setMovement(QListView::Snap);
  10. }
  11. void SceneTree::SetGridMode(bool grid)
  12. {
  13. parent()->setProperty("class", grid ? "list-grid" : "");
  14. gridMode = grid;
  15. if (gridMode) {
  16. setResizeMode(QListView::Adjust);
  17. setViewMode(QListView::IconMode);
  18. setUniformItemSizes(true);
  19. setStyleSheet("*{padding: 0; margin: 0;}");
  20. } else {
  21. setViewMode(QListView::ListMode);
  22. setResizeMode(QListView::Fixed);
  23. setStyleSheet("");
  24. }
  25. QResizeEvent event(size(), size());
  26. resizeEvent(&event);
  27. }
  28. bool SceneTree::GetGridMode()
  29. {
  30. return gridMode;
  31. }
  32. void SceneTree::SetGridItemWidth(int width)
  33. {
  34. maxWidth = width;
  35. }
  36. void SceneTree::SetGridItemHeight(int height)
  37. {
  38. itemHeight = height;
  39. }
  40. int SceneTree::GetGridItemWidth()
  41. {
  42. return maxWidth;
  43. }
  44. int SceneTree::GetGridItemHeight()
  45. {
  46. return itemHeight;
  47. }
  48. bool SceneTree::eventFilter(QObject *obj, QEvent *event)
  49. {
  50. return QObject::eventFilter(obj, event);
  51. }
  52. void SceneTree::resizeEvent(QResizeEvent *event)
  53. {
  54. if (gridMode) {
  55. int scrollWid = verticalScrollBar()->sizeHint().width();
  56. const QRect lastItem = visualItemRect(item(count() - 1));
  57. const int h = lastItem.y() + lastItem.height();
  58. if (h < height()) {
  59. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  60. scrollWid = 0;
  61. } else {
  62. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  63. }
  64. int wid = contentsRect().width() - scrollWid - 1;
  65. int items = (int)std::ceil((float)wid / maxWidth);
  66. int itemWidth = wid / items;
  67. setGridSize(QSize(itemWidth, itemHeight));
  68. for (int i = 0; i < count(); i++) {
  69. item(i)->setSizeHint(QSize(itemWidth, itemHeight));
  70. }
  71. } else {
  72. setGridSize(QSize());
  73. for (int i = 0; i < count(); i++) {
  74. item(i)->setData(Qt::SizeHintRole, QVariant());
  75. }
  76. }
  77. QListWidget::resizeEvent(event);
  78. }
  79. void SceneTree::startDrag(Qt::DropActions supportedActions)
  80. {
  81. QListWidget::startDrag(supportedActions);
  82. }
  83. void SceneTree::dropEvent(QDropEvent *event)
  84. {
  85. if (event->source() != this) {
  86. QListWidget::dropEvent(event);
  87. return;
  88. }
  89. if (gridMode) {
  90. int scrollWid = verticalScrollBar()->sizeHint().width();
  91. const QRect firstItem = visualItemRect(item(0));
  92. const QRect lastItem = visualItemRect(item(count() - 1));
  93. const int h = lastItem.y() + lastItem.height();
  94. const int firstItemY = abs(firstItem.y());
  95. if (h < height()) {
  96. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  97. scrollWid = 0;
  98. } else {
  99. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  100. }
  101. float wid = contentsRect().width() - scrollWid - 1;
  102. QPoint point = event->position().toPoint();
  103. int x = (float)point.x() / wid * std::ceil(wid / maxWidth);
  104. int y = (point.y() + firstItemY) / itemHeight;
  105. int r = x + y * std::ceil(wid / maxWidth);
  106. QListWidgetItem *item = takeItem(selectedIndexes()[0].row());
  107. insertItem(r, item);
  108. setCurrentItem(item);
  109. resize(size());
  110. }
  111. QListWidget::dropEvent(event);
  112. // We must call resizeEvent to correctly place all grid items.
  113. // We also do this in rowsInserted.
  114. QResizeEvent resEvent(size(), size());
  115. SceneTree::resizeEvent(&resEvent);
  116. QTimer::singleShot(100, [this]() { emit scenesReordered(); });
  117. }
  118. void SceneTree::RepositionGrid(QDragMoveEvent *event)
  119. {
  120. int scrollWid = verticalScrollBar()->sizeHint().width();
  121. const QRect firstItem = visualItemRect(item(0));
  122. const QRect lastItem = visualItemRect(item(count() - 1));
  123. const int h = lastItem.y() + lastItem.height();
  124. const int firstItemY = abs(firstItem.y());
  125. if (h < height()) {
  126. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  127. scrollWid = 0;
  128. } else {
  129. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  130. }
  131. float wid = contentsRect().width() - scrollWid - 1;
  132. if (event) {
  133. QPoint point = event->position().toPoint();
  134. int x = (float)point.x() / wid * std::ceil(wid / maxWidth);
  135. int y = (point.y() + firstItemY) / itemHeight;
  136. int r = x + y * std::ceil(wid / maxWidth);
  137. int orig = selectedIndexes()[0].row();
  138. for (int i = 0; i < count(); i++) {
  139. auto *wItem = item(i);
  140. if (wItem->isSelected())
  141. continue;
  142. QModelIndex index = indexFromItem(wItem);
  143. int off = (i >= r ? 1 : 0) - (i > orig && i > r ? 1 : 0) - (i > orig && i == r ? 2 : 0);
  144. int xPos = (i + off) % (int)std::ceil(wid / maxWidth);
  145. int yPos = (i + off) / (int)std::ceil(wid / maxWidth);
  146. QSize g = gridSize();
  147. QPoint position(xPos * g.width(), yPos * g.height());
  148. setPositionForIndex(position, index);
  149. }
  150. } else {
  151. for (int i = 0; i < count(); i++) {
  152. auto *wItem = item(i);
  153. if (wItem->isSelected())
  154. continue;
  155. QModelIndex index = indexFromItem(wItem);
  156. int xPos = i % (int)std::ceil(wid / maxWidth);
  157. int yPos = i / (int)std::ceil(wid / maxWidth);
  158. QSize g = gridSize();
  159. QPoint position(xPos * g.width(), yPos * g.height());
  160. setPositionForIndex(position, index);
  161. }
  162. }
  163. }
  164. void SceneTree::dragMoveEvent(QDragMoveEvent *event)
  165. {
  166. if (gridMode) {
  167. RepositionGrid(event);
  168. }
  169. QListWidget::dragMoveEvent(event);
  170. }
  171. void SceneTree::dragLeaveEvent(QDragLeaveEvent *event)
  172. {
  173. if (gridMode) {
  174. RepositionGrid();
  175. }
  176. QListWidget::dragLeaveEvent(event);
  177. }
  178. void SceneTree::rowsInserted(const QModelIndex &parent, int start, int end)
  179. {
  180. QResizeEvent event(size(), size());
  181. SceneTree::resizeEvent(&event);
  182. QListWidget::rowsInserted(parent, start, end);
  183. }
  184. #if QT_VERSION < QT_VERSION_CHECK(6, 4, 3)
  185. // Workaround for QTBUG-105870. Remove once that is solved upstream.
  186. void SceneTree::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
  187. {
  188. if (selected.count() == 0 && deselected.count() > 0 && !property("clearing").toBool())
  189. setCurrentRow(deselected.indexes().front().row());
  190. }
  191. #endif