locationlist.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "locationlist.h"
  2. #include <QVBoxLayout>
  3. #include <QToolButton>
  4. #include <QLabel>
  5. #include <QHeaderView>
  6. #include "treewidget.h"
  7. #include "widgetsfactory.h"
  8. #include "titlebar.h"
  9. #include "styleditemdelegate.h"
  10. #include "navigationmodemgr.h"
  11. #include <core/vnotex.h>
  12. #include <core/thememgr.h>
  13. #include <utils/iconutils.h>
  14. #include <utils/widgetutils.h>
  15. using namespace vnotex;
  16. QIcon LocationList::s_bufferIcon;
  17. QIcon LocationList::s_fileIcon;
  18. QIcon LocationList::s_folderIcon;
  19. QIcon LocationList::s_notebookIcon;
  20. LocationList::LocationList(QWidget *p_parent)
  21. : QFrame(p_parent)
  22. {
  23. setupUI();
  24. }
  25. void LocationList::setupUI()
  26. {
  27. auto mainLayout = new QVBoxLayout(this);
  28. WidgetUtils::setContentsMargins(mainLayout);
  29. {
  30. setupTitleBar(QString(), this);
  31. mainLayout->addWidget(m_titleBar);
  32. }
  33. m_tree = new TreeWidget(TreeWidget::Flag::EnhancedStyle, this);
  34. // When updated, pay attention to the Columns enum.
  35. m_tree->setHeaderLabels(QStringList() << tr("Path") << tr("Line") << tr("Text"));
  36. TreeWidget::showHorizontalScrollbar(m_tree);
  37. m_tree->header()->setStretchLastSection(true);
  38. connect(m_tree, &QTreeWidget::itemActivated,
  39. this, [this](QTreeWidgetItem *p_item, int p_col) {
  40. Q_UNUSED(p_col);
  41. if (!m_callback) {
  42. return;
  43. }
  44. m_callback(getItemLocation(p_item));
  45. });
  46. mainLayout->addWidget(m_tree);
  47. m_navigationWrapper.reset(new NavigationModeWrapper<QTreeWidget, QTreeWidgetItem>(m_tree));
  48. NavigationModeMgr::getInst().registerNavigationTarget(m_navigationWrapper.data());
  49. setFocusProxy(m_tree);
  50. }
  51. const QIcon &LocationList::getItemIcon(LocationType p_type)
  52. {
  53. if (s_bufferIcon.isNull()) {
  54. // Init.
  55. const QString nodeIconFgName = "widgets#locationlist#node_icon#fg";
  56. const auto &themeMgr = VNoteX::getInst().getThemeMgr();
  57. const auto fg = themeMgr.paletteColor(nodeIconFgName);
  58. s_bufferIcon = IconUtils::fetchIcon(themeMgr.getIconFile("buffer.svg"), fg);
  59. s_fileIcon = IconUtils::fetchIcon(themeMgr.getIconFile("file_node.svg"), fg);
  60. s_folderIcon = IconUtils::fetchIcon(themeMgr.getIconFile("folder_node.svg"), fg);
  61. s_notebookIcon = IconUtils::fetchIcon(themeMgr.getIconFile("notebook_default.svg"), fg);
  62. }
  63. switch (p_type) {
  64. case LocationType::Buffer:
  65. return s_bufferIcon;
  66. case LocationType::File:
  67. return s_fileIcon;
  68. case LocationType::Folder:
  69. return s_folderIcon;
  70. case LocationType::Notebook:
  71. Q_FALLTHROUGH();
  72. default:
  73. return s_notebookIcon;
  74. }
  75. }
  76. void LocationList::setupTitleBar(const QString &p_title, QWidget *p_parent)
  77. {
  78. m_titleBar = new TitleBar(p_title, true, TitleBar::Action::None, p_parent);
  79. m_titleBar->setActionButtonsAlwaysShown(true);
  80. {
  81. auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear"));
  82. connect(clearBtn, &QToolButton::triggered,
  83. this, &LocationList::clear);
  84. }
  85. }
  86. void LocationList::clear()
  87. {
  88. m_tree->clear();
  89. m_callback = LocationCallback();
  90. updateItemsCountLabel();
  91. }
  92. void LocationList::setItemLocationLineAndText(QTreeWidgetItem *p_item, const ComplexLocation::Line &p_line)
  93. {
  94. p_item->setData(Columns::LineColumn, Qt::UserRole, p_line.m_lineNumber);
  95. if (p_line.m_lineNumber != -1) {
  96. p_item->setText(Columns::LineColumn, QString::number(p_line.m_lineNumber + 1));
  97. }
  98. // Truncate the text.
  99. if (p_line.m_text.size() > 500) {
  100. p_item->setText(Columns::TextColumn, p_line.m_text.left(500));
  101. } else {
  102. p_item->setText(Columns::TextColumn, p_line.m_text);
  103. }
  104. if (!p_line.m_segments.isEmpty()) {
  105. p_item->setData(Columns::TextColumn, HighlightsRole, QVariant::fromValue(p_line.m_segments));
  106. }
  107. }
  108. void LocationList::addLocation(const ComplexLocation &p_location)
  109. {
  110. auto item = new QTreeWidgetItem(m_tree);
  111. item->setText(Columns::PathColumn, p_location.m_displayPath);
  112. item->setIcon(Columns::PathColumn, getItemIcon(p_location.m_type));
  113. item->setData(Columns::PathColumn, Qt::UserRole, p_location.m_path);
  114. item->setToolTip(Columns::PathColumn, p_location.m_path);
  115. if (p_location.m_lines.size() == 1) {
  116. setItemLocationLineAndText(item, p_location.m_lines[0]);
  117. } else if (p_location.m_lines.size() > 1) {
  118. // Add sub items.
  119. for (const auto &line : p_location.m_lines) {
  120. auto subItem = new QTreeWidgetItem(item);
  121. setItemLocationLineAndText(subItem, line);
  122. }
  123. item->setExpanded(true);
  124. }
  125. if (m_tree->topLevelItemCount() == 1) {
  126. m_tree->setCurrentItem(item);
  127. }
  128. updateItemsCountLabel();
  129. }
  130. void LocationList::startSession(const LocationCallback &p_callback)
  131. {
  132. m_callback = p_callback;
  133. }
  134. Location LocationList::getItemLocation(const QTreeWidgetItem *p_item) const
  135. {
  136. Location loc;
  137. if (!p_item) {
  138. return loc;
  139. }
  140. auto paItem = p_item->parent() ? p_item->parent() : p_item;
  141. loc.m_path = paItem->data(Columns::PathColumn, Qt::UserRole).toString();
  142. loc.m_displayPath = paItem->text(Columns::PathColumn);
  143. auto lineNumberData = p_item->data(Columns::LineColumn, Qt::UserRole);
  144. if (lineNumberData.isValid()) {
  145. loc.m_lineNumber = lineNumberData.toInt();
  146. }
  147. return loc;
  148. }
  149. void LocationList::updateItemsCountLabel()
  150. {
  151. const auto cnt = m_tree->topLevelItemCount();
  152. if (cnt == 0) {
  153. m_titleBar->setInfoLabel("");
  154. } else {
  155. m_titleBar->setInfoLabel(tr("%n Item(s)", "", cnt));
  156. }
  157. }