viewwindowtoolbarhelper.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. #include "viewwindowtoolbarhelper.h"
  2. #include <QToolBar>
  3. #include <QAction>
  4. #include <QShortcut>
  5. #include <QKeySequence>
  6. #include <QCoreApplication>
  7. #include <QToolButton>
  8. #include <QMenu>
  9. #include <QDebug>
  10. #include <QActionGroup>
  11. #include "toolbarhelper.h"
  12. #include <utils/iconutils.h>
  13. #include <utils/widgetutils.h>
  14. #include <core/configmgr.h>
  15. #include <core/editorconfig.h>
  16. #include "editreaddiscardaction.h"
  17. #include "widgetsfactory.h"
  18. #include "attachmentpopup.h"
  19. #include "tagpopup.h"
  20. #include "wordcountpopup.h"
  21. #include "propertydefs.h"
  22. #include "outlinepopup.h"
  23. #include "viewwindow.h"
  24. #include <core/global.h>
  25. using namespace vnotex;
  26. typedef EditorConfig::Shortcut Shortcut;
  27. // To get the right shortcut context, we use a separate QShrotcut for the action shortcut.
  28. // @p_parentAction: the parent action of @p_action which is in a menu of @p_parentAction.
  29. void ViewWindowToolBarHelper::addActionShortcut(QAction *p_action,
  30. const QString &p_shortcut,
  31. QWidget *p_widget,
  32. QAction *p_parentAction)
  33. {
  34. auto shortcut = WidgetUtils::createShortcut(p_shortcut, p_widget, Qt::WidgetWithChildrenShortcut);
  35. if (!shortcut) {
  36. return;
  37. }
  38. QObject::connect(shortcut, &QShortcut::activated,
  39. p_action, [p_action, p_parentAction]() {
  40. if (p_action->isEnabled()) {
  41. if (p_parentAction) {
  42. if (p_parentAction->isEnabled()) {
  43. p_action->trigger();
  44. }
  45. } else {
  46. p_action->trigger();
  47. }
  48. }
  49. });
  50. QObject::connect(shortcut, &QShortcut::activatedAmbiguously,
  51. p_action, [p_action]() {
  52. qWarning() << "ViewWindow shortcut activated ambiguously" << p_action->text();
  53. });
  54. p_action->setText(QString("%1\t%2").arg(p_action->text(), shortcut->key().toString(QKeySequence::NativeText)));
  55. }
  56. void ViewWindowToolBarHelper::addButtonShortcut(QToolButton *p_btn,
  57. const QString &p_shortcut,
  58. QWidget *p_widget)
  59. {
  60. auto shortcut = WidgetUtils::createShortcut(p_shortcut, p_widget, Qt::WidgetWithChildrenShortcut);
  61. if (!shortcut) {
  62. return;
  63. }
  64. QObject::connect(shortcut, &QShortcut::activated,
  65. p_btn, [p_btn]() {
  66. if (p_btn->isEnabled()) {
  67. p_btn->click();
  68. }
  69. });
  70. auto act = p_btn->defaultAction();
  71. if (act) {
  72. act->setText(QString("%1\t%2").arg(act->text(), shortcut->key().toString(QKeySequence::NativeText)));
  73. } else {
  74. p_btn->setText(QString("%1\t%2").arg(p_btn->text(), shortcut->key().toString(QKeySequence::NativeText)));
  75. }
  76. }
  77. QAction *ViewWindowToolBarHelper::addAction(QToolBar *p_tb, Action p_action)
  78. {
  79. auto viewWindow = static_cast<ViewWindow *>(p_tb->parent());
  80. const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
  81. QAction *act = nullptr;
  82. switch (p_action) {
  83. case Action::Save:
  84. act = p_tb->addAction(ToolBarHelper::generateIcon("save_editor.svg"),
  85. ViewWindow::tr("Save"));
  86. addActionShortcut(act, editorConfig.getShortcut(Shortcut::Save), viewWindow);
  87. break;
  88. case Action::EditReadDiscard:
  89. {
  90. auto erdAct = new EditReadDiscardAction(ToolBarHelper::generateIcon("edit_editor.svg"),
  91. ViewWindow::tr("Edit"),
  92. ToolBarHelper::generateIcon("read_editor.svg"),
  93. ViewWindow::tr("Read"),
  94. ToolBarHelper::generateIcon("discard_editor.svg"),
  95. ViewWindow::tr("Discard"),
  96. p_tb);
  97. act = erdAct;
  98. addActionShortcut(erdAct, editorConfig.getShortcut(Shortcut::EditRead), viewWindow);
  99. auto discardAct = erdAct->getDiscardAction();
  100. addActionShortcut(discardAct, editorConfig.getShortcut(Shortcut::Discard), viewWindow);
  101. p_tb->addAction(erdAct);
  102. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(erdAct));
  103. Q_ASSERT(toolBtn);
  104. erdAct->setToolButtonForAction(toolBtn);
  105. break;
  106. }
  107. case Action::ViewMode:
  108. {
  109. act = p_tb->addAction(ToolBarHelper::generateIcon("view_mode_editor.svg"),
  110. ViewWindow::tr("View Mode"));
  111. WidgetUtils::addActionShortcutText(act, editorConfig.getShortcut(Shortcut::AlternateViewMode));
  112. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  113. Q_ASSERT(toolBtn);
  114. toolBtn->setPopupMode(QToolButton::InstantPopup);
  115. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  116. break;
  117. }
  118. case Action::TypeHeading:
  119. {
  120. act = p_tb->addAction(ToolBarHelper::generateIcon("type_heading_editor.svg"),
  121. ViewWindow::tr("Heading"));
  122. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  123. Q_ASSERT(toolBtn);
  124. toolBtn->setPopupMode(QToolButton::InstantPopup);
  125. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  126. auto menu = WidgetsFactory::createMenu(p_tb);
  127. auto act1 = menu->addAction(ViewWindow::tr("Heading 1"));
  128. addActionShortcut(act1,
  129. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading1),
  130. viewWindow,
  131. act);
  132. act1->setData(1);
  133. auto act2 = menu->addAction(ViewWindow::tr("Heading 2"));
  134. addActionShortcut(act2,
  135. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading2),
  136. viewWindow,
  137. act);
  138. act2->setData(2);
  139. auto act3 = menu->addAction(ViewWindow::tr("Heading 3"));
  140. addActionShortcut(act3,
  141. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading3),
  142. viewWindow,
  143. act);
  144. act3->setData(3);
  145. auto act4 = menu->addAction(ViewWindow::tr("Heading 4"));
  146. addActionShortcut(act4,
  147. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading4),
  148. viewWindow,
  149. act);
  150. act4->setData(4);
  151. auto act5 = menu->addAction(ViewWindow::tr("Heading 5"));
  152. addActionShortcut(act5,
  153. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading5),
  154. viewWindow,
  155. act);
  156. act5->setData(5);
  157. auto act6 = menu->addAction(ViewWindow::tr("Heading 6"));
  158. addActionShortcut(act6,
  159. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeading6),
  160. viewWindow,
  161. act);
  162. act6->setData(6);
  163. auto act7 = menu->addAction(ViewWindow::tr("Clear"));
  164. addActionShortcut(act7,
  165. editorConfig.getShortcut(EditorConfig::Shortcut::TypeHeadingNone),
  166. viewWindow,
  167. act);
  168. act7->setData(7);
  169. toolBtn->setMenu(menu);
  170. break;
  171. }
  172. case Action::TypeBold:
  173. act = p_tb->addAction(ToolBarHelper::generateIcon("type_bold_editor.svg"),
  174. ViewWindow::tr("Bold"));
  175. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeBold), viewWindow);
  176. break;
  177. case Action::TypeItalic:
  178. act = p_tb->addAction(ToolBarHelper::generateIcon("type_italic_editor.svg"),
  179. ViewWindow::tr("Italic"));
  180. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeItalic), viewWindow);
  181. break;
  182. case Action::TypeStrikethrough:
  183. act = p_tb->addAction(ToolBarHelper::generateIcon("type_strikethrough_editor.svg"),
  184. ViewWindow::tr("Strikethrough"));
  185. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeStrikethrough), viewWindow);
  186. break;
  187. case Action::TypeUnorderedList:
  188. act = p_tb->addAction(ToolBarHelper::generateIcon("type_unordered_list_editor.svg"),
  189. ViewWindow::tr("Unordered List"));
  190. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeUnorderedList), viewWindow);
  191. break;
  192. case Action::TypeOrderedList:
  193. act = p_tb->addAction(ToolBarHelper::generateIcon("type_ordered_list_editor.svg"),
  194. ViewWindow::tr("Ordered List"));
  195. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeOrderedList), viewWindow);
  196. break;
  197. case Action::TypeTodoList:
  198. act = p_tb->addAction(ToolBarHelper::generateIcon("type_todo_list_editor.svg"),
  199. ViewWindow::tr("Todo List"));
  200. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeTodoList), viewWindow);
  201. break;
  202. case Action::TypeCheckedTodoList:
  203. act = p_tb->addAction(ToolBarHelper::generateIcon("type_checked_todo_list_editor.svg"),
  204. ViewWindow::tr("Checked Todo List"));
  205. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeCheckedTodoList), viewWindow);
  206. break;
  207. case Action::TypeCode:
  208. act = p_tb->addAction(ToolBarHelper::generateIcon("type_code_editor.svg"),
  209. ViewWindow::tr("Code"));
  210. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeCode), viewWindow);
  211. break;
  212. case Action::TypeCodeBlock:
  213. act = p_tb->addAction(ToolBarHelper::generateIcon("type_code_block_editor.svg"),
  214. ViewWindow::tr("Code Block"));
  215. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeCodeBlock), viewWindow);
  216. break;
  217. case Action::TypeMath:
  218. act = p_tb->addAction(ToolBarHelper::generateIcon("type_math_editor.svg"),
  219. ViewWindow::tr("Math"));
  220. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeMath), viewWindow);
  221. break;
  222. case Action::TypeMathBlock:
  223. act = p_tb->addAction(ToolBarHelper::generateIcon("type_math_block_editor.svg"),
  224. ViewWindow::tr("Math Block"));
  225. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeMathBlock), viewWindow);
  226. break;
  227. case Action::TypeQuote:
  228. act = p_tb->addAction(ToolBarHelper::generateIcon("type_quote_editor.svg"),
  229. ViewWindow::tr("Quote"));
  230. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeQuote), viewWindow);
  231. break;
  232. case Action::TypeLink:
  233. act = p_tb->addAction(ToolBarHelper::generateIcon("type_link_editor.svg"),
  234. ViewWindow::tr("Link"));
  235. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeLink), viewWindow);
  236. break;
  237. case Action::TypeImage:
  238. act = p_tb->addAction(ToolBarHelper::generateIcon("type_image_editor.svg"),
  239. ViewWindow::tr("Image"));
  240. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeImage), viewWindow);
  241. break;
  242. case Action::TypeTable:
  243. act = p_tb->addAction(ToolBarHelper::generateIcon("type_table_editor.svg"),
  244. ViewWindow::tr("Table"));
  245. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeTable), viewWindow);
  246. break;
  247. case Action::TypeMark:
  248. act = p_tb->addAction(ToolBarHelper::generateIcon("type_mark_editor.svg"),
  249. ViewWindow::tr("Mark"));
  250. addActionShortcut(act, editorConfig.getShortcut(Shortcut::TypeMark), viewWindow);
  251. break;
  252. case Action::Attachment:
  253. {
  254. act = p_tb->addAction(ToolBarHelper::generateIcon("attachment_editor.svg"),
  255. ViewWindow::tr("Attachments"));
  256. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  257. Q_ASSERT(toolBtn);
  258. toolBtn->setPopupMode(QToolButton::InstantPopup);
  259. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  260. addButtonShortcut(toolBtn, editorConfig.getShortcut(Shortcut::Attachment), viewWindow);
  261. auto menu = new AttachmentPopup(toolBtn, p_tb);
  262. toolBtn->setMenu(menu);
  263. break;
  264. }
  265. case Action::Tag:
  266. {
  267. act = p_tb->addAction(ToolBarHelper::generateIcon("tag_editor.svg"),
  268. ViewWindow::tr("Tags"));
  269. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  270. Q_ASSERT(toolBtn);
  271. toolBtn->setPopupMode(QToolButton::InstantPopup);
  272. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  273. addButtonShortcut(toolBtn, editorConfig.getShortcut(Shortcut::Tag), viewWindow);
  274. auto menu = new TagPopup(toolBtn, p_tb);
  275. toolBtn->setMenu(menu);
  276. break;
  277. }
  278. case Action::Outline:
  279. {
  280. act = p_tb->addAction(ToolBarHelper::generateIcon("outline_editor.svg"),
  281. ViewWindow::tr("Outline"));
  282. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  283. Q_ASSERT(toolBtn);
  284. toolBtn->setPopupMode(QToolButton::InstantPopup);
  285. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  286. addButtonShortcut(toolBtn, editorConfig.getShortcut(Shortcut::Outline), viewWindow);
  287. auto menu = new OutlinePopup(toolBtn, p_tb);
  288. toolBtn->setMenu(menu);
  289. break;
  290. }
  291. case Action::FindAndReplace:
  292. {
  293. act = p_tb->addAction(ToolBarHelper::generateIcon("find_replace_editor.svg"),
  294. ViewWindow::tr("Find And Replace"));
  295. addActionShortcut(act, editorConfig.getShortcut(Shortcut::FindAndReplace), viewWindow);
  296. break;
  297. }
  298. case Action::SectionNumber:
  299. {
  300. act = p_tb->addAction(ToolBarHelper::generateIcon("section_number_editor.svg"),
  301. ViewWindow::tr("Section Number"));
  302. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  303. Q_ASSERT(toolBtn);
  304. toolBtn->setPopupMode(QToolButton::InstantPopup);
  305. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  306. auto menu = WidgetsFactory::createMenu(p_tb);
  307. auto actGroup = new QActionGroup(menu);
  308. auto act1 = actGroup->addAction(ViewWindow::tr("Follow Configuration"));
  309. act1->setCheckable(true);
  310. act1->setChecked(true);
  311. act1->setData(OverrideState::NoOverride);
  312. menu->addAction(act1);
  313. act1 = actGroup->addAction(ViewWindow::tr("Enabled"));
  314. act1->setCheckable(true);
  315. act1->setData(OverrideState::ForceEnable);
  316. menu->addAction(act1);
  317. act1 = actGroup->addAction(ViewWindow::tr("Disabled"));
  318. act1->setCheckable(true);
  319. act1->setData(OverrideState::ForceDisable);
  320. menu->addAction(act1);
  321. toolBtn->setMenu(menu);
  322. break;
  323. }
  324. case Action::InplacePreview:
  325. {
  326. act = p_tb->addAction(ToolBarHelper::generateIcon("inplace_preview_editor.svg"),
  327. ViewWindow::tr("Toggle In-Place Preview"));
  328. act->setCheckable(true);
  329. act->setChecked(true);
  330. break;
  331. }
  332. case Action::ImageHost:
  333. {
  334. act = p_tb->addAction(ToolBarHelper::generateIcon("image_host_editor.svg"),
  335. ViewWindow::tr("Image Host"));
  336. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  337. Q_ASSERT(toolBtn);
  338. toolBtn->setPopupMode(QToolButton::InstantPopup);
  339. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  340. auto menu = WidgetsFactory::createMenu(p_tb);
  341. toolBtn->setMenu(menu);
  342. break;
  343. }
  344. case Action::Debug:
  345. {
  346. act = p_tb->addAction(ToolBarHelper::generateIcon("debug_editor.svg"), ViewWindow::tr("Debug"));
  347. addActionShortcut(act, editorConfig.getShortcut(Shortcut::Debug), viewWindow);
  348. break;
  349. }
  350. case Action::Print:
  351. {
  352. act = p_tb->addAction(ToolBarHelper::generateIcon("print_editor.svg"), ViewWindow::tr("Print"));
  353. addActionShortcut(act, editorConfig.getShortcut(Shortcut::Print), viewWindow);
  354. break;
  355. }
  356. case Action::WordCount:
  357. {
  358. act = p_tb->addAction(ToolBarHelper::generateIcon("word_count_editor.svg"),
  359. ViewWindow::tr("Word Count"));
  360. auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
  361. Q_ASSERT(toolBtn);
  362. toolBtn->setPopupMode(QToolButton::InstantPopup);
  363. toolBtn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
  364. addButtonShortcut(toolBtn, editorConfig.getShortcut(Shortcut::WordCount), viewWindow);
  365. auto menu = new WordCountPopup(toolBtn, viewWindow, p_tb);
  366. toolBtn->setMenu(menu);
  367. break;
  368. }
  369. default:
  370. Q_ASSERT(false);
  371. break;
  372. }
  373. return act;
  374. }