TDE personal information management applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

actionmanagerimpl.cpp 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. This file is part of Akregator.
  3. Copyright (C) 2005 Frank Osterfeld <frank.osterfeld at kdemail.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. As a special exception, permission is given to link this program
  16. with any edition of Qt, and distribute the resulting executable,
  17. without including the source code for Qt in the source distribution.
  18. */
  19. #include <qwidget.h>
  20. #include <kaction.h>
  21. #include <kactioncollection.h>
  22. #include <klocale.h>
  23. #include <kpopupmenu.h>
  24. #include <kshortcut.h>
  25. #include <kxmlguifactory.h>
  26. #include <qmap.h>
  27. #include <qstring.h>
  28. #include <qvaluelist.h>
  29. #include "actionmanagerimpl.h"
  30. #include "akregatorconfig.h"
  31. #include "akregator_part.h"
  32. #include "akregator_view.h"
  33. #include "articlelistview.h"
  34. #include "articleviewer.h"
  35. #include "feed.h"
  36. #include "feedlistview.h"
  37. #include "fetchqueue.h"
  38. #include "folder.h"
  39. #include "listtabwidget.h"
  40. #include "kernel.h"
  41. #include "speechclient.h"
  42. #include "tag.h"
  43. #include "tagaction.h"
  44. #include "tagnode.h"
  45. #include "tagset.h"
  46. #include "trayicon.h"
  47. #include "treenode.h"
  48. #include "treenodevisitor.h"
  49. #include "tabwidget.h"
  50. #include "kstdaccel.h"
  51. #include <kdebug.h>
  52. namespace Akregator
  53. {
  54. class ActionManagerImpl::NodeSelectVisitor : public TreeNodeVisitor
  55. {
  56. public:
  57. NodeSelectVisitor(ActionManagerImpl* manager) : m_manager(manager) {}
  58. virtual bool visitFeed(Feed* node)
  59. {
  60. KAction* remove = m_manager->action("feed_remove");
  61. if (remove)
  62. remove->setEnabled(true);
  63. KAction* hp = m_manager->action("feed_homepage");
  64. if (hp)
  65. hp->setEnabled(!node->htmlUrl().isEmpty());
  66. m_manager->action("feed_fetch")->setText(i18n("&Fetch Feed"));
  67. m_manager->action("feed_remove")->setText(i18n("&Delete Feed"));
  68. m_manager->action("feed_modify")->setText(i18n("&Edit Feed..."));
  69. m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Feed as Read"));
  70. return true;
  71. }
  72. virtual bool visitFolder(Folder* node)
  73. {
  74. KAction* remove = m_manager->action("feed_remove");
  75. if (remove)
  76. remove->setEnabled(node->parent()); // root nodes must not be deleted
  77. KAction* hp = m_manager->action("feed_homepage");
  78. if (hp)
  79. hp->setEnabled(false);
  80. m_manager->action("feed_fetch")->setText(i18n("&Fetch Feeds"));
  81. m_manager->action("feed_remove")->setText(i18n("&Delete Folder"));
  82. m_manager->action("feed_modify")->setText(i18n("&Rename Folder"));
  83. m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Feeds as Read"));
  84. return true;
  85. }
  86. virtual bool visitTagNode(TagNode* /*node*/)
  87. {
  88. KAction* remove = m_manager->action("feed_remove");
  89. if (remove)
  90. remove->setEnabled(true);
  91. KAction* hp = m_manager->action("feed_homepage");
  92. if (hp)
  93. hp->setEnabled(false);
  94. m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Articles as Read"));
  95. m_manager->action("feed_remove")->setText(i18n("&Delete Tag"));
  96. m_manager->action("feed_modify")->setText(i18n("&Edit Tag..."));
  97. return true;
  98. }
  99. private:
  100. ActionManagerImpl* m_manager;
  101. };
  102. class ActionManagerImpl::ActionManagerImplPrivate
  103. {
  104. public:
  105. NodeSelectVisitor* nodeSelectVisitor;
  106. ArticleListView* articleList;
  107. ListTabWidget* listTabWidget;
  108. View* view;
  109. ArticleViewer* articleViewer;
  110. Part* part;
  111. TrayIcon* trayIcon;
  112. KActionMenu* tagMenu;
  113. KActionCollection* actionCollection;
  114. TagSet* tagSet;
  115. QMap<QString, TagAction*> tagActions;
  116. TabWidget* tabWidget;
  117. KAction* speakSelectedArticlesAction;
  118. };
  119. void ActionManagerImpl::slotUpdateTagActions(bool enabled, const QStringList& tagIds)
  120. {
  121. if (Settings::showTaggingGUI() && d->tagMenu)
  122. {
  123. d->tagMenu->setEnabled(enabled);
  124. QValueList<TagAction*> actions = d->tagActions.values();
  125. for (QValueList<TagAction*>::ConstIterator it = actions.begin(); it != actions.end(); ++it)
  126. {
  127. (*it)->setChecked(tagIds.contains((*it)->tag().id()));
  128. }
  129. }
  130. }
  131. void ActionManagerImpl::setTagSet(TagSet* tagSet)
  132. {
  133. if (tagSet == d->tagSet)
  134. return;
  135. if (d->tagSet != 0)
  136. {
  137. disconnect(d->tagSet, SIGNAL(signalTagAdded(const Tag&)), this, SLOT(slotTagAdded(const Tag&)));
  138. disconnect(d->tagSet, SIGNAL(signalTagRemoved(const Tag&)), this, SLOT(slotTagRemoved(const Tag&)));
  139. }
  140. d->tagSet = tagSet;
  141. if (tagSet != 0)
  142. {
  143. connect(d->tagSet, SIGNAL(signalTagAdded(const Tag&)), this, SLOT(slotTagAdded(const Tag&)));
  144. connect(d->tagSet, SIGNAL(signalTagRemoved(const Tag&)), this, SLOT(slotTagRemoved(const Tag&)));
  145. }
  146. QValueList<TagAction*> actions = d->tagActions.values();
  147. for (QValueList<TagAction*>::ConstIterator it = actions.begin(); it != actions.end(); ++it)
  148. {
  149. d->tagMenu->remove(*it);
  150. delete *it;
  151. }
  152. d->tagActions.clear();
  153. //TODO: remove actions from menus, delete actions, clear maps
  154. if (tagSet != 0L)
  155. {
  156. QValueList<Tag> list = tagSet->toMap().values();
  157. for (QValueList<Tag>::ConstIterator it = list.begin(); it != list.end(); ++it)
  158. slotTagAdded(*it);
  159. }
  160. }
  161. void ActionManagerImpl::slotTagAdded(const Tag& tag)
  162. {
  163. if (!Settings::showTaggingGUI())
  164. return;
  165. if (!d->tagActions.contains(tag.id()))
  166. {
  167. d->tagActions[tag.id()] = new TagAction(tag, d->view, SLOT(slotAssignTag(const Tag&, bool)), d->tagMenu);
  168. d->tagMenu->insert(d->tagActions[tag.id()]);
  169. }
  170. }
  171. void ActionManagerImpl::slotTagRemoved(const Tag& tag)
  172. {
  173. if (!Settings::showTaggingGUI())
  174. return;
  175. QString id = tag.id();
  176. TagAction* action = d->tagActions[id];
  177. d->tagMenu->remove(action);
  178. d->tagActions.remove(id);
  179. delete action;
  180. }
  181. void ActionManagerImpl::slotNodeSelected(TreeNode* node)
  182. {
  183. if (node != 0)
  184. d->nodeSelectVisitor->visit(node);
  185. }
  186. ActionManagerImpl::ActionManagerImpl(Part* part, QObject* parent, const char* name) : ActionManager(parent, name), d(new ActionManagerImplPrivate)
  187. {
  188. d->nodeSelectVisitor = new NodeSelectVisitor(this);
  189. d->part = part;
  190. d->tagSet = 0;
  191. d->listTabWidget = 0;
  192. d->articleList = 0;
  193. d->trayIcon = 0;
  194. d->articleViewer = 0;
  195. d->view = 0;
  196. d->tabWidget = 0;
  197. d->tagMenu = 0;
  198. d->speakSelectedArticlesAction = 0;
  199. d->actionCollection = part->actionCollection();
  200. initPart();
  201. }
  202. ActionManagerImpl::~ActionManagerImpl()
  203. {
  204. delete d->nodeSelectVisitor;
  205. delete d;
  206. d = 0;
  207. }
  208. void ActionManagerImpl::initTrayIcon(TrayIcon* trayIcon)
  209. {
  210. if (d->trayIcon)
  211. return;
  212. else d->trayIcon = trayIcon;
  213. KPopupMenu* traypop = trayIcon->contextMenu();
  214. if (actionCollection()->action("feed_fetch_all"))
  215. actionCollection()->action("feed_fetch_all")->plug(traypop, 1);
  216. if (actionCollection()->action("akregator_configure_akregator"))
  217. actionCollection()->action("akregator_configure_akregator")->plug(traypop, 2);
  218. }
  219. void ActionManagerImpl::initPart()
  220. {
  221. new KAction(i18n("&Import Feeds..."), "", "", d->part, SLOT(fileImport()), d->actionCollection, "file_import");
  222. new KAction(i18n("&Export Feeds..."), "", "", d->part, SLOT(fileExport()), d->actionCollection, "file_export");
  223. //new KAction(i18n("&Get Feeds From Web..."), "", "", d->part, SLOT(fileGetFeeds()), d->actionCollection, "file_getfromweb");
  224. new KAction(i18n("Send &Link Address..."), "mail_generic", "", d->part, SLOT(fileSendLink()), d->actionCollection, "file_sendlink");
  225. new KAction(i18n("Send &File..."), "mail_generic", "", d->part, SLOT(fileSendFile()), d->actionCollection, "file_sendfile");
  226. KStdAction::configureNotifications(d->part, SLOT(showKNotifyOptions()), d->actionCollection); // options_configure_notifications
  227. new KAction( i18n("Configure &Akregator..."), "configure", "", d->part, SLOT(showOptions()), d->actionCollection, "akregator_configure_akregator" );
  228. }
  229. void ActionManagerImpl::initView(View* view)
  230. {
  231. if (d->view)
  232. return;
  233. else
  234. d->view = view;
  235. // tag actions
  236. new KAction(i18n("&New Tag..."), "", "", d->view, SLOT(slotNewTag()), actionCollection(), "tag_new");
  237. // Feed/Feed Group popup menu
  238. new KAction(i18n("&Open Homepage"), "", "Ctrl+H", d->view, SLOT(slotOpenHomepage()), actionCollection(), "feed_homepage");
  239. new KAction(i18n("&Add Feed..."), "bookmark_add", "Insert", d->view, SLOT(slotFeedAdd()), actionCollection(), "feed_add");
  240. new KAction(i18n("Ne&w Folder..."), "folder_new", "Shift+Insert", d->view, SLOT(slotFeedAddGroup()), actionCollection(), "feed_add_group");
  241. new KAction(i18n("&Delete Feed"), "editdelete", "Alt+Delete", d->view, SLOT(slotFeedRemove()), actionCollection(), "feed_remove");
  242. new KAction(i18n("&Edit Feed..."), "edit", "F2", d->view, SLOT(slotFeedModify()), actionCollection(), "feed_modify");
  243. KActionMenu* vm = new KActionMenu( i18n( "&View Mode" ), actionCollection(), "view_mode" );
  244. KRadioAction *ra = new KRadioAction(i18n("&Normal View"), "view_top_bottom", "Ctrl+Shift+1", d->view, SLOT(slotNormalView()), actionCollection(), "normal_view");
  245. ra->setExclusiveGroup( "ViewMode" );
  246. vm->insert(ra);
  247. ra = new KRadioAction(i18n("&Widescreen View"), "view_left_right", "Ctrl+Shift+2", d->view, SLOT(slotWidescreenView()), actionCollection(), "widescreen_view");
  248. ra->setExclusiveGroup( "ViewMode" );
  249. vm->insert(ra);
  250. ra = new KRadioAction(i18n("C&ombined View"), "view_text", "Ctrl+Shift+3", d->view, SLOT(slotCombinedView()), actionCollection(), "combined_view");
  251. ra->setExclusiveGroup( "ViewMode" );
  252. vm->insert(ra);
  253. // toolbar / feed menu
  254. new KAction(i18n("&Fetch Feed"), "down", KStdAccel::shortcut(KStdAccel::Reload), d->view, SLOT(slotFetchCurrentFeed()), actionCollection(), "feed_fetch");
  255. new KAction(i18n("Fe&tch All Feeds"), "bottom", "Ctrl+L", d->view, SLOT(slotFetchAllFeeds()), actionCollection(), "feed_fetch_all");
  256. KAction* stopAction = new KAction(i18n( "&Abort Fetches" ), "stop", Key_Escape, Kernel::self()->fetchQueue(), SLOT(slotAbort()), actionCollection(), "feed_stop");
  257. stopAction->setEnabled(false);
  258. new KAction(i18n("&Mark Feed as Read"), "goto", "Ctrl+R", d->view, SLOT(slotMarkAllRead()), actionCollection(), "feed_mark_all_as_read");
  259. new KAction(i18n("Ma&rk All Feeds as Read"), "goto", "Ctrl+Shift+R", d->view, SLOT(slotMarkAllFeedsRead()), actionCollection(), "feed_mark_all_feeds_as_read");
  260. // Settings menu
  261. KToggleAction* sqf = new KToggleAction(i18n("Show Quick Filter"), QString::null, 0, d->view, SLOT(slotToggleShowQuickFilter()), actionCollection(), "show_quick_filter");
  262. sqf->setChecked( Settings::showQuickFilter() );
  263. new KAction( i18n("Open in Tab"), "tab_new", "Shift+Return", d->view, SLOT(slotOpenCurrentArticle()), actionCollection(), "article_open" );
  264. new KAction( i18n("Open in Background Tab"), QString::null, "tab_new", d->view, SLOT(slotOpenCurrentArticleBackgroundTab()), actionCollection(), "article_open_background_tab" );
  265. new KAction( i18n("Open in External Browser"), "window_new", "Ctrl+Shift+Return", d->view, SLOT(slotOpenCurrentArticleExternal()), actionCollection(), "article_open_external" );
  266. new KAction( i18n("Copy Link Address"), QString::null, QString::null, d->view, SLOT(slotCopyLinkAddress()), actionCollection(), "article_copy_link_address" );
  267. new KAction(i18n("Pre&vious Unread Article"), "", Key_Minus, d->view, SLOT(slotPrevUnreadArticle()),actionCollection(), "go_prev_unread_article");
  268. new KAction(i18n("Ne&xt Unread Article"), "", Key_Plus, d->view, SLOT(slotNextUnreadArticle()),actionCollection(), "go_next_unread_article");
  269. new KAction(i18n("&Delete"), "editdelete", "Delete", d->view, SLOT(slotArticleDelete()), actionCollection(), "article_delete");
  270. if (Settings::showTaggingGUI())
  271. {
  272. d->tagMenu = new KActionMenu ( i18n( "&Set Tags" ), "rss_tag", actionCollection(), "article_tagmenu" );
  273. d->tagMenu->setEnabled(false); // only enabled when articles are selected
  274. }
  275. KActionMenu* statusMenu = new KActionMenu ( i18n( "&Mark As" ),
  276. actionCollection(), "article_set_status" );
  277. d->speakSelectedArticlesAction = new KAction(i18n("&Speak Selected Articles"), "kttsd", "", d->view, SLOT(slotTextToSpeechRequest()), actionCollection(), "akr_texttospeech");
  278. KAction* abortTTS = new KAction(i18n( "&Stop Speaking" ), "player_stop", Key_Escape, SpeechClient::self(), SLOT(slotAbortJobs()), actionCollection(), "akr_aborttexttospeech");
  279. abortTTS->setEnabled(false);
  280. connect(SpeechClient::self(), SIGNAL(signalActivated(bool)),
  281. abortTTS, SLOT(setEnabled(bool)));
  282. statusMenu->insert(new KAction(KGuiItem(i18n("as in: mark as read","&Read"), "",
  283. i18n("Mark selected article as read")),
  284. "Ctrl+E", d->view, SLOT(slotSetSelectedArticleRead()),
  285. actionCollection(), "article_set_status_read"));
  286. statusMenu->insert(new KAction(KGuiItem(i18n("&New"), "",
  287. i18n("Mark selected article as new")),
  288. "Ctrl+N", d->view, SLOT(slotSetSelectedArticleNew()),
  289. actionCollection(), "article_set_status_new" ));
  290. statusMenu->insert(new KAction(KGuiItem(i18n("&Unread"), "",
  291. i18n("Mark selected article as unread")),
  292. "Ctrl+U", d->view, SLOT(slotSetSelectedArticleUnread()),
  293. actionCollection(), "article_set_status_unread"));
  294. KToggleAction* importantAction = new KToggleAction(i18n("&Mark as Important"), "flag", "Ctrl+I", actionCollection(), "article_set_status_important");
  295. importantAction->setCheckedState(i18n("Remove &Important Mark"));
  296. connect(importantAction, SIGNAL(toggled(bool)), d->view, SLOT(slotArticleToggleKeepFlag(bool)));
  297. new KAction( i18n("Move Node Up"), QString::null, "Shift+Alt+Up", view, SLOT(slotMoveCurrentNodeUp()), d->actionCollection, "feedstree_move_up" );
  298. new KAction( i18n("Move Node Down"), QString::null, "Shift+Alt+Down", view, SLOT(slotMoveCurrentNodeDown()), d->actionCollection, "feedstree_move_down" );
  299. new KAction( i18n("Move Node Left"), QString::null, "Shift+Alt+Left", view, SLOT(slotMoveCurrentNodeLeft()), d->actionCollection, "feedstree_move_left" );
  300. new KAction( i18n("Move Node Right"), QString::null, "Shift+Alt+Right", view, SLOT(slotMoveCurrentNodeRight()), d->actionCollection, "feedstree_move_right");
  301. }
  302. void ActionManagerImpl::initArticleViewer(ArticleViewer* articleViewer)
  303. {
  304. if (d->articleViewer)
  305. return;
  306. else
  307. d->articleViewer = articleViewer;
  308. }
  309. void ActionManagerImpl::initArticleListView(ArticleListView* articleList)
  310. {
  311. if (d->articleList)
  312. return;
  313. else
  314. d->articleList = articleList;
  315. new KAction( i18n("&Previous Article"), QString::null, "Left", articleList, SLOT(slotPreviousArticle()), actionCollection(), "go_previous_article" );
  316. new KAction( i18n("&Next Article"), QString::null, "Right", articleList, SLOT(slotNextArticle()), actionCollection(), "go_next_article" );
  317. }
  318. void ActionManagerImpl::initListTabWidget(ListTabWidget* listTabWidget)
  319. {
  320. if (d->listTabWidget)
  321. return;
  322. else
  323. d->listTabWidget = listTabWidget;
  324. new KAction(i18n("&Previous Feed"), "", "P", listTabWidget, SLOT(slotPrevFeed()),actionCollection(), "go_prev_feed");
  325. new KAction(i18n("&Next Feed"), "", "N", listTabWidget, SLOT(slotNextFeed()),actionCollection(), "go_next_feed");
  326. new KAction(i18n("N&ext Unread Feed"), "", "Alt+Plus", listTabWidget, SLOT(slotNextUnreadFeed()),actionCollection(), "go_next_unread_feed");
  327. new KAction(i18n("Prev&ious Unread Feed"), "", "Alt+Minus", listTabWidget, SLOT(slotPrevUnreadFeed()),actionCollection(), "go_prev_unread_feed");
  328. new KAction( i18n("Go to Top of Tree"), QString::null, "Ctrl+Home", listTabWidget, SLOT(slotItemBegin()), d->actionCollection, "feedstree_home" );
  329. new KAction( i18n("Go to Bottom of Tree"), QString::null, "Ctrl+End", listTabWidget, SLOT(slotItemEnd()), d->actionCollection, "feedstree_end" );
  330. new KAction( i18n("Go Left in Tree"), QString::null, "Ctrl+Left", listTabWidget, SLOT(slotItemLeft()), d->actionCollection, "feedstree_left" );
  331. new KAction( i18n("Go Right in Tree"), QString::null, "Ctrl+Right", listTabWidget, SLOT(slotItemRight()), d->actionCollection, "feedstree_right" );
  332. new KAction( i18n("Go Up in Tree"), QString::null, "Ctrl+Up", listTabWidget, SLOT(slotItemUp()), d->actionCollection, "feedstree_up" );
  333. new KAction( i18n("Go Down in Tree"), QString::null, "Ctrl+Down", listTabWidget, SLOT(slotItemDown()), d->actionCollection, "feedstree_down" );
  334. }
  335. void ActionManagerImpl::initTabWidget(TabWidget* tabWidget)
  336. {
  337. if (d->tabWidget)
  338. return;
  339. else
  340. d->tabWidget = tabWidget;
  341. new KAction(i18n("Select Next Tab"), "", "Ctrl+Period", d->tabWidget, SLOT(slotNextTab()),actionCollection(), "select_next_tab");
  342. new KAction(i18n("Select Previous Tab"), "", "Ctrl+Comma", d->tabWidget, SLOT(slotPreviousTab()),actionCollection(), "select_previous_tab");
  343. new KAction( i18n("Detach Tab"), "tab_breakoff", CTRL+SHIFT+Key_B, d->tabWidget, SLOT(slotDetachTab()), actionCollection(), "tab_detach" );
  344. new KAction( i18n("Copy Link Address"), QString::null, QString::null, d->tabWidget, SLOT(slotCopyLinkAddress()), actionCollection(), "tab_copylinkaddress" );
  345. new KAction( i18n("&Close Tab"), "tab_remove", KStdAccel::close(), d->tabWidget, SLOT(slotCloseTab()), actionCollection(), "tab_remove" );
  346. }
  347. QWidget* ActionManagerImpl::container(const char* name)
  348. {
  349. return d->part->factory()->container(name, d->part);
  350. }
  351. KActionCollection* ActionManagerImpl::actionCollection()
  352. {
  353. return d->actionCollection;
  354. }
  355. KAction* ActionManagerImpl::action(const char* name, const char* classname)
  356. {
  357. return d->actionCollection != 0 ? d->actionCollection->action(name, classname) : 0;
  358. }
  359. } // namespace Akregator
  360. #include "actionmanagerimpl.moc"