vlistwidget.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "vlistwidget.h"
  2. #include <QKeyEvent>
  3. #include <QCoreApplication>
  4. #include <QSet>
  5. #include <QScrollBar>
  6. #include "utils/vutils.h"
  7. #include "utils/vimnavigationforwidget.h"
  8. #include "vstyleditemdelegate.h"
  9. #include "vpalette.h"
  10. extern VPalette *g_palette;
  11. VListWidget::VListWidget(QWidget *p_parent)
  12. : QListWidget(p_parent),
  13. ISimpleSearch(),
  14. m_fitContent(false)
  15. {
  16. m_searchInput = new VSimpleSearchInput(this, this);
  17. connect(m_searchInput, &VSimpleSearchInput::triggered,
  18. this, &VListWidget::handleSearchModeTriggered);
  19. m_searchInput->hide();
  20. m_delegate = new VStyledItemDelegate(this, NULL);
  21. setItemDelegate(m_delegate);
  22. }
  23. void VListWidget::keyPressEvent(QKeyEvent *p_event)
  24. {
  25. if (m_searchInput->tryHandleKeyPressEvent(p_event)) {
  26. return;
  27. }
  28. if (VimNavigationForWidget::injectKeyPressEventForVim(this, p_event)) {
  29. return;
  30. }
  31. QListWidget::keyPressEvent(p_event);
  32. }
  33. void VListWidget::clearAll()
  34. {
  35. m_searchInput->clear();
  36. setSearchInputVisible(false);
  37. QListWidget::clear();
  38. }
  39. void VListWidget::setSearchInputVisible(bool p_visible)
  40. {
  41. m_searchInput->setVisible(p_visible);
  42. int bottomMargin = 0;
  43. if (p_visible) {
  44. bottomMargin = m_searchInput->height();
  45. }
  46. setViewportMargins(0, 0, 0, bottomMargin);
  47. }
  48. void VListWidget::resizeEvent(QResizeEvent *p_event)
  49. {
  50. QListWidget::resizeEvent(p_event);
  51. QRect rect = contentsRect();
  52. int width = rect.width();
  53. QScrollBar *vbar = verticalScrollBar();
  54. if (vbar && (vbar->minimum() != vbar->maximum())) {
  55. width -= vbar->width();
  56. }
  57. int y = rect.bottom() - m_searchInput->height();
  58. QScrollBar *hbar = horizontalScrollBar();
  59. if (hbar && (hbar->minimum() != hbar->maximum())) {
  60. y -= hbar->height();
  61. }
  62. m_searchInput->setGeometry(QRect(rect.left(),
  63. y,
  64. width,
  65. m_searchInput->height()));
  66. }
  67. void VListWidget::handleSearchModeTriggered(bool p_inSearchMode, bool p_focus)
  68. {
  69. if (p_inSearchMode) {
  70. setSearchInputVisible(p_inSearchMode);
  71. } else {
  72. // Hiding search input will make QWebEngine get focus which will consume
  73. // the Esc key sequence by mistake.
  74. if (p_focus) {
  75. setFocus();
  76. }
  77. setSearchInputVisible(p_inSearchMode);
  78. clearItemsHighlight();
  79. }
  80. if (p_focus) {
  81. setFocus();
  82. }
  83. }
  84. QList<void *> VListWidget::searchItems(const QString &p_text,
  85. Qt::MatchFlags p_flags) const
  86. {
  87. QList<QListWidgetItem *> items = findItems(p_text, p_flags);
  88. QList<void *> res;
  89. res.reserve(items.size());
  90. for (int i = 0; i < items.size(); ++i) {
  91. if (items[i]->type() == ItemTypeSeparator) {
  92. continue;
  93. }
  94. res.append(items[i]);
  95. }
  96. return res;
  97. }
  98. void VListWidget::highlightHitItems(const QList<void *> &p_items)
  99. {
  100. clearItemsHighlight();
  101. QSet<QModelIndex> hitIndexes;
  102. for (auto it : p_items) {
  103. QModelIndex index = indexFromItem(static_cast<QListWidgetItem *>(it));
  104. if (index.isValid()) {
  105. hitIndexes.insert(index);
  106. }
  107. }
  108. if (!hitIndexes.isEmpty()) {
  109. m_delegate->setHitItems(hitIndexes);
  110. update();
  111. }
  112. }
  113. void VListWidget::clearItemsHighlight()
  114. {
  115. m_delegate->clearHitItems();
  116. update();
  117. }
  118. void VListWidget::selectHitItem(void *p_item)
  119. {
  120. setCurrentItem(static_cast<QListWidgetItem *>(p_item),
  121. QItemSelectionModel::ClearAndSelect);
  122. }
  123. int VListWidget::totalNumberOfItems()
  124. {
  125. return count();
  126. }
  127. void VListWidget::selectNextItem(bool p_forward)
  128. {
  129. if (count() == 0) {
  130. return;
  131. }
  132. int cur = currentRow();
  133. cur = cur + (p_forward ? 1 : -1);
  134. if (cur < 0) {
  135. cur = 0;
  136. } else if (cur >= count()) {
  137. cur = count() - 1;
  138. }
  139. setCurrentRow(cur, QItemSelectionModel::ClearAndSelect);
  140. }
  141. void VListWidget::sortListWidget(QListWidget *p_list, const QVector<int> &p_sortedIdx)
  142. {
  143. int cnt = p_list->count();
  144. Q_ASSERT(cnt == p_sortedIdx.size());
  145. QVector<QListWidgetItem *> sortedItems(cnt);
  146. for (int i = 0; i < cnt; ++i) {
  147. sortedItems[i] = p_list->item(p_sortedIdx[i]);
  148. }
  149. for (int i = 0; i < cnt; ++i) {
  150. QListWidgetItem *it = p_list->takeItem(p_list->row(sortedItems[i]));
  151. p_list->insertItem(i, it);
  152. }
  153. }
  154. QSize VListWidget::sizeHint() const
  155. {
  156. int cnt = count();
  157. if (cnt == 0 || !m_fitContent) {
  158. return QListWidget::sizeHint();
  159. } else {
  160. // Adjust size to content.
  161. int hei = 0;
  162. int wid = sizeHintForColumn(0) + 10;
  163. for (int i = 0; i < cnt; ++i) {
  164. hei += sizeHintForRow(i);
  165. }
  166. hei += 2 * cnt;
  167. // Scrollbar.
  168. QScrollBar *verBar = verticalScrollBar();
  169. QScrollBar *horBar = horizontalScrollBar();
  170. if (verBar && (verBar->minimum() != verBar->maximum())) {
  171. wid += verBar->width();
  172. }
  173. if (horBar && (horBar->minimum() != horBar->maximum())) {
  174. hei += horBar->height();
  175. }
  176. return QSize(wid, hei);
  177. }
  178. }
  179. QListWidgetItem *VListWidget::createSeparatorItem(const QString &p_text)
  180. {
  181. QListWidgetItem *item = new QListWidgetItem(p_text, NULL, ItemTypeSeparator);
  182. item->setFlags(Qt::NoItemFlags);
  183. return item;
  184. }
  185. bool VListWidget::isSeparatorItem(const QListWidgetItem *p_item)
  186. {
  187. return p_item->type() == ItemTypeSeparator;
  188. }
  189. void VListWidget::moveItem(int p_srcRow, int p_destRow)
  190. {
  191. QListWidgetItem *it = takeItem(p_srcRow);
  192. if (it) {
  193. insertItem(p_destRow, it);
  194. }
  195. }