voutline.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include <QDebug>
  2. #include <QVector>
  3. #include <QString>
  4. #include <QJsonObject>
  5. #include "voutline.h"
  6. #include "vtoc.h"
  7. VOutline::VOutline(QWidget *parent)
  8. : QTreeWidget(parent)
  9. {
  10. setColumnCount(1);
  11. setHeaderHidden(true);
  12. setSelectionMode(QAbstractItemView::SingleSelection);
  13. connect(this, &VOutline::itemClicked,
  14. this, &VOutline::handleItemClicked);
  15. }
  16. void VOutline::updateOutline(const VToc &toc)
  17. {
  18. outline = toc;
  19. updateTreeFromOutline(outline);
  20. expandTree();
  21. updateCurHeader(curHeader);
  22. }
  23. void VOutline::updateTreeFromOutline(const VToc &toc)
  24. {
  25. clear();
  26. if (!toc.valid) {
  27. return;
  28. }
  29. const QVector<VHeader> &headers = toc.headers;
  30. int idx = 0;
  31. updateTreeByLevel(headers, idx, NULL, NULL, 1);
  32. }
  33. void VOutline::updateTreeByLevel(const QVector<VHeader> &headers, int &index,
  34. QTreeWidgetItem *parent, QTreeWidgetItem *last, int level)
  35. {
  36. while (index < headers.size()) {
  37. const VHeader &header = headers[index];
  38. QTreeWidgetItem *item;
  39. if (header.level == level) {
  40. if (parent) {
  41. item = new QTreeWidgetItem(parent);
  42. } else {
  43. item = new QTreeWidgetItem(this);
  44. }
  45. QJsonObject itemJson;
  46. itemJson["anchor"] = header.anchor;
  47. itemJson["line_number"] = header.lineNumber;
  48. item->setData(0, Qt::UserRole, itemJson);
  49. item->setText(0, header.name);
  50. last = item;
  51. ++index;
  52. } else if (header.level < level) {
  53. return;
  54. } else {
  55. updateTreeByLevel(headers, index, last, NULL, level + 1);
  56. }
  57. }
  58. }
  59. void VOutline::expandTree()
  60. {
  61. if (topLevelItemCount() == 0) {
  62. return;
  63. }
  64. expandAll();
  65. setItemSelected(topLevelItem(0), true);
  66. }
  67. void VOutline::handleItemClicked(QTreeWidgetItem *item, int column)
  68. {
  69. Q_ASSERT(item && column == 0);
  70. QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject();
  71. QString anchor = itemJson["anchor"].toString();
  72. int lineNumber = itemJson["line_number"].toInt();
  73. qDebug() << "click anchor" << anchor << lineNumber;
  74. emit outlineItemActivated(VAnchor(outline.filePath, anchor, lineNumber));
  75. }
  76. void VOutline::updateCurHeader(const VAnchor &anchor)
  77. {
  78. curHeader = anchor;
  79. if (outline.type == VHeaderType::Anchor) {
  80. selectAnchor(anchor.anchor);
  81. } else {
  82. // Select by lineNumber
  83. selectLineNumber(anchor.lineNumber);
  84. }
  85. }
  86. void VOutline::selectAnchor(const QString &anchor)
  87. {
  88. QList<QTreeWidgetItem *> selected = selectedItems();
  89. foreach (QTreeWidgetItem *item, selected) {
  90. setItemSelected(item, false);
  91. }
  92. int nrTop = topLevelItemCount();
  93. for (int i = 0; i < nrTop; ++i) {
  94. if (selectAnchorOne(topLevelItem(i), anchor)) {
  95. return;
  96. }
  97. }
  98. }
  99. bool VOutline::selectAnchorOne(QTreeWidgetItem *item, const QString &anchor)
  100. {
  101. if (!item) {
  102. return false;
  103. }
  104. QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject();
  105. QString itemAnchor = itemJson["anchor"].toString();
  106. if (itemAnchor == anchor) {
  107. // Select this item
  108. setItemSelected(item, true);
  109. return true;
  110. }
  111. int nrChild = item->childCount();
  112. for (int i = 0; i < nrChild; ++i) {
  113. if (selectAnchorOne(item->child(i), anchor)) {
  114. return true;
  115. }
  116. }
  117. return false;
  118. }
  119. void VOutline::selectLineNumber(int lineNumber)
  120. {
  121. QList<QTreeWidgetItem *> selected = selectedItems();
  122. foreach (QTreeWidgetItem *item, selected) {
  123. setItemSelected(item, false);
  124. }
  125. int nrTop = topLevelItemCount();
  126. for (int i = 0; i < nrTop; ++i) {
  127. if (selectLineNumberOne(topLevelItem(i), lineNumber)) {
  128. return;
  129. }
  130. }
  131. }
  132. bool VOutline::selectLineNumberOne(QTreeWidgetItem *item, int lineNumber)
  133. {
  134. if (!item) {
  135. return false;
  136. }
  137. QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject();
  138. int itemLineNum = itemJson["line_number"].toInt();
  139. if (itemLineNum == lineNumber) {
  140. // Select this item
  141. setItemSelected(item, true);
  142. return true;
  143. }
  144. int nrChild = item->childCount();
  145. for (int i = 0; i < nrChild; ++i) {
  146. if (selectLineNumberOne(item->child(i), lineNumber)) {
  147. return true;
  148. }
  149. }
  150. return false;
  151. }