27 #include "actionmanagerimpl.h"
28 #include "akregator_part.h"
29 #include "akregator_run.h"
30 #include "akregator_view.h"
31 #include "listtabwidget.h"
32 #include "addfeeddialog.h"
33 #include "propertiesdialog.h"
35 #include "fetchqueue.h"
36 #include "feedlistview.h"
37 #include "articlelistview.h"
38 #include "articleviewer.h"
41 #include "tagfolder.h"
44 #include "akregatorconfig.h"
46 #include "pageviewer.h"
47 #include "searchbar.h"
48 #include "speechclient.h"
50 #include "tabwidget.h"
54 #include "tagnodelist.h"
55 #include "tagpropertiesdialog.h"
57 #include "progressmanager.h"
58 #include "treenodevisitor.h"
59 #include "notificationmanager.h"
61 #include <tdeaction.h>
62 #include <tdeapplication.h>
63 #include <kcharsets.h>
64 #include <kcombobox.h>
65 #include <tdeconfig.h>
68 #include <tdefiledialog.h>
69 #include <tdefileitem.h>
70 #include <tdehtml_part.h>
71 #include <tdehtmlview.h>
72 #include <kiconloader.h>
73 #include <kinputdialog.h>
74 #include <klineedit.h>
75 #include <tdelistview.h>
76 #include <tdelocale.h>
77 #include <tdemessagebox.h>
79 #include <tdeprocess.h>
82 #include <kstandarddirs.h>
84 #include <kxmlguifactory.h>
85 #include <tdeparts/partmanager.h>
87 #include <tqbuttongroup.h>
88 #include <tqcheckbox.h>
89 #include <tqdatetime.h>
94 #include <tqmultilineedit.h>
95 #include <tqpopupmenu.h>
96 #include <tqptrlist.h>
97 #include <tqstylesheet.h>
98 #include <tqtextstream.h>
100 #include <tqtoolbutton.h>
101 #include <tqtooltip.h>
102 #include <tqvaluevector.h>
103 #include <tqwhatsthis.h>
104 #include <tqclipboard.h>
106 namespace Akregator {
108 class View::EditNodePropertiesVisitor :
public TreeNodeVisitor
111 EditNodePropertiesVisitor(
View* view) : m_view(view) {}
112 virtual ~EditNodePropertiesVisitor() {}
114 virtual bool visitTagNode(TagNode* node)
116 TagPropertiesDialog* dlg =
new TagPropertiesDialog(m_view);
117 dlg->setTag(node->tag());
123 virtual bool visitFolder(Folder* node)
125 m_view->m_listTabWidget->activeView()->startNodeRenaming(node);
129 virtual bool visitFeed(Feed* node)
131 FeedPropertiesDialog *dlg =
new FeedPropertiesDialog( m_view,
"edit_feed" );
142 class View::DeleteNodeVisitor :
public TreeNodeVisitor
145 DeleteNodeVisitor(
View* view) : m_view(view) {}
146 virtual ~DeleteNodeVisitor() {}
148 virtual bool visitTagNode(TagNode* node)
150 TQString msg = i18n(
"<qt>Are you sure you want to delete tag <b>%1</b>? The tag will be removed from all articles.</qt>").arg(node->title());
151 if (KMessageBox::warningContinueCancel(0, msg, i18n(
"Delete Tag"), KStdGuiItem::del()) == KMessageBox::Continue)
153 Tag tag = node->tag();
154 TQValueList<Article> articles = m_view->m_feedList->rootNode()->articles(tag.id());
155 node->setNotificationMode(
false);
156 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
157 (*it).removeTag(tag.id());
158 node->setNotificationMode(
true);
159 Kernel::self()->tagSet()->remove(tag);
160 m_view->m_listTabWidget->activeView()->setFocus();
165 virtual bool visitFolder(Folder* node)
168 if (node->title().isEmpty())
169 msg = i18n(
"<qt>Are you sure you want to delete this folder and its feeds and subfolders?</qt>");
171 msg = i18n(
"<qt>Are you sure you want to delete folder <b>%1</b> and its feeds and subfolders?</qt>").arg(node->title());
173 if (KMessageBox::warningContinueCancel(0, msg, i18n(
"Delete Folder"), KStdGuiItem::del()) == KMessageBox::Continue)
176 m_view->m_listTabWidget->activeView()->setFocus();
181 virtual bool visitFeed(Feed* node)
184 if (node->title().isEmpty())
185 msg = i18n(
"<qt>Are you sure you want to delete this feed?</qt>");
187 msg = i18n(
"<qt>Are you sure you want to delete feed <b>%1</b>?</qt>").arg(node->title());
189 if (KMessageBox::warningContinueCancel(0, msg, i18n(
"Delete Feed"), KStdGuiItem::del()) == KMessageBox::Continue)
192 m_view->m_listTabWidget->activeView()->setFocus();
209 kdDebug() <<
"View::~View(): slotOnShutdown() wasn't called. Calling it now." << endl;
212 kdDebug() <<
"View::~View(): leaving" << endl;
216 : TQWidget(parent, name), m_viewMode(NormalView), m_actionManager(actionManager)
218 m_editNodePropertiesVisitor =
new EditNodePropertiesVisitor(
this);
219 m_deleteNodeVisitor =
new DeleteNodeVisitor(
this);
220 m_keepFlagIcon = TQPixmap(locate(
"data",
"akregator/pics/akregator_flag.png"));
223 m_tagNodeList =
new TagNodeList(m_feedList, Kernel::self()->tagSet());
224 m_shuttingDown =
false;
225 m_displayingAboutPage =
false;
227 setFocusPolicy(TQWidget::StrongFocus);
229 TQVBoxLayout *lt =
new TQVBoxLayout(
this );
231 m_horizontalSplitter =
new TQSplitter(TQt::Horizontal,
this);
233 m_horizontalSplitter->setOpaqueResize(
true);
234 lt->addWidget(m_horizontalSplitter);
237 connect (Kernel::self()->fetchQueue(), TQ_SIGNAL(signalStarted()),
this, TQ_SLOT(slotFetchingStarted()));
238 connect (Kernel::self()->fetchQueue(), TQ_SIGNAL(signalStopped()),
this, TQ_SLOT(slotFetchingStopped()));
240 connect(Kernel::self()->tagSet(), TQ_SIGNAL(signalTagAdded(
const Tag&)),
this, TQ_SLOT(slotTagCreated(
const Tag&)));
241 connect(Kernel::self()->tagSet(), TQ_SIGNAL(signalTagRemoved(
const Tag&)),
this, TQ_SLOT(slotTagRemoved(
const Tag&)));
244 m_actionManager->initListTabWidget(m_listTabWidget);
248 if (!Settings::showTaggingGUI())
249 m_listTabWidget->setViewMode(ListTabWidget::single);
251 m_feedListView =
new NodeListView(
this,
"feedtree" );
252 m_listTabWidget->addView(m_feedListView, i18n(
"Feeds"), TDEGlobal::iconLoader()->loadIcon(
"folder", TDEIcon::Small));
256 connect(m_feedListView, TQ_SIGNAL(signalDropped (KURL::List &,
TreeNode*,
260 m_tagNodeListView =
new NodeListView(
this);
261 m_listTabWidget->addView(m_tagNodeListView, i18n(
"Tags"), TDEGlobal::iconLoader()->loadIcon(
"rss_tag", TDEIcon::Small));
266 ProgressManager::self()->setFeedList(m_feedList);
268 m_tabs =
new TabWidget(m_horizontalSplitter);
269 m_actionManager->initTabWidget(m_tabs);
271 connect( m_part, TQ_SIGNAL(signalSettingsChanged()), m_tabs, TQ_SLOT(slotSettingsChanged()));
273 connect( m_tabs, TQ_SIGNAL( currentFrameChanged(Frame *) ),
this,
276 TQWhatsThis::add(m_tabs, i18n(
"You can view multiple articles in several open tabs."));
278 m_mainTab =
new TQWidget(
this,
"Article Tab");
279 TQVBoxLayout *mainTabLayout =
new TQVBoxLayout( m_mainTab, 0, 2,
"mainTabLayout");
281 TQWhatsThis::add(m_mainTab, i18n(
"Articles list."));
283 m_searchBar =
new SearchBar(m_mainTab);
285 if ( !Settings::showQuickFilter() )
288 mainTabLayout->addWidget(m_searchBar);
290 m_articleSplitter =
new TQSplitter(TQt::Vertical, m_mainTab,
"panner2");
292 m_articleList =
new ArticleListView( m_articleSplitter,
"articles" );
293 m_actionManager->initArticleListView(m_articleList);
295 connect( m_articleList, TQ_SIGNAL(signalMouseButtonPressed(
int,
const Article&,
const TQPoint &,
int)),
this, TQ_SLOT(
slotMouseButtonPressed(
int,
const Article&,
const TQPoint &,
int)));
298 connect( m_articleList, TQ_SIGNAL(signalArticleChosen(
const Article&)),
300 connect( m_articleList, TQ_SIGNAL(signalDoubleClicked(
const Article&,
const TQPoint&,
int)),
303 m_articleViewer =
new ArticleViewer(m_articleSplitter,
"article_viewer");
304 m_articleViewer->setSafeMode();
306 m_actionManager->initArticleViewer(m_articleViewer);
312 connect( m_articleViewer, TQ_SIGNAL(urlClicked(
const KURL&, Viewer*,
bool,
bool)),
315 connect( m_articleViewer->browserExtension(), TQ_SIGNAL(mouseOverInfo(
const KFileItem *)),
318 connect( m_part, TQ_SIGNAL(signalSettingsChanged()), m_articleViewer, TQ_SLOT(slotPaletteOrFontChanged()));
319 TQWhatsThis::add(m_articleViewer->widget(), i18n(
"Browsing area."));
320 mainTabLayout->addWidget( m_articleSplitter );
322 m_mainFrame=
new Frame(
this, m_part, m_mainTab, i18n(
"Articles"),
false);
323 connectFrame(m_mainFrame);
324 m_tabs->addFrame(m_mainFrame);
326 const TQValueList<int> sp1sizes = Settings::splitter1Sizes();
327 if ( sp1sizes.count() >= m_horizontalSplitter->sizes().count() )
328 m_horizontalSplitter->setSizes( sp1sizes );
329 const TQValueList<int> sp2sizes = Settings::splitter2Sizes();
330 if ( sp2sizes.count() >= m_articleSplitter->sizes().count() )
331 m_articleSplitter->setSizes( sp2sizes );
333 TDEConfig *conf = Settings::self()->config();
334 conf->setGroup(
"General");
335 if(!conf->readBoolEntry(
"Disable Introduction",
false))
337 m_articleList->hide();
339 m_articleViewer->displayAboutPage();
340 m_mainFrame->setTitle(i18n(
"About"));
341 m_displayingAboutPage =
true;
344 m_fetchTimer =
new TQTimer(
this);
345 connect( m_fetchTimer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotDoIntervalFetches()) );
346 m_fetchTimer->start(1000*60);
349 m_expiryTimer =
new TQTimer(
this);
350 connect(m_expiryTimer, TQ_SIGNAL(timeout()),
this,
351 TQ_SLOT(slotDeleteExpiredArticles()) );
352 m_expiryTimer->start(3600*1000);
354 m_markReadTimer =
new TQTimer(
this);
357 switch (Settings::viewMode())
369 if (!Settings::resetQuickFilterOnNodeChange())
371 m_searchBar->slotSetStatus(Settings::statusFilter());
372 m_searchBar->slotSetText(Settings::textFilter());
375 TQTimer::singleShot(1000,
this, TQ_SLOT(slotDeleteExpiredArticles()) );
379 void View::slotSettingsChanged()
382 m_listTabWidget->setViewMode(Settings::showTaggingGUI() ? ListTabWidget::verticalTabs : ListTabWidget::single);
385 if (m_articleList->isShown()) {
386 m_articleList->repaintContents();
388 if (m_feedListView->isShown()) {
389 m_feedListView->repaintContents();
393 void View::slotOnShutdown()
395 m_shuttingDown =
true;
397 m_articleList->slotShowNode(0);
400 Kernel::self()->fetchQueue()->slotAbort();
402 m_feedListView->setNodeList(0);
403 ProgressManager::self()->setFeedList(0);
406 delete m_tagNodeList;
410 m_tabs->setCurrentPage(m_tabs->count()-1);
411 while (m_tabs->count() > 1)
412 m_tabs->slotRemoveCurrentFrame();
416 delete m_editNodePropertiesVisitor;
417 delete m_deleteNodeVisitor;
422 const TQValueList<int> spl1 = m_horizontalSplitter->sizes();
423 if ( spl1.contains( 0 ) == 0 )
424 Settings::setSplitter1Sizes( spl1 );
425 const TQValueList<int> spl2 = m_articleSplitter->sizes();
426 if ( spl2.contains( 0 ) == 0 )
427 Settings::setSplitter2Sizes( spl2 );
428 Settings::setViewMode( m_viewMode );
429 Settings::writeConfig();
434 PageViewer* page =
new PageViewer(
this,
"page");
436 connect( m_part, TQ_SIGNAL(signalSettingsChanged()), page, TQ_SLOT(slotPaletteOrFontChanged()));
438 connect( page, TQ_SIGNAL(setTabIcon(
const TQPixmap&)),
439 this, TQ_SLOT(setTabIcon(
const TQPixmap&)));
440 connect( page, TQ_SIGNAL(urlClicked(
const KURL &, Viewer*,
bool,
bool)),
443 Frame* frame =
new Frame(
this, page, page->widget(), i18n(
"Untitled"));
444 frame->setAutoDeletePart(
true);
446 connect(page, TQ_SIGNAL(setWindowCaption (
const TQString &)), frame, TQ_SLOT(setTitle (
const TQString &)));
448 m_tabs->addFrame(frame);
451 m_tabs->showPage(page->widget());
459 void View::setTabIcon(
const TQPixmap& icon)
461 const PageViewer *s =
dynamic_cast<const PageViewer*
>(sender());
463 m_tabs->setTabIconSet(
const_cast<PageViewer*
>(s)->widget(), icon);
467 void View::connectFrame(Frame *f)
469 connect(f, TQ_SIGNAL(statusText(
const TQString &)),
this, TQ_SLOT(
slotStatusText(
const TQString&)));
470 connect(f, TQ_SIGNAL(captionChanged (
const TQString &)),
this, TQ_SLOT(
slotCaptionChanged (
const TQString &)));
471 connect(f, TQ_SIGNAL(loadingProgress(
int)),
this, TQ_SLOT(slotLoadingProgress(
int)) );
472 connect(f, TQ_SIGNAL(started()),
this, TQ_SLOT(slotStarted()));
473 connect(f, TQ_SIGNAL(completed()),
this, TQ_SLOT(slotCompleted()));
474 connect(f, TQ_SIGNAL(canceled(
const TQString &)),
this, TQ_SLOT(slotCanceled(
const TQString&)));
479 if (sender() == m_currentFrame)
480 emit setStatusBarText(c);
485 if (sender() == m_currentFrame)
486 emit setWindowCaption(c);
489 void View::slotStarted()
491 if (sender() == m_currentFrame)
492 emit signalStarted(0);
495 void View::slotCanceled(
const TQString &s)
497 if (sender() == m_currentFrame)
498 emit signalCanceled(s);
501 void View::slotCompleted()
503 if (sender() == m_currentFrame)
504 emit signalCompleted();
507 void View::slotLoadingProgress(
int percent)
509 if (sender() == m_currentFrame)
510 emit setProgress(percent);
524 TQString title = feedList->title();
527 title = i18n(
"Imported Folder");
530 title = KInputDialog::getText(i18n(
"Add Imported Folder"), i18n(
"Imported folder name:"), title, &ok);
539 m_feedList->rootNode()->appendChild(fg);
540 m_feedList->
append(feedList, fg);
556 m_feedListView->setUpdatesEnabled(
false);
557 m_tagNodeListView->setUpdatesEnabled(
false);
560 TagSet* tagSet = Kernel::self()->tagSet();
562 Kernel::self()->setFeedList(feedList);
563 ProgressManager::self()->setFeedList(feedList);
564 disconnectFromFeedList(m_feedList);
566 delete m_tagNodeList;
567 m_feedList = feedList;
568 connectToFeedList(m_feedList);
570 m_tagNodeList =
new TagNodeList(m_feedList, tagSet);
571 m_feedListView->setNodeList(m_feedList);
572 m_tagNodeListView->setNodeList(m_tagNodeList);
574 TQStringList tagIDs = m_feedList->rootNode()->tags();
575 TQStringList::ConstIterator end = tagIDs.end();
576 for (TQStringList::ConstIterator it = tagIDs.begin(); it != end; ++it)
578 kdDebug() << *it << endl;
590 m_feedList->
append(feedList, parent);
592 m_feedListView->setUpdatesEnabled(
true);
593 m_feedListView->triggerUpdate();
594 m_tagNodeListView->setUpdatesEnabled(
true);
595 m_tagNodeListView->triggerUpdate();
599 void View::slotDeleteExpiredArticles()
601 TreeNode* rootNode = m_feedList->rootNode();
608 return m_feedList->
toXML();
615 TreeNode* node = m_feedListView->findNodeByTitle(groupName);
621 m_feedList->rootNode()->appendChild(g);
625 group =
static_cast<Folder*
>(node);
629 addFeed(url, 0, group,
true);
634 if (m_viewMode == NormalView)
637 if (m_viewMode == CombinedView)
639 m_articleList->slotShowNode(m_listTabWidget->activeView()->selectedNode());
640 m_articleList->show();
642 Article article = m_articleList->currentArticle();
644 if (!article.isNull())
647 m_articleViewer->slotShowSummary(m_listTabWidget->activeView()->selectedNode());
650 m_articleSplitter->setOrientation(TQt::Vertical);
651 m_viewMode = NormalView;
653 Settings::setViewMode( m_viewMode );
658 if (m_viewMode == WidescreenView)
661 if (m_viewMode == CombinedView)
663 m_articleList->slotShowNode(m_listTabWidget->activeView()->selectedNode());
664 m_articleList->show();
666 Article article = m_articleList->currentArticle();
668 if (!article.isNull())
671 m_articleViewer->slotShowSummary(m_listTabWidget->activeView()->selectedNode());
674 m_articleSplitter->setOrientation(TQt::Horizontal);
675 m_viewMode = WidescreenView;
677 Settings::setViewMode( m_viewMode );
682 if (m_viewMode == CombinedView)
685 m_articleList->slotClear();
686 m_articleList->hide();
687 m_viewMode = CombinedView;
690 Settings::setViewMode( m_viewMode );
700 emit setWindowCaption(f->caption());
701 emit setProgress(f->progress());
702 emit setStatusBarText(f->statusText());
704 if (f->part() == m_part)
709 f->widget()->setFocus();
714 emit signalStarted(0);
716 case Frame::Canceled:
717 emit signalCanceled(TQString());
720 case Frame::Completed:
722 emit signalCompleted();
728 m_tabs->showPage(m_mainTab);
731 void View::slotMoveCurrentNodeUp()
733 TreeNode* current = m_listTabWidget->activeView()->selectedNode();
739 if (!prev || !parent)
744 m_listTabWidget->activeView()->ensureNodeVisible(current);
747 void View::slotMoveCurrentNodeDown()
749 TreeNode* current = m_listTabWidget->activeView()->selectedNode();
752 TreeNode* next = current->nextSibling();
753 Folder* parent = current->
parent();
755 if (!next || !parent)
759 parent->insertChild(current, next);
760 m_listTabWidget->activeView()->ensureNodeVisible(current);
763 void View::slotMoveCurrentNodeLeft()
765 TreeNode* current = m_listTabWidget->activeView()->selectedNode();
766 if (!current || !current->parent() || !current->parent()->parent())
769 Folder* parent = current->parent();
770 Folder* grandparent = current->parent()->parent();
772 parent->removeChild(current);
773 grandparent->insertChild(current, parent);
774 m_listTabWidget->activeView()->ensureNodeVisible(current);
777 void View::slotMoveCurrentNodeRight()
779 TreeNode* current = m_listTabWidget->activeView()->selectedNode();
780 if (!current || !current->parent())
784 if ( prev && prev->isGroup() )
786 Folder* fg =
static_cast<Folder*
>(prev);
788 fg->appendChild(current);
789 m_listTabWidget->activeView()->ensureNodeVisible(current);
795 m_markReadTimer->stop();
799 kdDebug() <<
"node selected: " << node->
title() << endl;
800 kdDebug() <<
"unread: " << node->
unread() << endl;
801 kdDebug() <<
"total: " << node->
totalCount() << endl;
804 if (m_displayingAboutPage)
806 m_mainFrame->setTitle(i18n(
"Articles"));
807 if (m_viewMode != CombinedView)
808 m_articleList->show();
809 if (Settings::showQuickFilter())
811 m_displayingAboutPage =
false;
814 m_tabs->showPage(m_mainTab);
816 if (Settings::resetQuickFilterOnNodeChange())
817 m_searchBar->slotClearSearch();
819 if (m_viewMode == CombinedView)
823 m_articleList->slotShowNode(node);
824 m_articleViewer->slotShowSummary(node);
828 m_mainFrame->setCaption(node->
title());
830 m_actionManager->slotNodeSelected(node);
835 void View::slotOpenURL(
const KURL& url, Viewer* currentViewer, BrowserRun::OpeningMode mode)
837 if (mode == BrowserRun::EXTERNAL)
838 Viewer::displayInExternalBrowser(url);
841 KParts::URLArgs args = currentViewer ? currentViewer->browserExtension()->urlArgs() : KParts::URLArgs();
843 BrowserRun* r =
new BrowserRun(
this, currentViewer, url, args, mode);
844 connect(r, TQ_SIGNAL(signalOpenInViewer(
const KURL&, Akregator::Viewer*, Akregator::BrowserRun::OpeningMode)),
845 this, TQ_SLOT(
slotOpenURLReply(
const KURL&, Akregator::Viewer*, Akregator::BrowserRun::OpeningMode)));
855 slotOpenURL(url, viewer, BrowserRun::CURRENT_TAB);
859 slotOpenURL(url, 0L, background ? BrowserRun::NEW_TAB_BACKGROUND : BrowserRun::NEW_TAB_FOREGROUND);
868 case BrowserRun::CURRENT_TAB:
869 currentViewer->openURL(url);
871 case BrowserRun::NEW_TAB_FOREGROUND:
872 case BrowserRun::NEW_TAB_BACKGROUND:
875 case BrowserRun::EXTERNAL:
876 Viewer::displayInExternalBrowser(url);
884 if (!m_feedListView->selectedNode())
885 group = m_feedList->rootNode();
889 if ( m_feedListView->selectedNode()->isGroup())
890 group =
static_cast<Folder*
>(m_feedListView->selectedNode());
892 group= m_feedListView->selectedNode()->parent();
898 addFeed(TQString(), lastChild, group,
false);
901 void View::addFeed(
const TQString& url,
TreeNode *after,
Folder* parent,
bool autoExec)
904 AddFeedDialog *afd =
new AddFeedDialog( 0,
"add_feed" );
906 afd->setURL(KURL::decode_string(url));
912 if (afd->exec() != TQDialog::Accepted)
919 Feed* feed = afd->feed;
922 FeedPropertiesDialog *dlg =
new FeedPropertiesDialog( 0,
"edit_feed" );
925 dlg->selectFeedName();
928 if (dlg->exec() != TQDialog::Accepted)
936 parent = m_feedList->rootNode();
940 m_feedListView->ensureNodeVisible(feed);
948 TreeNode* node = m_feedListView->selectedNode();
952 node = m_feedListView->rootNode();
966 TQString text = KInputDialog::getText(i18n(
"Add Folder"), i18n(
"Folder name:"),
"", &Ok);
976 m_feedListView->ensureNodeVisible(newGroup);
982 TreeNode* selectedNode = m_listTabWidget->activeView()->selectedNode();
985 if (!selectedNode || selectedNode == m_feedList->rootNode())
988 m_deleteNodeVisitor->visit(selectedNode);
993 TreeNode* node = m_listTabWidget->activeView()->selectedNode();
995 m_editNodePropertiesVisitor->visit(node);
1001 if (m_viewMode == CombinedView)
1002 m_listTabWidget->activeView()->slotNextUnreadFeed();
1004 TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
1005 if (sel && sel->
unread() > 0)
1006 m_articleList->slotNextUnreadArticle();
1008 m_listTabWidget->activeView()->slotNextUnreadFeed();
1013 if (m_viewMode == CombinedView)
1014 m_listTabWidget->activeView()->slotPrevUnreadFeed();
1016 TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
1017 if (sel && sel->
unread() > 0)
1018 m_articleList->slotPreviousUnreadArticle();
1020 m_listTabWidget->activeView()->slotPrevUnreadFeed();
1025 m_feedList->rootNode()->slotMarkAllArticlesAsRead();
1030 if(!m_listTabWidget->activeView()->selectedNode())
return;
1031 m_listTabWidget->activeView()->selectedNode()->slotMarkAllArticlesAsRead();
1036 Feed* feed =
dynamic_cast<Feed *
>(m_listTabWidget->activeView()->selectedNode());
1041 KURL url = KURL(feed->
htmlUrl())
1043 switch (Settings::lMBBehaviour())
1045 case Settings::EnumLMBBehaviour::OpenInExternalBrowser:
1046 slotOpenURL(url, 0, BrowserRun::EXTERNAL);
1048 case Settings::EnumLMBBehaviour::OpenInBackground:
1049 slotOpenURL(url, 0, BrowserRun::NEW_TAB_BACKGROUND);
1052 slotOpenURL(url, 0, BrowserRun::NEW_TAB_FOREGROUND);
1061 void View::slotDoIntervalFetches()
1063 m_feedList->rootNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue(),
true);
1068 if ( !m_listTabWidget->activeView()->selectedNode() )
1070 m_listTabWidget->activeView()->selectedNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue());
1075 m_feedList->rootNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue());
1078 void View::slotFetchingStarted()
1080 m_mainFrame->setState(Frame::Started);
1081 m_actionManager->action(
"feed_stop")->setEnabled(
true);
1082 m_mainFrame->setStatusText(i18n(
"Fetching Feeds..."));
1085 void View::slotFetchingStopped()
1087 m_mainFrame->setState(Frame::Completed);
1088 m_actionManager->action(
"feed_stop")->setEnabled(
false);
1089 m_mainFrame->setStatusText(TQString());
1097 TQValueList<Article> articles = feed->
articles();
1098 TQValueList<Article>::ConstIterator it;
1099 TQValueList<Article>::ConstIterator end = articles.end();
1100 for (it = articles.begin(); it != end; ++it)
1102 if ((*it).status()==Article::New && ((*it).feed()->useNotification() || Settings::useNotifications()))
1112 if (button == TQt::MidButton)
1114 KURL link = article.link();
1115 switch (Settings::mMBBehaviour())
1117 case Settings::EnumMMBBehaviour::OpenInExternalBrowser:
1118 slotOpenURL(link, 0L, BrowserRun::EXTERNAL);
1120 case Settings::EnumMMBBehaviour::OpenInBackground:
1121 slotOpenURL(link, 0L, BrowserRun::NEW_TAB_BACKGROUND);
1124 slotOpenURL(link, 0L, BrowserRun::NEW_TAB_FOREGROUND);
1129 void View::slotAssignTag(
const Tag& tag,
bool assign)
1131 kdDebug() << (assign ?
"assigned" :
"removed") <<
" tag \"" << tag.id() <<
"\"" << endl;
1132 TQValueList<Article> selectedArticles = m_articleList->selectedArticles();
1133 for (TQValueList<Article>::Iterator it = selectedArticles.begin(); it != selectedArticles.end(); ++it)
1136 (*it).addTag(tag.id());
1138 (*it).removeTag(tag.id());
1153 void View::slotNewTag()
1155 Tag tag(TDEApplication::randomString(8),
"New Tag");
1156 Kernel::self()->tagSet()->insert(tag);
1157 TagNode* node = m_tagNodeList->findByTagID(tag.id());
1159 m_tagNodeListView->startNodeRenaming(node);
1162 void View::slotTagCreated(
const Tag& tag)
1164 if (m_tagNodeList && !m_tagNodeList->containsTagId(tag.id()))
1166 TagNode* tagNode =
new TagNode(tag, m_feedList->rootNode());
1167 m_tagNodeList->rootNode()->appendChild(tagNode);
1171 void View::slotTagRemoved(
const Tag& )
1177 if (m_viewMode == CombinedView)
1180 m_markReadTimer->stop();
1182 Feed *feed = article.feed();
1187 if (a.status() != Article::Read)
1191 if ( Settings::useMarkReadDelay() )
1193 delay = Settings::markReadDelay();
1196 m_markReadTimer->start( delay*1000,
true );
1198 a.setStatus(Article::Read);
1202 TDEToggleAction* maai =
dynamic_cast<TDEToggleAction*
>(m_actionManager->action(
"article_set_status_important"));
1203 maai->setChecked(a.
keep());
1205 kdDebug() <<
"selected: " << a.guid() << endl;
1214 if (!article.isNull())
1215 Viewer::displayInExternalBrowser(article.link());
1221 Article article = m_articleList->currentArticle();
1223 if (article.isNull())
1227 if (article.link().isValid())
1228 link = article.link();
1229 else if (article.guidIsPermaLink())
1230 link = KURL(article.guid());
1234 slotOpenURL(link, 0L, BrowserRun::NEW_TAB_FOREGROUND);
1245 Article article = m_articleList->currentArticle();
1247 if (article.isNull())
1252 if (article.link().isValid())
1253 link = article.link();
1254 else if (article.guidIsPermaLink())
1255 link = KURL(article.guid());
1259 slotOpenURL(link, 0L, BrowserRun::NEW_TAB_BACKGROUND);
1265 Article article = m_articleList->currentArticle();
1267 if(article.isNull())
1271 if (article.link().isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
1274 if (article.link().isValid())
1275 link = article.link().url();
1277 link = article.guid();
1278 TQClipboard *cb = TQApplication::clipboard();
1279 cb->setText(link, TQClipboard::Clipboard);
1280 cb->setText(link, TQClipboard::Selection);
1286 KURL::List::iterator it;
1287 for ( it = urls.begin(); it != urls.end(); ++it )
1289 addFeed((*it).prettyURL(), after, parent,
false);
1295 if ( Settings::showQuickFilter() )
1297 Settings::setShowQuickFilter(
false);
1298 m_searchBar->slotClearSearch();
1299 m_searchBar->hide();
1303 Settings::setShowQuickFilter(
true);
1304 if (!m_displayingAboutPage)
1305 m_searchBar->show();
1313 if ( m_viewMode == CombinedView )
1316 TQValueList<Article> articles = m_articleList->selectedArticles();
1319 switch (articles.count())
1324 msg = i18n(
"<qt>Are you sure you want to delete article <b>%1</b>?</qt>").arg(TQStyleSheet::escape(articles.first().title()));
1327 msg = i18n(
"<qt>Are you sure you want to delete the selected article?</qt>",
1328 "<qt>Are you sure you want to delete the %n selected articles?</qt>",
1332 if (KMessageBox::warningContinueCancel(0, msg, i18n(
"Delete Article"), KStdGuiItem::del()) == KMessageBox::Continue)
1334 if (m_listTabWidget->activeView()->selectedNode())
1335 m_listTabWidget->activeView()->selectedNode()->setNotificationMode(
false);
1337 TQValueList<Feed*> feeds;
1338 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
1340 Feed* feed = (*it).feed();
1341 if (!feeds.contains(feed))
1347 for (TQValueList<Feed*>::Iterator it = feeds.begin(); it != feeds.end(); ++it)
1349 (*it)->setNotificationMode(
true);
1352 if (m_listTabWidget->activeView()->selectedNode())
1353 m_listTabWidget->activeView()->selectedNode()->setNotificationMode(
true);
1360 TQValueList<Article> articles = m_articleList->selectedArticles();
1362 if (articles.isEmpty())
1365 bool allFlagsSet =
true;
1366 for (TQValueList<Article>::Iterator it = articles.begin(); allFlagsSet && it != articles.end(); ++it)
1368 allFlagsSet =
false;
1370 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
1371 (*it).setKeep(!allFlagsSet);
1376 TQValueList<Article> articles = m_articleList->selectedArticles();
1378 if (articles.isEmpty())
1381 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
1382 (*it).setStatus(Article::Read);
1387 if (m_currentFrame == m_mainFrame)
1389 if (m_viewMode != CombinedView)
1392 SpeechClient::self()->slotSpeak(m_articleList->selectedArticles());
1397 if (m_listTabWidget->activeView()->selectedNode())
1405 TQString selectedText =
static_cast<PageViewer *
>(m_currentFrame->part())->selectedText();
1407 if (!selectedText.isEmpty())
1408 SpeechClient::self()->slotSpeak(selectedText,
"en");
1414 TQValueList<Article> articles = m_articleList->selectedArticles();
1416 if (articles.isEmpty())
1419 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
1420 (*it).setStatus(Article::Unread);
1425 TQValueList<Article> articles = m_articleList->selectedArticles();
1427 if (articles.isEmpty())
1430 for (TQValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
1431 (*it).setStatus(Article::New);
1436 Article article = m_articleList->currentArticle();
1438 if (article.isNull())
1441 article.setStatus(Article::Read);
1448 KFileItem *k=(KFileItem*)kifi;
1449 m_mainFrame->setStatusText(k->url().prettyURL());
1453 m_mainFrame->setStatusText(TQString());
1460 if (!Settings::resetQuickFilterOnNodeChange())
1462 m_searchBar->slotSetText(config->readEntry(
"searchLine"));
1463 int statusfilter = config->readNumEntry(
"searchCombo", -1);
1464 if (statusfilter != -1)
1465 m_searchBar->slotSetStatus(statusfilter);
1468 int selectedID = config->readNumEntry(
"selectedNodeID", -1);
1469 if (selectedID != -1)
1471 TreeNode* selNode = m_feedList->findByID(selectedID);
1473 m_listTabWidget->activeView()->setSelectedNode(selNode);
1476 TQStringList urls = config->readListEntry(
"FeedBrowserURLs");
1477 TQStringList::ConstIterator it = urls.begin();
1478 for (; it != urls.end(); ++it)
1480 KURL url = KURL::fromPathOrURL(*it);
1486 void View::saveProperties(TDEConfig* config)
1489 config->writeEntry(
"searchLine", m_searchBar->text());
1490 config->writeEntry(
"searchCombo", m_searchBar->status());
1492 TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
1496 config->writeEntry(
"selectedNodeID", sel->
id() );
1501 TQPtrList<Frame> frames = m_tabs->frames();
1502 TQPtrList<Frame>::ConstIterator it = frames.begin();
1503 for (; it != frames.end(); ++it)
1506 KParts::ReadOnlyPart *part = frame->part();
1507 PageViewer *pageViewer =
dynamic_cast<PageViewer*
>(part);
1510 KURL url = pageViewer->url();
1512 urls.append(url.prettyURL());
1516 config->writeEntry(
"FeedBrowserURLs", urls);
1519 void View::connectToFeedList(FeedList* feedList)
1521 connect(feedList->rootNode(), TQ_SIGNAL(signalChanged(TreeNode*)),
this, TQ_SLOT(
slotSetTotalUnread()));
1525 void View::disconnectFromFeedList(FeedList* feedList)
1527 disconnect(feedList->rootNode(), TQ_SIGNAL(signalChanged(TreeNode*)),
this, TQ_SLOT(
slotSetTotalUnread()));
1530 void View::updateTagActions()
1534 TQValueList<Article> selectedArticles = m_articleList->selectedArticles();
1536 for (TQValueList<Article>::ConstIterator it = selectedArticles.begin(); it != selectedArticles.end(); ++it)
1538 TQStringList atags = (*it).tags();
1539 for (TQStringList::ConstIterator it2 = atags.begin(); it2 != atags.end(); ++it2)
1541 if (!tags.contains(*it2))
1550 #include "akregator_view.moc"
Akregator-specific implementation of the ActionManager interface.
void slotUpdateTagActions(bool enabled, const TQStringList &tagIds)
fills the remove tag menu with the given tags enables/disables tag menu action according to enabled
This HTML viewer is used to display articles.
void slotShowArticle(const Article &article)
Show single article (normal view)
void slotShowNode(TreeNode *node)
Shows the articles of the tree node node (combined view).
A proxy class for RSS::Article with some additional methods to assist sorting.
bool keep() const
if true, the article should be kept even when expired
The model of a feed tree, represents an OPML document.
virtual TQDomDocument toXML() const
exports the feed list as OPML.
virtual bool readFromXML(const TQDomDocument &doc)
reads an OPML document and appends the items to this list
void append(FeedList *list, Folder *parent=0, TreeNode *after=0)
appends another feed list as sub tree.
virtual TQValueList< Article > articles(const TQString &tag=TQString())
Returns a sequence of the articles this node contains.
const TQString & htmlUrl() const
returns the URL of the HTML page of this feed
a powerful matcher supporting multiple criterions, which can be combined via logical OR or AND
Represents a folder (containing feeds and/or other folders)
virtual void insertChild(TreeNode *node, TreeNode *after)
inserts node as child after child node after.
virtual TQValueList< TreeNode * > children() const
returns the (direct) children of this node.
virtual void removeChild(TreeNode *node)
remove node from children.
virtual void appendChild(TreeNode *node)
inserts node as last child
void slotNotifyArticle(const Article &article)
notifies an article.
static NotificationManager * self()
singleton instance of notification manager
This is a RSS Aggregator "Part".
virtual bool mergePart(KParts::Part *)
merges a nested part's GUI into the gui of this part
Abstract base class for all kind of elements in the feed tree, like feeds and feed groups (and search...
virtual uint id() const
returns the ID of this node.
virtual bool isGroup() const =0
Helps the rest of the app to decide if node should be handled as group or not.
virtual int totalCount() const =0
returns the number of total articles in the node (for groups: the accumulated count of the subtree)
virtual TreeNode * prevSibling() const
Get the previous sibling.
virtual void setNotificationMode(bool doNotify, bool notifyOccurredChanges=true)
virtual int unread() const =0
The unread count, returns the number of new/unread articles in the node (for groups: the accumulated ...
virtual const TQString & title() const
Get title of node.
virtual Folder * parent() const
Returns the parent node.
virtual void slotDeleteExpiredArticles()=0
Deletes all expired articles in the node (depending on the expiry settings).
void slotMouseButtonPressed(int button, const Article &article, const TQPoint &pos, int c)
special behaviour in article list view (TODO: move code there?)
void slotFeedURLDropped(KURL::List &urls, TreeNode *after, Folder *parent)
called when URLs are dropped into the tree view
void slotFeedAdd()
adds a new feed to the feed tree
bool importFeeds(const TQDomDocument &doc)
Adds the feeds in doc to the "Imported Folder".
void slotUrlClickedInViewer(const KURL &url, Viewer *viewer, bool newTab, bool background)
HACK: part of the url opening hack for 3.5.
void slotSetSelectedArticleRead()
marks the currently selected article as read
void slotFetchCurrentFeed()
fetches the currently selected feed
void slotOpenCurrentArticle()
opens current article in new tab, background/foreground depends on settings TODO: use selected instea...
TQDomDocument feedListToOPML()
void slotMouseOverInfo(const KFileItem *kifi)
displays a URL in the status bar when the user moves the mouse over a link
void slotOpenCurrentArticleExternal()
opens the current article (currentItem) in external browser TODO: use selected instead of current?
void slotSetCurrentArticleReadDelayed()
marks the currenctly selected article as read after a user-set delay
virtual void readProperties(TDEConfig *config)
session management
void slotPrevUnreadArticle()
selects the previous unread article in the article list
void slotFeedTreeContextMenu(TDEListView *, TreeNode *, const TQPoint &)
Shows requested popup menu for feed tree.
void saveSettings()
saves settings.
void slotOpenArticleExternal(const Article &article, const TQPoint &, int)
opens article of item in external browser
void slotNodeSelected(TreeNode *node)
selected tree node has changed
void slotSetSelectedArticleUnread()
marks the currently selected article as unread
void slotArticleToggleKeepFlag(bool enabled)
toggles the keep flag of the currently selected article
View(Akregator::Part *part, TQWidget *parent, ActionManagerImpl *actionManager, const char *name)
constructor
void slotOpenCurrentArticleBackgroundTab()
opens the current article (currentItem) in background tab TODO: use selected instead of current?
void slotCopyLinkAddress()
copies the link of current article to clipboard
void slotSetSelectedArticleNew()
marks the currently selected article as new
void slotArticleDelete()
deletes the currently selected article
void slotCaptionChanged(const TQString &)
sets the window caption after a frame change
void slotNormalView()
switches view mode to normal view
void signalUnreadCountChanged(int)
emitted when the unread count of "All Feeds" was changed
void slotOpenNewTab(const KURL &url, bool background=false)
opens a page viewer in a new tab and loads an URL
void slotFeedRemove()
removes the currently selected feed (ask for confirmation)
void slotOpenURLReply(const KURL &url, Akregator::Viewer *currentViewer, Akregator::BrowserRun::OpeningMode mode)
HACK: receives signal from browserrun when the browserrun detects an HTML mimetype and actually loads...
void addFeedToGroup(const TQString &url, const TQString &group)
Add a feed to a group.
void slotMarkAllRead()
marks all articles in the currently selected feed as read
void slotFrameChanged(Frame *f)
called when another part/frame is activated.
void slotCombinedView()
switches view mode to combined view
void slotSetTotalUnread()
emits signalUnreadCountChanged(int)
void slotStatusText(const TQString &)
sets the status bar text to a given string
void slotToggleShowQuickFilter()
toggles the visibility of the filter bar
void slotFeedModify()
calls the properties dialog for feeds, starts renaming for feed groups
void slotOpenHomepage()
opens the homepage of the currently selected feed
void slotFetchAllFeeds()
starts fetching of all feeds in the tree
void slotWidescreenView()
switches view mode to widescreen view
void slotTextToSpeechRequest()
reads the currently selected articles using KTTSD
void slotArticleSelected(const Article &)
the article selection has changed
void slotFeedFetched(Feed *)
Feed has been fetched, populate article view if needed and update counters.
bool loadFeeds(const TQDomDocument &doc, Folder *parent=0)
Parse OPML presentation of feeds and read in articles archive, if present.
void slotMarkAllFeedsRead()
marks all articles in all feeds in the tree as read
void slotFeedAddGroup()
adds a feed group to the feed tree
void slotNextUnreadArticle()
selects the next unread article in the article list