akregator/src

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