vnavigationmode.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "vnavigationmode.h"
  2. #include <QDebug>
  3. #include <QLabel>
  4. #include <QListWidget>
  5. #include <QTreeWidget>
  6. #include <QScrollBar>
  7. #include "vnote.h"
  8. #include "utils/vutils.h"
  9. #include "vtreewidget.h"
  10. extern VNote *g_vnote;
  11. VNavigationMode::VNavigationMode()
  12. : m_isSecondKey(false)
  13. {
  14. }
  15. VNavigationMode::~VNavigationMode()
  16. {
  17. }
  18. void VNavigationMode::registerNavigation(QChar p_majorKey)
  19. {
  20. m_majorKey = p_majorKey;
  21. Q_ASSERT(m_keyMap.empty());
  22. Q_ASSERT(m_naviLabels.empty());
  23. }
  24. void VNavigationMode::hideNavigation()
  25. {
  26. clearNavigation();
  27. }
  28. void VNavigationMode::showNavigation(QListWidget *p_widget)
  29. {
  30. clearNavigation();
  31. if (!p_widget->isVisible()) {
  32. return;
  33. }
  34. // Generate labels for visible items.
  35. auto items = getVisibleItems(p_widget);
  36. for (int i = 0; i < 26 && i < items.size(); ++i) {
  37. QChar key('a' + i);
  38. m_keyMap[key] = items[i];
  39. QString str = QString(m_majorKey) + key;
  40. QLabel *label = new QLabel(str, p_widget);
  41. label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
  42. label->show();
  43. QRect rect = p_widget->visualItemRect(items[i]);
  44. // Display the label at the end to show the file name.
  45. // Fix: take the vertical scrollbar into account.
  46. int extraWidth = label->width() + 2;
  47. QScrollBar *vbar = p_widget->verticalScrollBar();
  48. if (vbar && vbar->minimum() != vbar->maximum()) {
  49. extraWidth += vbar->width();
  50. }
  51. label->move(rect.x() + p_widget->rect().width() - extraWidth,
  52. rect.y());
  53. m_naviLabels.append(label);
  54. }
  55. }
  56. QList<QListWidgetItem *> VNavigationMode::getVisibleItems(const QListWidget *p_widget) const
  57. {
  58. QList<QListWidgetItem *> items;
  59. // The first visible item.
  60. QListWidgetItem *firstItem = p_widget->itemAt(0, 0);
  61. if (!firstItem) {
  62. return items;
  63. }
  64. QListWidgetItem *lastItem = NULL;
  65. lastItem = p_widget->itemAt(p_widget->viewport()->rect().bottomLeft());
  66. int first = p_widget->row(firstItem);
  67. int last = lastItem ? p_widget->row(lastItem) : (p_widget->count() - 1);
  68. for (int i = first; i <= last; ++i) {
  69. QListWidgetItem *item = p_widget->item(i);
  70. if (!item->isHidden() && item->flags() != Qt::NoItemFlags) {
  71. items.append(item);
  72. }
  73. }
  74. return items;
  75. }
  76. QList<QTreeWidgetItem *> VNavigationMode::getVisibleItems(const QTreeWidget *p_widget) const
  77. {
  78. QList<QTreeWidgetItem *> items;
  79. // The first visible item.
  80. QTreeWidgetItem *firstItem = p_widget->itemAt(0, 0);
  81. if (!firstItem) {
  82. return items;
  83. }
  84. QTreeWidgetItem *lastItem = NULL;
  85. lastItem = p_widget->itemAt(p_widget->viewport()->rect().bottomLeft());
  86. QTreeWidgetItem *item = firstItem;
  87. while (item) {
  88. items.append(item);
  89. if (item == lastItem) {
  90. break;
  91. }
  92. item = VTreeWidget::nextItem(p_widget, item, true);
  93. }
  94. return items;
  95. }
  96. bool VNavigationMode::handleKeyNavigation(QListWidget *p_widget,
  97. int p_key,
  98. bool &p_succeed)
  99. {
  100. bool ret = false;
  101. p_succeed = false;
  102. QChar keyChar = VUtils::keyToChar(p_key);
  103. if (m_isSecondKey && !keyChar.isNull()) {
  104. m_isSecondKey = false;
  105. p_succeed = true;
  106. auto it = m_keyMap.find(keyChar);
  107. if (it != m_keyMap.end()) {
  108. ret = true;
  109. p_widget->setCurrentItem(static_cast<QListWidgetItem *>(it.value()),
  110. QItemSelectionModel::ClearAndSelect);
  111. p_widget->setFocus();
  112. }
  113. } else if (keyChar == m_majorKey) {
  114. // Major key pressed.
  115. // Need second key if m_keyMap is not empty.
  116. if (m_keyMap.isEmpty()) {
  117. p_succeed = true;
  118. } else {
  119. m_isSecondKey = true;
  120. }
  121. ret = true;
  122. }
  123. return ret;
  124. }
  125. void VNavigationMode::showNavigation(QTreeWidget *p_widget)
  126. {
  127. clearNavigation();
  128. if (!p_widget->isVisible()) {
  129. return;
  130. }
  131. // Generate labels for visible items.
  132. auto items = getVisibleItems(p_widget);
  133. for (int i = 0; i < 26 && i < items.size(); ++i) {
  134. QChar key('a' + i);
  135. m_keyMap[key] = items[i];
  136. QString str = QString(m_majorKey) + key;
  137. QLabel *label = new QLabel(str, p_widget);
  138. label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
  139. label->move(p_widget->visualItemRect(items[i]).topLeft());
  140. label->show();
  141. m_naviLabels.append(label);
  142. }
  143. }
  144. void VNavigationMode::clearNavigation()
  145. {
  146. m_isSecondKey = false;
  147. m_keyMap.clear();
  148. for (auto label : m_naviLabels) {
  149. delete label;
  150. }
  151. m_naviLabels.clear();
  152. }
  153. bool VNavigationMode::handleKeyNavigation(QTreeWidget *p_widget,
  154. int p_key,
  155. bool &p_succeed)
  156. {
  157. bool ret = false;
  158. p_succeed = false;
  159. QChar keyChar = VUtils::keyToChar(p_key);
  160. if (m_isSecondKey && !keyChar.isNull()) {
  161. m_isSecondKey = false;
  162. p_succeed = true;
  163. auto it = m_keyMap.find(keyChar);
  164. if (it != m_keyMap.end()) {
  165. ret = true;
  166. p_widget->setCurrentItem(static_cast<QTreeWidgetItem *>(it.value()));
  167. p_widget->setFocus();
  168. }
  169. } else if (keyChar == m_majorKey) {
  170. // Major key pressed.
  171. // Need second key if m_keyMap is not empty.
  172. if (m_keyMap.isEmpty()) {
  173. p_succeed = true;
  174. } else {
  175. m_isSecondKey = true;
  176. }
  177. ret = true;
  178. }
  179. return ret;
  180. }