snippetpanel.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "snippetpanel.h"
  2. #include <QVBoxLayout>
  3. #include <QToolButton>
  4. #include <QListWidgetItem>
  5. #include <utils/widgetutils.h>
  6. #include <snippet/snippetmgr.h>
  7. #include <core/vnotex.h>
  8. #include <core/exception.h>
  9. #include "titlebar.h"
  10. #include "listwidget.h"
  11. #include "dialogs/newsnippetdialog.h"
  12. #include "dialogs/snippetpropertiesdialog.h"
  13. #include "dialogs/deleteconfirmdialog.h"
  14. #include "mainwindow.h"
  15. #include "messageboxhelper.h"
  16. using namespace vnotex;
  17. SnippetPanel::SnippetPanel(QWidget *p_parent)
  18. : QFrame(p_parent)
  19. {
  20. setupUI();
  21. }
  22. void SnippetPanel::setupUI()
  23. {
  24. auto mainLayout = new QVBoxLayout(this);
  25. WidgetUtils::setContentsMargins(mainLayout);
  26. {
  27. setupTitleBar(QString(), this);
  28. mainLayout->addWidget(m_titleBar);
  29. }
  30. m_snippetList = new ListWidget(this);
  31. m_snippetList->setContextMenuPolicy(Qt::CustomContextMenu);
  32. m_snippetList->setSelectionMode(QAbstractItemView::ExtendedSelection);
  33. connect(m_snippetList, &QListWidget::customContextMenuRequested,
  34. this, &SnippetPanel::handleContextMenuRequested);
  35. connect(m_snippetList, &QListWidget::itemActivated,
  36. this, &SnippetPanel::applySnippet);
  37. mainLayout->addWidget(m_snippetList);
  38. setFocusProxy(m_snippetList);
  39. }
  40. void SnippetPanel::setupTitleBar(const QString &p_title, QWidget *p_parent)
  41. {
  42. m_titleBar = new TitleBar(p_title, true, TitleBar::Action::None, p_parent);
  43. m_titleBar->setActionButtonsAlwaysShown(true);
  44. {
  45. auto newBtn = m_titleBar->addActionButton(QStringLiteral("add.svg"), tr("New Snippet"));
  46. connect(newBtn, &QToolButton::triggered,
  47. this, &SnippetPanel::newSnippet);
  48. }
  49. {
  50. auto openFolderBtn = m_titleBar->addActionButton(QStringLiteral("open_folder.svg"), tr("Open Folder"));
  51. connect(openFolderBtn, &QToolButton::triggered,
  52. this, [this]() {
  53. WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(SnippetMgr::getInst().getSnippetFolder()));
  54. });
  55. }
  56. }
  57. void SnippetPanel::newSnippet()
  58. {
  59. NewSnippetDialog dialog(VNoteX::getInst().getMainWindow());
  60. if (dialog.exec() == QDialog::Accepted) {
  61. updateSnippetList();
  62. }
  63. }
  64. void SnippetPanel::updateItemsCountLabel()
  65. {
  66. const auto cnt = m_snippetList->count();
  67. if (cnt == 0) {
  68. m_titleBar->setInfoLabel("");
  69. } else {
  70. m_titleBar->setInfoLabel(tr("%n Item(s)", "", cnt));
  71. }
  72. }
  73. void SnippetPanel::updateSnippetList()
  74. {
  75. m_snippetList->clear();
  76. const auto &snippets = SnippetMgr::getInst().getSnippets();
  77. for (const auto &snippet : snippets) {
  78. auto item = new QListWidgetItem(m_snippetList);
  79. QString suffix;
  80. if (snippet->isReadOnly()) {
  81. suffix = QLatin1Char('*');
  82. }
  83. if (snippet->getShortcut() == Snippet::InvalidShortcut) {
  84. item->setText(snippet->getName() + suffix);
  85. } else {
  86. item->setText(tr("%1%2 [%3]").arg(snippet->getName(), suffix, snippet->getShortcutString()));
  87. }
  88. item->setData(Qt::UserRole, snippet->getName());
  89. item->setToolTip(snippet->getDescription());
  90. }
  91. updateItemsCountLabel();
  92. }
  93. void SnippetPanel::showEvent(QShowEvent *p_event)
  94. {
  95. QFrame::showEvent(p_event);
  96. if (!m_listInitialized) {
  97. m_listInitialized = true;
  98. updateSnippetList();
  99. }
  100. }
  101. void SnippetPanel::handleContextMenuRequested(QPoint p_pos)
  102. {
  103. QMenu menu(this);
  104. auto item = m_snippetList->itemAt(p_pos);
  105. if (!item) {
  106. return;
  107. }
  108. const int selectedCount = m_snippetList->selectedItems().size();
  109. if (selectedCount == 1) {
  110. menu.addAction(tr("&Apply"),
  111. &menu,
  112. [this]() {
  113. applySnippet(m_snippetList->currentItem());
  114. });
  115. }
  116. menu.addAction(tr("&Delete"),
  117. this,
  118. &SnippetPanel::removeSelectedSnippets);
  119. if (selectedCount == 1) {
  120. menu.addAction(tr("&Properties (Rename)"),
  121. &menu,
  122. [this]() {
  123. auto item = m_snippetList->currentItem();
  124. if (!item) {
  125. return;
  126. }
  127. auto snippet = SnippetMgr::getInst().find(getSnippetName(item));
  128. if (!snippet) {
  129. qWarning() << "failed to find snippet for properties" << getSnippetName(item);
  130. return;
  131. }
  132. SnippetPropertiesDialog dialog(snippet.data(), VNoteX::getInst().getMainWindow());
  133. if (dialog.exec()) {
  134. updateSnippetList();
  135. }
  136. });
  137. }
  138. menu.exec(m_snippetList->mapToGlobal(p_pos));
  139. }
  140. QString SnippetPanel::getSnippetName(const QListWidgetItem *p_item)
  141. {
  142. return p_item->data(Qt::UserRole).toString();
  143. }
  144. void SnippetPanel::removeSelectedSnippets()
  145. {
  146. const auto selectedItems = m_snippetList->selectedItems();
  147. if (selectedItems.isEmpty()) {
  148. return;
  149. }
  150. QVector<ConfirmItemInfo> items;
  151. for (const auto &selectedItem : selectedItems) {
  152. const auto name = getSnippetName(selectedItem);
  153. items.push_back(ConfirmItemInfo(name,
  154. name,
  155. QString(),
  156. nullptr));
  157. }
  158. DeleteConfirmDialog dialog(tr("Confirm Deletion"),
  159. tr("Delete these snippets permanently?"),
  160. tr("Files will be deleted permanently and could not be found even "
  161. "in operating system's recycle bin."),
  162. items,
  163. DeleteConfirmDialog::Flag::None,
  164. false,
  165. VNoteX::getInst().getMainWindow());
  166. QStringList snippetsToDelete;
  167. if (dialog.exec()) {
  168. items = dialog.getConfirmedItems();
  169. for (const auto &item : items) {
  170. snippetsToDelete << item.m_name;
  171. }
  172. }
  173. if (snippetsToDelete.isEmpty()) {
  174. return;
  175. }
  176. for (const auto &snippetName : snippetsToDelete) {
  177. try {
  178. SnippetMgr::getInst().removeSnippet(snippetName);
  179. } catch (Exception &p_e) {
  180. QString msg = tr("Failed to remove snippet (%1) (%2).").arg(snippetName, p_e.what());
  181. qCritical() << msg;
  182. MessageBoxHelper::notify(MessageBoxHelper::Critical, msg, VNoteX::getInst().getMainWindow());
  183. }
  184. }
  185. updateSnippetList();
  186. }
  187. void SnippetPanel::applySnippet(const QListWidgetItem *p_item)
  188. {
  189. if (!p_item) {
  190. return;
  191. }
  192. const auto name = getSnippetName(p_item);
  193. if (!name.isEmpty()) {
  194. emit applySnippetRequested(name);
  195. }
  196. }