snippetpanel.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. }
  90. updateItemsCountLabel();
  91. }
  92. void SnippetPanel::showEvent(QShowEvent *p_event)
  93. {
  94. QFrame::showEvent(p_event);
  95. if (!m_listInitialized) {
  96. m_listInitialized = true;
  97. updateSnippetList();
  98. }
  99. }
  100. void SnippetPanel::handleContextMenuRequested(QPoint p_pos)
  101. {
  102. QMenu menu(this);
  103. auto item = m_snippetList->itemAt(p_pos);
  104. if (!item) {
  105. return;
  106. }
  107. const int selectedCount = m_snippetList->selectedItems().size();
  108. if (selectedCount == 1) {
  109. menu.addAction(tr("&Apply"),
  110. &menu,
  111. [this]() {
  112. applySnippet(m_snippetList->currentItem());
  113. });
  114. }
  115. menu.addAction(tr("&Delete"),
  116. this,
  117. &SnippetPanel::removeSelectedSnippets);
  118. if (selectedCount == 1) {
  119. menu.addAction(tr("&Properties (Rename)"),
  120. &menu,
  121. [this]() {
  122. auto item = m_snippetList->currentItem();
  123. if (!item) {
  124. return;
  125. }
  126. auto snippet = SnippetMgr::getInst().find(getSnippetName(item));
  127. if (!snippet) {
  128. qWarning() << "failed to find snippet for properties" << getSnippetName(item);
  129. return;
  130. }
  131. SnippetPropertiesDialog dialog(snippet.data(), VNoteX::getInst().getMainWindow());
  132. if (dialog.exec()) {
  133. updateSnippetList();
  134. }
  135. });
  136. }
  137. menu.exec(m_snippetList->mapToGlobal(p_pos));
  138. }
  139. QString SnippetPanel::getSnippetName(const QListWidgetItem *p_item)
  140. {
  141. return p_item->data(Qt::UserRole).toString();
  142. }
  143. void SnippetPanel::removeSelectedSnippets()
  144. {
  145. const auto selectedItems = m_snippetList->selectedItems();
  146. if (selectedItems.isEmpty()) {
  147. return;
  148. }
  149. QVector<ConfirmItemInfo> items;
  150. for (const auto &selectedItem : selectedItems) {
  151. const auto name = getSnippetName(selectedItem);
  152. items.push_back(ConfirmItemInfo(name,
  153. name,
  154. QString(),
  155. nullptr));
  156. }
  157. DeleteConfirmDialog dialog(tr("Confirm Deletion"),
  158. tr("Delete these snippets permanently?"),
  159. tr("Files will be deleted permanently and could not be found even "
  160. "in operating system's recycle bin."),
  161. items,
  162. DeleteConfirmDialog::Flag::None,
  163. false,
  164. VNoteX::getInst().getMainWindow());
  165. QStringList snippetsToDelete;
  166. if (dialog.exec()) {
  167. items = dialog.getConfirmedItems();
  168. for (const auto &item : items) {
  169. snippetsToDelete << item.m_name;
  170. }
  171. }
  172. if (snippetsToDelete.isEmpty()) {
  173. return;
  174. }
  175. for (const auto &snippetName : snippetsToDelete) {
  176. try {
  177. SnippetMgr::getInst().removeSnippet(snippetName);
  178. } catch (Exception &p_e) {
  179. QString msg = tr("Failed to remove snippet (%1) (%2).").arg(snippetName, p_e.what());
  180. qCritical() << msg;
  181. MessageBoxHelper::notify(MessageBoxHelper::Critical, msg, VNoteX::getInst().getMainWindow());
  182. }
  183. }
  184. updateSnippetList();
  185. }
  186. void SnippetPanel::applySnippet(const QListWidgetItem *p_item)
  187. {
  188. if (!p_item) {
  189. return;
  190. }
  191. const auto name = getSnippetName(p_item);
  192. if (!name.isEmpty()) {
  193. emit applySnippetRequested(name);
  194. }
  195. }