vsortdialog.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include "vsortdialog.h"
  2. #include <QtWidgets>
  3. void VTreeWidget::dropEvent(QDropEvent *p_event)
  4. {
  5. QList<QTreeWidgetItem *> dragItems = selectedItems();
  6. int first = -1, last = -1;
  7. QTreeWidgetItem *firstItem = NULL;
  8. for (int i = 0; i < dragItems.size(); ++i) {
  9. int row = indexFromItem(dragItems[i]).row();
  10. if (row > last) {
  11. last = row;
  12. }
  13. if (first == -1 || row < first) {
  14. first = row;
  15. firstItem = dragItems[i];
  16. }
  17. }
  18. Q_ASSERT(firstItem);
  19. QTreeWidget::dropEvent(p_event);
  20. int target = indexFromItem(firstItem).row();
  21. emit rowsMoved(first, last, target);
  22. }
  23. VSortDialog::VSortDialog(const QString &p_title,
  24. const QString &p_info,
  25. QWidget *p_parent)
  26. : QDialog(p_parent)
  27. {
  28. setupUI(p_title, p_info);
  29. }
  30. void VSortDialog::setupUI(const QString &p_title, const QString &p_info)
  31. {
  32. QLabel *infoLabel = NULL;
  33. if (!p_info.isEmpty()) {
  34. infoLabel = new QLabel(p_info);
  35. infoLabel->setWordWrap(true);
  36. }
  37. m_treeWidget = new VTreeWidget();
  38. m_treeWidget->setRootIsDecorated(false);
  39. m_treeWidget->setSelectionMode(QAbstractItemView::ContiguousSelection);
  40. m_treeWidget->setDragDropMode(QAbstractItemView::InternalMove);
  41. connect(m_treeWidget, &VTreeWidget::rowsMoved,
  42. this, [this](int p_first, int p_last, int p_row) {
  43. Q_UNUSED(p_first);
  44. Q_UNUSED(p_last);
  45. QTreeWidgetItem *item = m_treeWidget->topLevelItem(p_row);
  46. if (item) {
  47. m_treeWidget->setCurrentItem(item);
  48. // Select all items back.
  49. int cnt = p_last - p_first + 1;
  50. for (int i = 0; i < cnt; ++i) {
  51. QTreeWidgetItem *it = m_treeWidget->topLevelItem(p_row + i);
  52. if (it) {
  53. it->setSelected(true);
  54. }
  55. }
  56. }
  57. });
  58. // Buttons for top/up/down/bottom.
  59. m_topBtn = new QPushButton(tr("&Top"));
  60. m_topBtn->setToolTip(tr("Move selected items to top"));
  61. connect(m_topBtn, &QPushButton::clicked,
  62. this, [this]() {
  63. this->handleMoveOperation(MoveOperation::Top);
  64. });
  65. m_upBtn = new QPushButton(tr("&Up"));
  66. m_upBtn->setToolTip(tr("Move selected items up"));
  67. connect(m_upBtn, &QPushButton::clicked,
  68. this, [this]() {
  69. this->handleMoveOperation(MoveOperation::Up);
  70. });
  71. m_downBtn = new QPushButton(tr("&Down"));
  72. m_downBtn->setToolTip(tr("Move selected items down"));
  73. connect(m_downBtn, &QPushButton::clicked,
  74. this, [this]() {
  75. this->handleMoveOperation(MoveOperation::Down);
  76. });
  77. m_bottomBtn = new QPushButton(tr("&Bottom"));
  78. m_bottomBtn->setToolTip(tr("Move selected items to bottom"));
  79. connect(m_bottomBtn, &QPushButton::clicked,
  80. this, [this]() {
  81. this->handleMoveOperation(MoveOperation::Bottom);
  82. });
  83. QVBoxLayout *btnLayout = new QVBoxLayout;
  84. btnLayout->addWidget(m_topBtn);
  85. btnLayout->addWidget(m_upBtn);
  86. btnLayout->addWidget(m_downBtn);
  87. btnLayout->addWidget(m_bottomBtn);
  88. btnLayout->addStretch();
  89. QHBoxLayout *midLayout = new QHBoxLayout;
  90. midLayout->addWidget(m_treeWidget);
  91. midLayout->addLayout(btnLayout);
  92. // Ok is the default button.
  93. m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
  94. connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
  95. connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
  96. QVBoxLayout *mainLayout = new QVBoxLayout;
  97. if (infoLabel) {
  98. mainLayout->addWidget(infoLabel);
  99. }
  100. mainLayout->addLayout(midLayout);
  101. mainLayout->addWidget(m_btnBox);
  102. setLayout(mainLayout);
  103. setWindowTitle(p_title);
  104. }
  105. void VSortDialog::treeUpdated()
  106. {
  107. int cols = m_treeWidget->columnCount();
  108. for (int i = 0; i < cols; ++i) {
  109. m_treeWidget->resizeColumnToContents(i);
  110. }
  111. QHeaderView *header = m_treeWidget->header();
  112. if (header) {
  113. header->setStretchLastSection(true);
  114. }
  115. // We just need single level.
  116. int cnt = m_treeWidget->topLevelItemCount();
  117. for (int i = 0; i < cnt; ++i) {
  118. QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
  119. item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
  120. }
  121. }
  122. void VSortDialog::handleMoveOperation(MoveOperation p_op)
  123. {
  124. const QList<QTreeWidgetItem *> selectedItems = m_treeWidget->selectedItems();
  125. if (selectedItems.isEmpty()) {
  126. return;
  127. }
  128. int first = m_treeWidget->topLevelItemCount();
  129. int last = -1;
  130. for (auto const & it : selectedItems) {
  131. int idx = m_treeWidget->indexOfTopLevelItem(it);
  132. Q_ASSERT(idx > -1);
  133. if (idx < first) {
  134. first = idx;
  135. }
  136. if (idx > last) {
  137. last = idx;
  138. }
  139. }
  140. Q_ASSERT(first <= last && (last - first + 1) == selectedItems.size());
  141. QTreeWidgetItem *firstItem = NULL;
  142. switch (p_op) {
  143. case MoveOperation::Top:
  144. if (first == 0) {
  145. break;
  146. }
  147. m_treeWidget->clearSelection();
  148. // Insert item[last] to index 0 repeatedly.
  149. for (int i = last - first; i >= 0; --i) {
  150. QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last);
  151. Q_ASSERT(item);
  152. m_treeWidget->insertTopLevelItem(0, item);
  153. item->setSelected(true);
  154. }
  155. firstItem = m_treeWidget->topLevelItem(0);
  156. break;
  157. case MoveOperation::Up:
  158. if (first == 0) {
  159. break;
  160. }
  161. m_treeWidget->clearSelection();
  162. // Insert item[last] to index (first -1) repeatedly.
  163. for (int i = last - first; i >= 0; --i) {
  164. QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last);
  165. Q_ASSERT(item);
  166. m_treeWidget->insertTopLevelItem(first - 1, item);
  167. item->setSelected(true);
  168. }
  169. firstItem = m_treeWidget->topLevelItem(first - 1);
  170. break;
  171. case MoveOperation::Down:
  172. if (last == m_treeWidget->topLevelItemCount() - 1) {
  173. break;
  174. }
  175. m_treeWidget->clearSelection();
  176. // Insert item[first] to index (last) repeatedly.
  177. for (int i = last - first; i >= 0; --i) {
  178. QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first);
  179. Q_ASSERT(item);
  180. m_treeWidget->insertTopLevelItem(last + 1, item);
  181. item->setSelected(true);
  182. if (!firstItem) {
  183. firstItem = item;
  184. }
  185. }
  186. break;
  187. case MoveOperation::Bottom:
  188. if (last == m_treeWidget->topLevelItemCount() - 1) {
  189. break;
  190. }
  191. m_treeWidget->clearSelection();
  192. // Insert item[first] to the last of the tree repeatedly.
  193. for (int i = last - first; i >= 0; --i) {
  194. QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first);
  195. Q_ASSERT(item);
  196. m_treeWidget->addTopLevelItem(item);
  197. item->setSelected(true);
  198. if (!firstItem) {
  199. firstItem = item;
  200. }
  201. }
  202. break;
  203. default:
  204. return;
  205. }
  206. if (firstItem) {
  207. m_treeWidget->setCurrentItem(firstItem);
  208. m_treeWidget->scrollToItem(firstItem);
  209. }
  210. }
  211. QVector<QVariant> VSortDialog::getSortedData() const
  212. {
  213. int cnt = m_treeWidget->topLevelItemCount();
  214. QVector<QVariant> data(cnt);
  215. for (int i = 0; i < cnt; ++i) {
  216. QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
  217. Q_ASSERT(item);
  218. data[i] = item->data(0, Qt::UserRole);
  219. }
  220. return data;
  221. }