00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <qwidget.h>
00026 #include <kaction.h>
00027 #include <kactioncollection.h>
00028 #include <klocale.h>
00029 #include <kpopupmenu.h>
00030 #include <kshortcut.h>
00031 #include <kxmlguifactory.h>
00032
00033 #include <qmap.h>
00034 #include <qstring.h>
00035 #include <qvaluelist.h>
00036
00037 #include "actionmanagerimpl.h"
00038 #include "akregatorconfig.h"
00039 #include "akregator_part.h"
00040 #include "akregator_view.h"
00041 #include "articlelistview.h"
00042 #include "articleviewer.h"
00043 #include "feed.h"
00044 #include "feedlistview.h"
00045 #include "fetchqueue.h"
00046 #include "folder.h"
00047 #include "listtabwidget.h"
00048 #include "kernel.h"
00049 #include "speechclient.h"
00050 #include "tag.h"
00051 #include "tagaction.h"
00052 #include "tagnode.h"
00053 #include "tagset.h"
00054 #include "trayicon.h"
00055 #include "treenode.h"
00056 #include "treenodevisitor.h"
00057 #include "tabwidget.h"
00058 #include "kstdaccel.h"
00059
00060
00061
00062 #include <kdebug.h>
00063
00064 namespace Akregator
00065 {
00066
00067 class ActionManagerImpl::NodeSelectVisitor : public TreeNodeVisitor
00068 {
00069 public:
00070 NodeSelectVisitor(ActionManagerImpl* manager) : m_manager(manager) {}
00071
00072 virtual bool visitFeed(Feed* node)
00073 {
00074 KAction* remove = m_manager->action("feed_remove");
00075 if (remove)
00076 remove->setEnabled(true);
00077 KAction* hp = m_manager->action("feed_homepage");
00078 if (hp)
00079 hp->setEnabled(!node->htmlUrl().isEmpty());
00080 m_manager->action("feed_fetch")->setText(i18n("&Fetch Feed"));
00081 m_manager->action("feed_remove")->setText(i18n("&Delete Feed"));
00082 m_manager->action("feed_modify")->setText(i18n("&Edit Feed..."));
00083 m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Feed as Read"));
00084
00085 return true;
00086 }
00087
00088 virtual bool visitFolder(Folder* node)
00089 {
00090 KAction* remove = m_manager->action("feed_remove");
00091 if (remove)
00092 remove->setEnabled(node->parent());
00093 KAction* hp = m_manager->action("feed_homepage");
00094 if (hp)
00095 hp->setEnabled(false);
00096
00097 m_manager->action("feed_fetch")->setText(i18n("&Fetch Feeds"));
00098 m_manager->action("feed_remove")->setText(i18n("&Delete Folder"));
00099 m_manager->action("feed_modify")->setText(i18n("&Rename Folder"));
00100 m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Feeds as Read"));
00101
00102 return true;
00103 }
00104
00105 virtual bool visitTagNode(TagNode* )
00106 {
00107 KAction* remove = m_manager->action("feed_remove");
00108 if (remove)
00109 remove->setEnabled(true);
00110 KAction* hp = m_manager->action("feed_homepage");
00111 if (hp)
00112 hp->setEnabled(false);
00113 m_manager->action("feed_mark_all_as_read")->setText(i18n("&Mark Articles as Read"));
00114 m_manager->action("feed_remove")->setText(i18n("&Delete Tag"));
00115 m_manager->action("feed_modify")->setText(i18n("&Edit Tag..."));
00116
00117 return true;
00118 }
00119 private:
00120 ActionManagerImpl* m_manager;
00121 };
00122
00123 class ActionManagerImpl::ActionManagerImplPrivate
00124 {
00125 public:
00126
00127 NodeSelectVisitor* nodeSelectVisitor;
00128 ArticleListView* articleList;
00129 ListTabWidget* listTabWidget;
00130 View* view;
00131 ArticleViewer* articleViewer;
00132 Part* part;
00133 TrayIcon* trayIcon;
00134 KActionMenu* tagMenu;
00135 KActionCollection* actionCollection;
00136 TagSet* tagSet;
00137 QMap<QString, TagAction*> tagActions;
00138 TabWidget* tabWidget;
00139 KAction* speakSelectedArticlesAction;
00140 };
00141
00142 void ActionManagerImpl::slotUpdateTagActions(bool enabled, const QStringList& tagIds)
00143 {
00144 if (Settings::showTaggingGUI() && d->tagMenu)
00145 {
00146 d->tagMenu->setEnabled(enabled);
00147 QValueList<TagAction*> actions = d->tagActions.values();
00148
00149 for (QValueList<TagAction*>::ConstIterator it = actions.begin(); it != actions.end(); ++it)
00150 {
00151 (*it)->setChecked(tagIds.contains((*it)->tag().id()));
00152 }
00153 }
00154 }
00155
00156 void ActionManagerImpl::setTagSet(TagSet* tagSet)
00157 {
00158 if (tagSet == d->tagSet)
00159 return;
00160
00161 if (d->tagSet != 0)
00162 {
00163 disconnect(d->tagSet, SIGNAL(signalTagAdded(const Tag&)), this, SLOT(slotTagAdded(const Tag&)));
00164 disconnect(d->tagSet, SIGNAL(signalTagRemoved(const Tag&)), this, SLOT(slotTagRemoved(const Tag&)));
00165 }
00166
00167 d->tagSet = tagSet;
00168
00169 if (tagSet != 0)
00170 {
00171 connect(d->tagSet, SIGNAL(signalTagAdded(const Tag&)), this, SLOT(slotTagAdded(const Tag&)));
00172 connect(d->tagSet, SIGNAL(signalTagRemoved(const Tag&)), this, SLOT(slotTagRemoved(const Tag&)));
00173 }
00174
00175 QValueList<TagAction*> actions = d->tagActions.values();
00176 for (QValueList<TagAction*>::ConstIterator it = actions.begin(); it != actions.end(); ++it)
00177 {
00178 d->tagMenu->remove(*it);
00179 delete *it;
00180 }
00181
00182
00183 d->tagActions.clear();
00184
00185
00186
00187 if (tagSet != 0L)
00188 {
00189 QValueList<Tag> list = tagSet->toMap().values();
00190 for (QValueList<Tag>::ConstIterator it = list.begin(); it != list.end(); ++it)
00191 slotTagAdded(*it);
00192 }
00193 }
00194
00195 void ActionManagerImpl::slotTagAdded(const Tag& tag)
00196 {
00197 if (!Settings::showTaggingGUI())
00198 return;
00199
00200 if (!d->tagActions.contains(tag.id()))
00201 {
00202 d->tagActions[tag.id()] = new TagAction(tag, d->view, SLOT(slotAssignTag(const Tag&, bool)), d->tagMenu);
00203 d->tagMenu->insert(d->tagActions[tag.id()]);
00204 }
00205 }
00206
00207 void ActionManagerImpl::slotTagRemoved(const Tag& tag)
00208 {
00209 if (!Settings::showTaggingGUI())
00210 return;
00211
00212 QString id = tag.id();
00213 TagAction* action = d->tagActions[id];
00214 d->tagMenu->remove(action);
00215 d->tagActions.remove(id);
00216 delete action;
00217 }
00218
00219 void ActionManagerImpl::slotNodeSelected(TreeNode* node)
00220 {
00221 if (node != 0)
00222 d->nodeSelectVisitor->visit(node);
00223 }
00224
00225 ActionManagerImpl::ActionManagerImpl(Part* part, QObject* parent, const char* name) : ActionManager(parent, name), d(new ActionManagerImplPrivate)
00226 {
00227 d->nodeSelectVisitor = new NodeSelectVisitor(this);
00228 d->part = part;
00229 d->tagSet = 0;
00230 d->listTabWidget = 0;
00231 d->articleList = 0;
00232 d->trayIcon = 0;
00233 d->articleViewer = 0;
00234 d->view = 0;
00235 d->tabWidget = 0;
00236 d->tagMenu = 0;
00237 d->speakSelectedArticlesAction = 0;
00238 d->actionCollection = part->actionCollection();
00239 initPart();
00240 }
00241
00242 ActionManagerImpl::~ActionManagerImpl()
00243 {
00244 delete d->nodeSelectVisitor;
00245 delete d;
00246 d = 0;
00247 }
00248
00249 void ActionManagerImpl::initTrayIcon(TrayIcon* trayIcon)
00250 {
00251 if (d->trayIcon)
00252 return;
00253 else d->trayIcon = trayIcon;
00254
00255 KPopupMenu* traypop = trayIcon->contextMenu();
00256
00257 if (actionCollection()->action("feed_fetch_all"))
00258 actionCollection()->action("feed_fetch_all")->plug(traypop, 1);
00259 if (actionCollection()->action("akregator_configure_akregator"))
00260 actionCollection()->action("akregator_configure_akregator")->plug(traypop, 2);
00261 }
00262
00263 void ActionManagerImpl::initPart()
00264 {
00265 new KAction(i18n("&Import Feeds..."), "", "", d->part, SLOT(fileImport()), d->actionCollection, "file_import");
00266 new KAction(i18n("&Export Feeds..."), "", "", d->part, SLOT(fileExport()), d->actionCollection, "file_export");
00267
00268
00269 new KAction(i18n("Send &Link Address..."), "mail_generic", "", d->part, SLOT(fileSendLink()), d->actionCollection, "file_sendlink");
00270 new KAction(i18n("Send &File..."), "mail_generic", "", d->part, SLOT(fileSendFile()), d->actionCollection, "file_sendfile");
00271
00272 KStdAction::configureNotifications(d->part, SLOT(showKNotifyOptions()), d->actionCollection);
00273 new KAction( i18n("Configure &Akregator..."), "configure", "", d->part, SLOT(showOptions()), d->actionCollection, "akregator_configure_akregator" );
00274 }
00275
00276 void ActionManagerImpl::initView(View* view)
00277 {
00278 if (d->view)
00279 return;
00280 else
00281 d->view = view;
00282
00283
00284 new KAction(i18n("&New Tag..."), "", "", d->view, SLOT(slotNewTag()), actionCollection(), "tag_new");
00285
00286
00287 new KAction(i18n("&Open Homepage"), "", "Ctrl+H", d->view, SLOT(slotOpenHomepage()), actionCollection(), "feed_homepage");
00288 new KAction(i18n("&Add Feed..."), "bookmark_add", "Insert", d->view, SLOT(slotFeedAdd()), actionCollection(), "feed_add");
00289 new KAction(i18n("Ne&w Folder..."), "folder_new", "Shift+Insert", d->view, SLOT(slotFeedAddGroup()), actionCollection(), "feed_add_group");
00290 new KAction(i18n("&Delete Feed"), "editdelete", "Alt+Delete", d->view, SLOT(slotFeedRemove()), actionCollection(), "feed_remove");
00291 new KAction(i18n("&Edit Feed..."), "edit", "F2", d->view, SLOT(slotFeedModify()), actionCollection(), "feed_modify");
00292 KActionMenu* vm = new KActionMenu( i18n( "&View Mode" ), actionCollection(), "view_mode" );
00293
00294 KRadioAction *ra = new KRadioAction(i18n("&Normal View"), "view_top_bottom", "Ctrl+Shift+1", d->view, SLOT(slotNormalView()), actionCollection(), "normal_view");
00295 ra->setExclusiveGroup( "ViewMode" );
00296 vm->insert(ra);
00297
00298 ra = new KRadioAction(i18n("&Widescreen View"), "view_left_right", "Ctrl+Shift+2", d->view, SLOT(slotWidescreenView()), actionCollection(), "widescreen_view");
00299 ra->setExclusiveGroup( "ViewMode" );
00300 vm->insert(ra);
00301
00302 ra = new KRadioAction(i18n("C&ombined View"), "view_text", "Ctrl+Shift+3", d->view, SLOT(slotCombinedView()), actionCollection(), "combined_view");
00303 ra->setExclusiveGroup( "ViewMode" );
00304 vm->insert(ra);
00305
00306
00307 new KAction(i18n("&Fetch Feed"), "down", KStdAccel::shortcut(KStdAccel::Reload), d->view, SLOT(slotFetchCurrentFeed()), actionCollection(), "feed_fetch");
00308 new KAction(i18n("Fe&tch All Feeds"), "bottom", "Ctrl+L", d->view, SLOT(slotFetchAllFeeds()), actionCollection(), "feed_fetch_all");
00309
00310 KAction* stopAction = new KAction(i18n( "&Abort Fetches" ), "stop", Key_Escape, Kernel::self()->fetchQueue(), SLOT(slotAbort()), actionCollection(), "feed_stop");
00311 stopAction->setEnabled(false);
00312
00313 new KAction(i18n("&Mark Feed as Read"), "goto", "Ctrl+R", d->view, SLOT(slotMarkAllRead()), actionCollection(), "feed_mark_all_as_read");
00314 new KAction(i18n("Ma&rk All Feeds as Read"), "goto", "Ctrl+Shift+R", d->view, SLOT(slotMarkAllFeedsRead()), actionCollection(), "feed_mark_all_feeds_as_read");
00315
00316
00317 KToggleAction* sqf = new KToggleAction(i18n("Show Quick Filter"), QString::null, 0, d->view, SLOT(slotToggleShowQuickFilter()), actionCollection(), "show_quick_filter");
00318 sqf->setChecked( Settings::showQuickFilter() );
00319
00320 new KAction( i18n("Open in Tab"), "tab_new", "Shift+Return", d->view, SLOT(slotOpenCurrentArticle()), actionCollection(), "article_open" );
00321 new KAction( i18n("Open in Background Tab"), QString::null, "tab_new", d->view, SLOT(slotOpenCurrentArticleBackgroundTab()), actionCollection(), "article_open_background_tab" );
00322 new KAction( i18n("Open in External Browser"), "window_new", "Ctrl+Shift+Return", d->view, SLOT(slotOpenCurrentArticleExternal()), actionCollection(), "article_open_external" );
00323 new KAction( i18n("Copy Link Address"), QString::null, QString::null, d->view, SLOT(slotCopyLinkAddress()), actionCollection(), "article_copy_link_address" );
00324
00325 new KAction(i18n("Pre&vious Unread Article"), "", Key_Minus, d->view, SLOT(slotPrevUnreadArticle()),actionCollection(), "go_prev_unread_article");
00326 new KAction(i18n("Ne&xt Unread Article"), "", Key_Plus, d->view, SLOT(slotNextUnreadArticle()),actionCollection(), "go_next_unread_article");
00327
00328 new KAction(i18n("&Delete"), "editdelete", "Delete", d->view, SLOT(slotArticleDelete()), actionCollection(), "article_delete");
00329
00330 if (Settings::showTaggingGUI())
00331 {
00332 d->tagMenu = new KActionMenu ( i18n( "&Set Tags" ), "rss_tag", actionCollection(), "article_tagmenu" );
00333 d->tagMenu->setEnabled(false);
00334 }
00335 KActionMenu* statusMenu = new KActionMenu ( i18n( "&Mark As" ),
00336 actionCollection(), "article_set_status" );
00337
00338 d->speakSelectedArticlesAction = new KAction(i18n("&Speak Selected Articles"), "kttsd", "", d->view, SLOT(slotTextToSpeechRequest()), actionCollection(), "akr_texttospeech");
00339
00340 KAction* abortTTS = new KAction(i18n( "&Stop Speaking" ), "player_stop", Key_Escape, SpeechClient::self(), SLOT(slotAbortJobs()), actionCollection(), "akr_aborttexttospeech");
00341 abortTTS->setEnabled(false);
00342
00343 connect(SpeechClient::self(), SIGNAL(signalActivated(bool)),
00344 abortTTS, SLOT(setEnabled(bool)));
00345
00346 statusMenu->insert(new KAction(KGuiItem(i18n("as in: mark as read","&Read"), "",
00347 i18n("Mark selected article as read")),
00348 "Ctrl+E", d->view, SLOT(slotSetSelectedArticleRead()),
00349 actionCollection(), "article_set_status_read"));
00350
00351 statusMenu->insert(new KAction(KGuiItem(i18n("&New"), "",
00352 i18n("Mark selected article as new")),
00353 "Ctrl+N", d->view, SLOT(slotSetSelectedArticleNew()),
00354 actionCollection(), "article_set_status_new" ));
00355
00356
00357 statusMenu->insert(new KAction(KGuiItem(i18n("&Unread"), "",
00358 i18n("Mark selected article as unread")),
00359 "Ctrl+U", d->view, SLOT(slotSetSelectedArticleUnread()),
00360 actionCollection(), "article_set_status_unread"));
00361
00362 KToggleAction* importantAction = new KToggleAction(i18n("&Mark as Important"), "flag", "Ctrl+I", actionCollection(), "article_set_status_important");
00363 importantAction->setCheckedState(i18n("Remove &Important Mark"));
00364 connect(importantAction, SIGNAL(toggled(bool)), d->view, SLOT(slotArticleToggleKeepFlag(bool)));
00365
00366
00367 new KAction( i18n("Move Node Up"), QString::null, "Shift+Alt+Up", view, SLOT(slotMoveCurrentNodeUp()), d->actionCollection, "feedstree_move_up" );
00368 new KAction( i18n("Move Node Down"), QString::null, "Shift+Alt+Down", view, SLOT(slotMoveCurrentNodeDown()), d->actionCollection, "feedstree_move_down" );
00369 new KAction( i18n("Move Node Left"), QString::null, "Shift+Alt+Left", view, SLOT(slotMoveCurrentNodeLeft()), d->actionCollection, "feedstree_move_left" );
00370 new KAction( i18n("Move Node Right"), QString::null, "Shift+Alt+Right", view, SLOT(slotMoveCurrentNodeRight()), d->actionCollection, "feedstree_move_right");
00371 }
00372
00373 void ActionManagerImpl::initArticleViewer(ArticleViewer* articleViewer)
00374 {
00375 if (d->articleViewer)
00376 return;
00377 else
00378 d->articleViewer = articleViewer;
00379 }
00380
00381 void ActionManagerImpl::initArticleListView(ArticleListView* articleList)
00382 {
00383 if (d->articleList)
00384 return;
00385 else
00386 d->articleList = articleList;
00387
00388 new KAction( i18n("&Previous Article"), QString::null, "Left", articleList, SLOT(slotPreviousArticle()), actionCollection(), "go_previous_article" );
00389 new KAction( i18n("&Next Article"), QString::null, "Right", articleList, SLOT(slotNextArticle()), actionCollection(), "go_next_article" );
00390 }
00391
00392 void ActionManagerImpl::initListTabWidget(ListTabWidget* listTabWidget)
00393 {
00394 if (d->listTabWidget)
00395 return;
00396 else
00397 d->listTabWidget = listTabWidget;
00398
00399 new KAction(i18n("&Previous Feed"), "", "P", listTabWidget, SLOT(slotPrevFeed()),actionCollection(), "go_prev_feed");
00400 new KAction(i18n("&Next Feed"), "", "N", listTabWidget, SLOT(slotNextFeed()),actionCollection(), "go_next_feed");
00401 new KAction(i18n("N&ext Unread Feed"), "", "Alt+Plus", listTabWidget, SLOT(slotNextUnreadFeed()),actionCollection(), "go_next_unread_feed");
00402 new KAction(i18n("Prev&ious Unread Feed"), "", "Alt+Minus", listTabWidget, SLOT(slotPrevUnreadFeed()),actionCollection(), "go_prev_unread_feed");
00403
00404 new KAction( i18n("Go to Top of Tree"), QString::null, "Ctrl+Home", listTabWidget, SLOT(slotItemBegin()), d->actionCollection, "feedstree_home" );
00405 new KAction( i18n("Go to Bottom of Tree"), QString::null, "Ctrl+End", listTabWidget, SLOT(slotItemEnd()), d->actionCollection, "feedstree_end" );
00406 new KAction( i18n("Go Left in Tree"), QString::null, "Ctrl+Left", listTabWidget, SLOT(slotItemLeft()), d->actionCollection, "feedstree_left" );
00407 new KAction( i18n("Go Right in Tree"), QString::null, "Ctrl+Right", listTabWidget, SLOT(slotItemRight()), d->actionCollection, "feedstree_right" );
00408 new KAction( i18n("Go Up in Tree"), QString::null, "Ctrl+Up", listTabWidget, SLOT(slotItemUp()), d->actionCollection, "feedstree_up" );
00409 new KAction( i18n("Go Down in Tree"), QString::null, "Ctrl+Down", listTabWidget, SLOT(slotItemDown()), d->actionCollection, "feedstree_down" );
00410 }
00411
00412 void ActionManagerImpl::initTabWidget(TabWidget* tabWidget)
00413 {
00414 if (d->tabWidget)
00415 return;
00416 else
00417 d->tabWidget = tabWidget;
00418
00419 new KAction(i18n("Select Next Tab"), "", "Ctrl+Period", d->tabWidget, SLOT(slotNextTab()),actionCollection(), "select_next_tab");
00420 new KAction(i18n("Select Previous Tab"), "", "Ctrl+Comma", d->tabWidget, SLOT(slotPreviousTab()),actionCollection(), "select_previous_tab");
00421 new KAction( i18n("Detach Tab"), "tab_breakoff", CTRL+SHIFT+Key_B, d->tabWidget, SLOT(slotDetachTab()), actionCollection(), "tab_detach" );
00422 new KAction( i18n("Copy Link Address"), QString::null, QString::null, d->tabWidget, SLOT(slotCopyLinkAddress()), actionCollection(), "tab_copylinkaddress" );
00423 new KAction( i18n("&Close Tab"), "tab_remove", KStdAccel::close(), d->tabWidget, SLOT(slotCloseTab()), actionCollection(), "tab_remove" );
00424 }
00425
00426 QWidget* ActionManagerImpl::container(const char* name)
00427 {
00428 return d->part->factory()->container(name, d->part);
00429 }
00430
00431
00432 KActionCollection* ActionManagerImpl::actionCollection()
00433 {
00434 return d->actionCollection;
00435 }
00436 KAction* ActionManagerImpl::action(const char* name, const char* classname)
00437 {
00438 return d->actionCollection != 0 ? d->actionCollection->action(name, classname) : 0;
00439 }
00440
00441 }
00442
00443 #include "actionmanagerimpl.moc"