summaryrefslogtreecommitdiffstats
path: root/akregator/src/akregator_view.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch)
tree67208f7c145782a7e90b123b982ca78d88cc2c87 /akregator/src/akregator_view.cpp
downloadtdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz
tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'akregator/src/akregator_view.cpp')
-rw-r--r--akregator/src/akregator_view.cpp1533
1 files changed, 1533 insertions, 0 deletions
diff --git a/akregator/src/akregator_view.cpp b/akregator/src/akregator_view.cpp
new file mode 100644
index 000000000..f45f784ed
--- /dev/null
+++ b/akregator/src/akregator_view.cpp
@@ -0,0 +1,1533 @@
+/*
+ This file is part of Akregator.
+
+ Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
+ 2004 Sashmit Bhaduri <smt@vfemail.net>
+ 2005 Frank Osterfeld <frank.osterfeld at kdemail.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include "actionmanagerimpl.h"
+#include "akregator_part.h"
+#include "akregator_run.h"
+#include "akregator_view.h"
+#include "listtabwidget.h"
+#include "addfeeddialog.h"
+#include "propertiesdialog.h"
+#include "frame.h"
+#include "fetchqueue.h"
+#include "feedlistview.h"
+#include "articlelistview.h"
+#include "articleviewer.h"
+#include "viewer.h"
+#include "feed.h"
+#include "tagfolder.h"
+#include "folder.h"
+#include "feedlist.h"
+#include "akregatorconfig.h"
+#include "kernel.h"
+#include "pageviewer.h"
+#include "searchbar.h"
+#include "speechclient.h"
+#include "storage.h"
+#include "tabwidget.h"
+#include "tag.h"
+#include "tagset.h"
+#include "tagnode.h"
+#include "tagnodelist.h"
+#include "tagpropertiesdialog.h"
+#include "treenode.h"
+#include "progressmanager.h"
+#include "treenodevisitor.h"
+#include "notificationmanager.h"
+
+#include <kaction.h>
+#include <kapplication.h>
+#include <kcharsets.h>
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kfileitem.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpassdlg.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <kshell.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kxmlguifactory.h>
+#include <kparts/partmanager.h>
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qdatetime.h> // for startup time measure
+#include <qfile.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmultilineedit.h>
+#include <qpopupmenu.h>
+#include <qptrlist.h>
+#include <qstylesheet.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qvaluevector.h>
+#include <qwhatsthis.h>
+#include <qclipboard.h>
+
+namespace Akregator {
+
+class View::EditNodePropertiesVisitor : public TreeNodeVisitor
+{
+ public:
+ EditNodePropertiesVisitor(View* view) : m_view(view) {}
+
+ virtual bool visitTagNode(TagNode* node)
+ {
+ TagPropertiesDialog* dlg = new TagPropertiesDialog(m_view);
+ dlg->setTag(node->tag());
+ dlg->exec();
+ delete dlg;
+ return true;
+ }
+
+ virtual bool visitFolder(Folder* node)
+ {
+ m_view->m_listTabWidget->activeView()->startNodeRenaming(node);
+ return true;
+ }
+
+ virtual bool visitFeed(Feed* node)
+ {
+ FeedPropertiesDialog *dlg = new FeedPropertiesDialog( m_view, "edit_feed" );
+ dlg->setFeed(node);
+ dlg->exec();
+ delete dlg;
+ return true;
+ }
+ private:
+
+ View* m_view;
+};
+
+class View::DeleteNodeVisitor : public TreeNodeVisitor
+{
+ public:
+ DeleteNodeVisitor(View* view) : m_view(view) {}
+
+ virtual bool visitTagNode(TagNode* node)
+ {
+ QString 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());
+ if (KMessageBox::warningContinueCancel(0, msg, i18n("Delete Tag"), KStdGuiItem::del()) == KMessageBox::Continue)
+ {
+ Tag tag = node->tag();
+ QValueList<Article> articles = m_view->m_feedList->rootNode()->articles(tag.id());
+ node->setNotificationMode(false);
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ (*it).removeTag(tag.id());
+ node->setNotificationMode(true);
+ Kernel::self()->tagSet()->remove(tag);
+ m_view->m_listTabWidget->activeView()->setFocus();
+ }
+ return true;
+ }
+
+ virtual bool visitFolder(Folder* node)
+ {
+ QString msg;
+ if (node->title().isEmpty())
+ msg = i18n("<qt>Are you sure you want to delete this folder and its feeds and subfolders?</qt>");
+ else
+ msg = i18n("<qt>Are you sure you want to delete folder <b>%1</b> and its feeds and subfolders?</qt>").arg(node->title());
+
+ if (KMessageBox::warningContinueCancel(0, msg, i18n("Delete Folder"), KStdGuiItem::del()) == KMessageBox::Continue)
+ {
+ delete node;
+ m_view->m_listTabWidget->activeView()->setFocus();
+ }
+ return true;
+ }
+
+ virtual bool visitFeed(Feed* node)
+ {
+ QString msg;
+ if (node->title().isEmpty())
+ msg = i18n("<qt>Are you sure you want to delete this feed?</qt>");
+ else
+ msg = i18n("<qt>Are you sure you want to delete feed <b>%1</b>?</qt>").arg(node->title());
+
+ if (KMessageBox::warningContinueCancel(0, msg, i18n("Delete Feed"), KStdGuiItem::del()) == KMessageBox::Continue)
+ {
+ delete node;
+ m_view->m_listTabWidget->activeView()->setFocus();
+ }
+ return true;
+ }
+ private:
+
+ View* m_view;
+};
+
+
+View::~View()
+{
+ // if m_shuttingDown is false, slotOnShutdown was not called. That
+ // means that not the whole app is shutdown, only the part. So it
+ // should be no risk to do the cleanups now
+ if (!m_shuttingDown)
+ {
+ kdDebug() << "View::~View(): slotOnShutdown() wasn't called. Calling it now." << endl;
+ slotOnShutdown();
+ }
+ kdDebug() << "View::~View(): leaving" << endl;
+}
+
+View::View( Part *part, QWidget *parent, ActionManagerImpl* actionManager, const char *name)
+ : QWidget(parent, name), m_viewMode(NormalView), m_actionManager(actionManager)
+{
+ m_editNodePropertiesVisitor = new EditNodePropertiesVisitor(this);
+ m_deleteNodeVisitor = new DeleteNodeVisitor(this);
+ m_keepFlagIcon = QPixmap(locate("data", "akregator/pics/akregator_flag.png"));
+ m_part = part;
+ m_feedList = new FeedList();
+ m_tagNodeList = new TagNodeList(m_feedList, Kernel::self()->tagSet());
+ m_shuttingDown = false;
+ m_displayingAboutPage = false;
+ m_currentFrame = 0L;
+ setFocusPolicy(QWidget::StrongFocus);
+
+ QVBoxLayout *lt = new QVBoxLayout( this );
+
+ m_horizontalSplitter = new QSplitter(QSplitter::Horizontal, this);
+
+ m_horizontalSplitter->setOpaqueResize(true);
+ lt->addWidget(m_horizontalSplitter);
+
+ connect (Kernel::self()->fetchQueue(), SIGNAL(fetched(Feed*)), this, SLOT(slotFeedFetched(Feed*)));
+ connect (Kernel::self()->fetchQueue(), SIGNAL(signalStarted()), this, SLOT(slotFetchingStarted()));
+ connect (Kernel::self()->fetchQueue(), SIGNAL(signalStopped()), this, SLOT(slotFetchingStopped()));
+
+ connect(Kernel::self()->tagSet(), SIGNAL(signalTagAdded(const Tag&)), this, SLOT(slotTagCreated(const Tag&)));
+ connect(Kernel::self()->tagSet(), SIGNAL(signalTagRemoved(const Tag&)), this, SLOT(slotTagRemoved(const Tag&)));
+
+ m_listTabWidget = new ListTabWidget(m_horizontalSplitter);
+ m_actionManager->initListTabWidget(m_listTabWidget);
+
+ connect(m_listTabWidget, SIGNAL(signalNodeSelected(TreeNode*)), this, SLOT(slotNodeSelected(TreeNode*)));
+
+ if (!Settings::showTaggingGUI())
+ m_listTabWidget->setViewMode(ListTabWidget::single);
+
+ m_feedListView = new NodeListView( this, "feedtree" );
+ m_listTabWidget->addView(m_feedListView, i18n("Feeds"), KGlobal::iconLoader()->loadIcon("folder", KIcon::Small));
+
+ connect(m_feedListView, SIGNAL(signalContextMenu(KListView*, TreeNode*, const QPoint&)), this, SLOT(slotFeedTreeContextMenu(KListView*, TreeNode*, const QPoint&)));
+
+ connect(m_feedListView, SIGNAL(signalDropped (KURL::List &, TreeNode*,
+ Folder*)), this, SLOT(slotFeedURLDropped (KURL::List &,
+ TreeNode*, Folder*)));
+
+ m_tagNodeListView = new NodeListView(this);
+ m_listTabWidget->addView(m_tagNodeListView, i18n("Tags"), KGlobal::iconLoader()->loadIcon("rss_tag", KIcon::Small));
+
+ connect(m_tagNodeListView, SIGNAL(signalContextMenu(KListView*, TreeNode*, const QPoint&)), this, SLOT(slotFeedTreeContextMenu(KListView*, TreeNode*, const QPoint&)));
+
+
+ ProgressManager::self()->setFeedList(m_feedList);
+
+ m_tabs = new TabWidget(m_horizontalSplitter);
+ m_actionManager->initTabWidget(m_tabs);
+
+ connect( m_part, SIGNAL(signalSettingsChanged()), m_tabs, SLOT(slotSettingsChanged()));
+
+ connect( m_tabs, SIGNAL( currentFrameChanged(Frame *) ), this,
+ SLOT( slotFrameChanged(Frame *) ) );
+
+ QWhatsThis::add(m_tabs, i18n("You can view multiple articles in several open tabs."));
+
+ m_mainTab = new QWidget(this, "Article Tab");
+ QVBoxLayout *mainTabLayout = new QVBoxLayout( m_mainTab, 0, 2, "mainTabLayout");
+
+ QWhatsThis::add(m_mainTab, i18n("Articles list."));
+
+ m_searchBar = new SearchBar(m_mainTab);
+
+ if ( !Settings::showQuickFilter() )
+ m_searchBar->hide();
+
+ mainTabLayout->addWidget(m_searchBar);
+
+ m_articleSplitter = new QSplitter(QSplitter::Vertical, m_mainTab, "panner2");
+
+ m_articleList = new ArticleListView( m_articleSplitter, "articles" );
+ m_actionManager->initArticleListView(m_articleList);
+
+ connect( m_articleList, SIGNAL(signalMouseButtonPressed(int, const Article&, const QPoint &, int)), this, SLOT(slotMouseButtonPressed(int, const Article&, const QPoint &, int)));
+
+ // use selectionChanged instead of clicked
+ connect( m_articleList, SIGNAL(signalArticleChosen(const Article&)),
+ this, SLOT( slotArticleSelected(const Article&)) );
+ connect( m_articleList, SIGNAL(signalDoubleClicked(const Article&, const QPoint&, int)),
+ this, SLOT( slotOpenArticleExternal(const Article&, const QPoint&, int)) );
+
+ m_articleViewer = new ArticleViewer(m_articleSplitter, "article_viewer");
+ m_articleViewer->setSafeMode(); // disable JS, Java, etc...
+
+ m_actionManager->initArticleViewer(m_articleViewer);
+
+ connect(m_searchBar, SIGNAL(signalSearch(const Akregator::Filters::ArticleMatcher&, const Akregator::Filters::ArticleMatcher&)), m_articleList, SLOT(slotSetFilter(const Akregator::Filters::ArticleMatcher&, const Akregator::Filters::ArticleMatcher&)));
+
+ connect(m_searchBar, SIGNAL(signalSearch(const Akregator::Filters::ArticleMatcher&, const Akregator::Filters::ArticleMatcher&)), m_articleViewer, SLOT(slotSetFilter(const Akregator::Filters::ArticleMatcher&, const Akregator::Filters::ArticleMatcher&)));
+
+ connect( m_articleViewer, SIGNAL(urlClicked(const KURL&, Viewer*, bool, bool)),
+ this, SLOT(slotUrlClickedInViewer(const KURL&, Viewer*, bool, bool)) );
+
+ connect( m_articleViewer->browserExtension(), SIGNAL(mouseOverInfo(const KFileItem *)),
+ this, SLOT(slotMouseOverInfo(const KFileItem *)) );
+
+ connect( m_part, SIGNAL(signalSettingsChanged()), m_articleViewer, SLOT(slotPaletteOrFontChanged()));
+ QWhatsThis::add(m_articleViewer->widget(), i18n("Browsing area."));
+ mainTabLayout->addWidget( m_articleSplitter );
+
+ m_mainFrame=new Frame(this, m_part, m_mainTab, i18n("Articles"), false);
+ connectFrame(m_mainFrame);
+ m_tabs->addFrame(m_mainFrame);
+
+ m_horizontalSplitter->setSizes( Settings::splitter1Sizes() );
+ m_articleSplitter->setSizes( Settings::splitter2Sizes() );
+
+ KConfig *conf = Settings::self()->config();
+ conf->setGroup("General");
+ if(!conf->readBoolEntry("Disable Introduction", false))
+ {
+ m_articleList->hide();
+ m_searchBar->hide();
+ m_articleViewer->displayAboutPage();
+ m_mainFrame->setTitle(i18n("About"));
+ m_displayingAboutPage = true;
+ }
+
+ m_fetchTimer = new QTimer(this);
+ connect( m_fetchTimer, SIGNAL(timeout()), this, SLOT(slotDoIntervalFetches()) );
+ m_fetchTimer->start(1000*60);
+
+ // delete expired articles once per hour
+ m_expiryTimer = new QTimer(this);
+ connect(m_expiryTimer, SIGNAL(timeout()), this,
+ SLOT(slotDeleteExpiredArticles()) );
+ m_expiryTimer->start(3600*1000);
+
+ m_markReadTimer = new QTimer(this);
+ connect(m_markReadTimer, SIGNAL(timeout()), this, SLOT(slotSetCurrentArticleReadDelayed()) );
+
+ switch (Settings::viewMode())
+ {
+ case CombinedView:
+ slotCombinedView();
+ break;
+ case WidescreenView:
+ slotWidescreenView();
+ break;
+ default:
+ slotNormalView();
+ }
+
+ if (!Settings::resetQuickFilterOnNodeChange())
+ {
+ m_searchBar->slotSetStatus(Settings::statusFilter());
+ m_searchBar->slotSetText(Settings::textFilter());
+ }
+
+ QTimer::singleShot(1000, this, SLOT(slotDeleteExpiredArticles()) );
+ m_part->mergePart(m_articleViewer);
+}
+
+void View::slotSettingsChanged()
+{
+ // if tagging is hidden, show only feed list
+ m_listTabWidget->setViewMode(Settings::showTaggingGUI() ? ListTabWidget::verticalTabs : ListTabWidget::single);
+
+}
+
+void View::slotOnShutdown()
+{
+ m_shuttingDown = true; // prevents slotFrameChanged from crashing
+
+ m_articleList->slotShowNode(0);
+ m_articleViewer->slotShowNode(0);
+
+ Kernel::self()->fetchQueue()->slotAbort();
+
+ m_feedListView->setNodeList(0);
+ ProgressManager::self()->setFeedList(0);
+
+ delete m_feedList;
+ delete m_tagNodeList;
+
+ // close all pageviewers in a controlled way
+ // fixes bug 91660, at least when no part loading data
+ m_tabs->setCurrentPage(m_tabs->count()-1); // select last page
+ while (m_tabs->count() > 1) // remove frames until only the main frame remains
+ m_tabs->slotRemoveCurrentFrame();
+
+ delete m_mainTab;
+ delete m_mainFrame;
+ delete m_editNodePropertiesVisitor;
+ delete m_deleteNodeVisitor;
+}
+
+void View::saveSettings()
+{
+ Settings::setSplitter1Sizes( m_horizontalSplitter->sizes() );
+ Settings::setSplitter2Sizes( m_articleSplitter->sizes() );
+ Settings::setViewMode( m_viewMode );
+ Settings::writeConfig();
+}
+
+void View::slotOpenNewTab(const KURL& url, bool background)
+{
+ PageViewer* page = new PageViewer(this, "page");
+
+ connect( m_part, SIGNAL(signalSettingsChanged()), page, SLOT(slotPaletteOrFontChanged()));
+
+ connect( page, SIGNAL(setTabIcon(const QPixmap&)),
+ this, SLOT(setTabIcon(const QPixmap&)));
+ connect( page, SIGNAL(urlClicked(const KURL &, Viewer*, bool, bool)),
+ this, SLOT(slotUrlClickedInViewer(const KURL &, Viewer*, bool, bool)) );
+
+ Frame* frame = new Frame(this, page, page->widget(), i18n("Untitled"));
+ frame->setAutoDeletePart(true); // delete page viewer when removing the tab
+
+ connect(page, SIGNAL(setWindowCaption (const QString &)), frame, SLOT(setTitle (const QString &)));
+ connectFrame(frame);
+ m_tabs->addFrame(frame);
+
+ if(!background)
+ m_tabs->showPage(page->widget());
+ else
+ setFocus();
+
+ page->openURL(url);
+}
+
+
+void View::setTabIcon(const QPixmap& icon)
+{
+ const PageViewer *s = dynamic_cast<const PageViewer*>(sender());
+ if (s) {
+ m_tabs->setTabIconSet(const_cast<PageViewer*>(s)->widget(), icon);
+ }
+}
+
+void View::connectFrame(Frame *f)
+{
+ connect(f, SIGNAL(statusText(const QString &)), this, SLOT(slotStatusText(const QString&)));
+ connect(f, SIGNAL(captionChanged (const QString &)), this, SLOT(slotCaptionChanged (const QString &)));
+ connect(f, SIGNAL(loadingProgress(int)), this, SLOT(slotLoadingProgress(int)) );
+ connect(f, SIGNAL(started()), this, SLOT(slotStarted()));
+ connect(f, SIGNAL(completed()), this, SLOT(slotCompleted()));
+ connect(f, SIGNAL(canceled(const QString &)), this, SLOT(slotCanceled(const QString&)));
+}
+
+void View::slotStatusText(const QString &c)
+{
+ if (sender() == m_currentFrame)
+ emit setStatusBarText(c);
+}
+
+void View::slotCaptionChanged(const QString &c)
+{
+ if (sender() == m_currentFrame)
+ emit setWindowCaption(c);
+}
+
+void View::slotStarted()
+{
+ if (sender() == m_currentFrame)
+ emit signalStarted(0);
+}
+
+void View::slotCanceled(const QString &s)
+{
+ if (sender() == m_currentFrame)
+ emit signalCanceled(s);
+}
+
+void View::slotCompleted()
+{
+ if (sender() == m_currentFrame)
+ emit signalCompleted();
+}
+
+void View::slotLoadingProgress(int percent)
+{
+ if (sender() == m_currentFrame)
+ emit setProgress(percent);
+}
+
+bool View::importFeeds(const QDomDocument& doc)
+{
+ FeedList* feedList = new FeedList();
+ bool parsed = feedList->readFromXML(doc);
+
+ // FIXME: parsing error, print some message
+ if (!parsed)
+ {
+ delete feedList;
+ return false;
+ }
+ QString title = feedList->title();
+
+ if (title.isEmpty())
+ title = i18n("Imported Folder");
+
+ bool ok;
+ title = KInputDialog::getText(i18n("Add Imported Folder"), i18n("Imported folder name:"), title, &ok);
+
+ if (!ok)
+ {
+ delete feedList;
+ return false;
+ }
+
+ Folder* fg = new Folder(title);
+ m_feedList->rootNode()->appendChild(fg);
+ m_feedList->append(feedList, fg);
+
+ return true;
+}
+
+bool View::loadFeeds(const QDomDocument& doc, Folder* parent)
+{
+ FeedList* feedList = new FeedList();
+ bool parsed = feedList->readFromXML(doc);
+
+ // parsing went wrong
+ if (!parsed)
+ {
+ delete feedList;
+ return false;
+ }
+ m_feedListView->setUpdatesEnabled(false);
+ m_tagNodeListView->setUpdatesEnabled(false);
+ if (!parent)
+ {
+ TagSet* tagSet = Kernel::self()->tagSet();
+
+ Kernel::self()->setFeedList(feedList);
+ ProgressManager::self()->setFeedList(feedList);
+ disconnectFromFeedList(m_feedList);
+ delete m_feedList;
+ delete m_tagNodeList;
+ m_feedList = feedList;
+ connectToFeedList(m_feedList);
+
+ m_tagNodeList = new TagNodeList(m_feedList, tagSet);
+ m_feedListView->setNodeList(m_feedList);
+ m_tagNodeListView->setNodeList(m_tagNodeList);
+
+ QStringList tagIDs = m_feedList->rootNode()->tags();
+ QStringList::ConstIterator end = tagIDs.end();
+ for (QStringList::ConstIterator it = tagIDs.begin(); it != end; ++it)
+ {
+ kdDebug() << *it << endl;
+ // create a tag for every tag ID in the archive that is not part of the tagset
+ // this is a fallback in case the tagset was corrupted,
+ // so the tagging information from archive does not get lost.
+ if (!tagSet->containsID(*it))
+ {
+ Tag tag(*it, *it);
+ tagSet->insert(tag);
+ }
+ }
+ }
+ else
+ m_feedList->append(feedList, parent);
+
+ m_feedListView->setUpdatesEnabled(true);
+ m_feedListView->triggerUpdate();
+ m_tagNodeListView->setUpdatesEnabled(true);
+ m_tagNodeListView->triggerUpdate();
+ return true;
+}
+
+void View::slotDeleteExpiredArticles()
+{
+ TreeNode* rootNode = m_feedList->rootNode();
+ if (rootNode)
+ rootNode->slotDeleteExpiredArticles();
+}
+
+QDomDocument View::feedListToOPML()
+{
+ return m_feedList->toXML();
+}
+
+void View::addFeedToGroup(const QString& url, const QString& groupName)
+{
+
+ // Locate the group.
+ TreeNode* node = m_feedListView->findNodeByTitle(groupName);
+
+ Folder* group = 0;
+ if (!node || !node->isGroup())
+ {
+ Folder* g = new Folder( groupName );
+ m_feedList->rootNode()->appendChild(g);
+ group = g;
+ }
+ else
+ group = static_cast<Folder*>(node);
+
+ // Invoke the Add Feed dialog with url filled in.
+ if (group)
+ addFeed(url, 0, group, true);
+}
+
+void View::slotNormalView()
+{
+ if (m_viewMode == NormalView)
+ return;
+
+ if (m_viewMode == CombinedView)
+ {
+ m_articleList->slotShowNode(m_listTabWidget->activeView()->selectedNode());
+ m_articleList->show();
+
+ Article article = m_articleList->currentArticle();
+
+ if (!article.isNull())
+ m_articleViewer->slotShowArticle(article);
+ else
+ m_articleViewer->slotShowSummary(m_listTabWidget->activeView()->selectedNode());
+ }
+
+ m_articleSplitter->setOrientation(QSplitter::Vertical);
+ m_viewMode = NormalView;
+
+ Settings::setViewMode( m_viewMode );
+}
+
+void View::slotWidescreenView()
+{
+ if (m_viewMode == WidescreenView)
+ return;
+
+ if (m_viewMode == CombinedView)
+ {
+ m_articleList->slotShowNode(m_listTabWidget->activeView()->selectedNode());
+ m_articleList->show();
+
+ Article article = m_articleList->currentArticle();
+
+ if (!article.isNull())
+ m_articleViewer->slotShowArticle(article);
+ else
+ m_articleViewer->slotShowSummary(m_listTabWidget->activeView()->selectedNode());
+ }
+
+ m_articleSplitter->setOrientation(QSplitter::Horizontal);
+ m_viewMode = WidescreenView;
+
+ Settings::setViewMode( m_viewMode );
+}
+
+void View::slotCombinedView()
+{
+ if (m_viewMode == CombinedView)
+ return;
+
+ m_articleList->slotClear();
+ m_articleList->hide();
+ m_viewMode = CombinedView;
+
+ slotNodeSelected(m_listTabWidget->activeView()->selectedNode());
+ Settings::setViewMode( m_viewMode );
+}
+
+void View::slotFrameChanged(Frame *f)
+{
+ if (m_shuttingDown)
+ return;
+
+ m_currentFrame=f;
+
+ emit setWindowCaption(f->caption());
+ emit setProgress(f->progress());
+ emit setStatusBarText(f->statusText());
+
+ if (f->part() == m_part)
+ m_part->mergePart(m_articleViewer);
+ else
+ m_part->mergePart(f->part());
+
+ f->widget()->setFocus();
+
+ switch (f->state())
+ {
+ case Frame::Started:
+ emit signalStarted(0);
+ break;
+ case Frame::Canceled:
+ emit signalCanceled(QString::null);
+ break;
+ case Frame::Idle:
+ case Frame::Completed:
+ default:
+ emit signalCompleted();
+ }
+}
+
+void View::slotFeedTreeContextMenu(KListView*, TreeNode* /*node*/, const QPoint& /*p*/)
+{
+ m_tabs->showPage(m_mainTab);
+}
+
+void View::slotMoveCurrentNodeUp()
+{
+ TreeNode* current = m_listTabWidget->activeView()->selectedNode();
+ if (!current)
+ return;
+ TreeNode* prev = current->prevSibling();
+ Folder* parent = current->parent();
+
+ if (!prev || !parent)
+ return;
+
+ parent->removeChild(prev);
+ parent->insertChild(prev, current);
+ m_listTabWidget->activeView()->ensureNodeVisible(current);
+}
+
+void View::slotMoveCurrentNodeDown()
+{
+ TreeNode* current = m_listTabWidget->activeView()->selectedNode();
+ if (!current)
+ return;
+ TreeNode* next = current->nextSibling();
+ Folder* parent = current->parent();
+
+ if (!next || !parent)
+ return;
+
+ parent->removeChild(current);
+ parent->insertChild(current, next);
+ m_listTabWidget->activeView()->ensureNodeVisible(current);
+}
+
+void View::slotMoveCurrentNodeLeft()
+{
+ TreeNode* current = m_listTabWidget->activeView()->selectedNode();
+ if (!current || !current->parent() || !current->parent()->parent())
+ return;
+
+ Folder* parent = current->parent();
+ Folder* grandparent = current->parent()->parent();
+
+ parent->removeChild(current);
+ grandparent->insertChild(current, parent);
+ m_listTabWidget->activeView()->ensureNodeVisible(current);
+}
+
+void View::slotMoveCurrentNodeRight()
+{
+ TreeNode* current = m_listTabWidget->activeView()->selectedNode();
+ if (!current || !current->parent())
+ return;
+ TreeNode* prev = current->prevSibling();
+
+ if ( prev && prev->isGroup() )
+ {
+ Folder* fg = static_cast<Folder*>(prev);
+ current->parent()->removeChild(current);
+ fg->appendChild(current);
+ m_listTabWidget->activeView()->ensureNodeVisible(current);
+ }
+}
+
+void View::slotNodeSelected(TreeNode* node)
+{
+ m_markReadTimer->stop();
+
+ if (node)
+ {
+ kdDebug() << "node selected: " << node->title() << endl;
+ kdDebug() << "unread: " << node->unread() << endl;
+ kdDebug() << "total: " << node->totalCount() << endl;
+ }
+
+ if (m_displayingAboutPage)
+ {
+ m_mainFrame->setTitle(i18n("Articles"));
+ if (m_viewMode != CombinedView)
+ m_articleList->show();
+ if (Settings::showQuickFilter())
+ m_searchBar->show();
+ m_displayingAboutPage = false;
+ }
+
+ m_tabs->showPage(m_mainTab);
+
+ if (Settings::resetQuickFilterOnNodeChange())
+ m_searchBar->slotClearSearch();
+
+ if (m_viewMode == CombinedView)
+ m_articleViewer->slotShowNode(node);
+ else
+ {
+ m_articleList->slotShowNode(node);
+ m_articleViewer->slotShowSummary(node);
+ }
+
+ if (node)
+ m_mainFrame->setCaption(node->title());
+
+ m_actionManager->slotNodeSelected(node);
+
+ updateTagActions();
+}
+
+void View::slotOpenURL(const KURL& url, Viewer* currentViewer, BrowserRun::OpeningMode mode)
+{
+ if (mode == BrowserRun::EXTERNAL)
+ Viewer::displayInExternalBrowser(url);
+ else
+ {
+ KParts::URLArgs args = currentViewer ? currentViewer->browserExtension()->urlArgs() : KParts::URLArgs();
+
+ BrowserRun* r = new BrowserRun(this, currentViewer, url, args, mode);
+ connect(r, SIGNAL(signalOpenInViewer(const KURL&, Akregator::Viewer*, Akregator::BrowserRun::OpeningMode)),
+ this, SLOT(slotOpenURLReply(const KURL&, Akregator::Viewer*, Akregator::BrowserRun::OpeningMode)));
+ }
+}
+
+//TODO: KDE4 remove this ugly ugly hack
+void View::slotUrlClickedInViewer(const KURL& url, Viewer* viewer, bool newTab, bool background)
+{
+
+ if (!newTab)
+ {
+ slotOpenURL(url, viewer, BrowserRun::CURRENT_TAB);
+ }
+ else
+ {
+ slotOpenURL(url, 0L, background ? BrowserRun::NEW_TAB_BACKGROUND : BrowserRun::NEW_TAB_FOREGROUND);
+ }
+}
+
+//TODO: KDE4 remove this ugly ugly hack
+void View::slotOpenURLReply(const KURL& url, Viewer* currentViewer, BrowserRun::OpeningMode mode)
+{
+ switch (mode)
+ {
+ case BrowserRun::CURRENT_TAB:
+ currentViewer->openURL(url);
+ break;
+ case BrowserRun::NEW_TAB_FOREGROUND:
+ case BrowserRun::NEW_TAB_BACKGROUND:
+ slotOpenNewTab(url, mode == BrowserRun::NEW_TAB_BACKGROUND);
+ break;
+ case BrowserRun::EXTERNAL:
+ Viewer::displayInExternalBrowser(url);
+ break;
+ }
+}
+
+void View::slotFeedAdd()
+{
+ Folder* group = 0;
+ if (!m_feedListView->selectedNode())
+ group = m_feedList->rootNode(); // all feeds
+ else
+ {
+ //TODO: tag nodes need rework
+ if ( m_feedListView->selectedNode()->isGroup())
+ group = static_cast<Folder*>(m_feedListView->selectedNode());
+ else
+ group= m_feedListView->selectedNode()->parent();
+
+ }
+
+ TreeNode* lastChild = group->children().last();
+
+ addFeed(QString::null, lastChild, group, false);
+}
+
+void View::addFeed(const QString& url, TreeNode *after, Folder* parent, bool autoExec)
+{
+
+ AddFeedDialog *afd = new AddFeedDialog( 0, "add_feed" );
+
+ afd->setURL(KURL::decode_string(url));
+
+ if (autoExec)
+ afd->slotOk();
+ else
+ {
+ if (afd->exec() != QDialog::Accepted)
+ {
+ delete afd;
+ return;
+ }
+ }
+
+ Feed* feed = afd->feed;
+ delete afd;
+
+ FeedPropertiesDialog *dlg = new FeedPropertiesDialog( 0, "edit_feed" );
+ dlg->setFeed(feed);
+
+ dlg->selectFeedName();
+
+ if (!autoExec)
+ if (dlg->exec() != QDialog::Accepted)
+ {
+ delete feed;
+ delete dlg;
+ return;
+ }
+
+ if (!parent)
+ parent = m_feedList->rootNode();
+
+ parent->insertChild(feed, after);
+
+ m_feedListView->ensureNodeVisible(feed);
+
+
+ delete dlg;
+}
+
+void View::slotFeedAddGroup()
+{
+ TreeNode* node = m_feedListView->selectedNode();
+ TreeNode* after = 0;
+
+ if (!node)
+ node = m_feedListView->rootNode();
+
+ // if a feed is selected, add group next to it
+ //TODO: tag nodes need rework
+ if (!node->isGroup())
+ {
+ after = node;
+ node = node->parent();
+ }
+
+ Folder* currentGroup = static_cast<Folder*> (node);
+
+ bool Ok;
+
+ QString text = KInputDialog::getText(i18n("Add Folder"), i18n("Folder name:"), "", &Ok);
+
+ if (Ok)
+ {
+ Folder* newGroup = new Folder(text);
+ if (!after)
+ currentGroup->appendChild(newGroup);
+ else
+ currentGroup->insertChild(newGroup, after);
+
+ m_feedListView->ensureNodeVisible(newGroup);
+ }
+}
+
+void View::slotFeedRemove()
+{
+ TreeNode* selectedNode = m_listTabWidget->activeView()->selectedNode();
+
+ // don't delete root element! (safety valve)
+ if (!selectedNode || selectedNode == m_feedList->rootNode())
+ return;
+
+ m_deleteNodeVisitor->visit(selectedNode);
+}
+
+void View::slotFeedModify()
+{
+ TreeNode* node = m_listTabWidget->activeView()->selectedNode();
+ if (node)
+ m_editNodePropertiesVisitor->visit(node);
+
+}
+
+void View::slotNextUnreadArticle()
+{
+ if (m_viewMode == CombinedView)
+ m_listTabWidget->activeView()->slotNextUnreadFeed();
+
+ TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
+ if (sel && sel->unread() > 0)
+ m_articleList->slotNextUnreadArticle();
+ else
+ m_listTabWidget->activeView()->slotNextUnreadFeed();
+}
+
+void View::slotPrevUnreadArticle()
+{
+ if (m_viewMode == CombinedView)
+ m_listTabWidget->activeView()->slotPrevUnreadFeed();
+
+ TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
+ if (sel && sel->unread() > 0)
+ m_articleList->slotPreviousUnreadArticle();
+ else
+ m_listTabWidget->activeView()->slotPrevUnreadFeed();
+}
+
+void View::slotMarkAllFeedsRead()
+{
+ m_feedList->rootNode()->slotMarkAllArticlesAsRead();
+}
+
+void View::slotMarkAllRead()
+{
+ if(!m_listTabWidget->activeView()->selectedNode()) return;
+ m_listTabWidget->activeView()->selectedNode()->slotMarkAllArticlesAsRead();
+}
+
+void View::slotOpenHomepage()
+{
+ Feed* feed = dynamic_cast<Feed *>(m_listTabWidget->activeView()->selectedNode());
+
+ if (!feed)
+ return;
+
+ KURL url = KURL(feed->htmlUrl())
+;
+ switch (Settings::lMBBehaviour())
+ {
+ case Settings::EnumLMBBehaviour::OpenInExternalBrowser:
+ slotOpenURL(url, 0, BrowserRun::EXTERNAL);
+ break;
+ case Settings::EnumLMBBehaviour::OpenInBackground:
+ slotOpenURL(url, 0, BrowserRun::NEW_TAB_BACKGROUND);
+ break;
+ default:
+ slotOpenURL(url, 0, BrowserRun::NEW_TAB_FOREGROUND);
+ }
+}
+
+void View::slotSetTotalUnread()
+{
+ emit signalUnreadCountChanged( m_feedList->rootNode()->unread() );
+}
+
+void View::slotDoIntervalFetches()
+{
+ m_feedList->rootNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue(), true);
+}
+
+void View::slotFetchCurrentFeed()
+{
+ if ( !m_listTabWidget->activeView()->selectedNode() )
+ return;
+ m_listTabWidget->activeView()->selectedNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue());
+}
+
+void View::slotFetchAllFeeds()
+{
+ m_feedList->rootNode()->slotAddToFetchQueue(Kernel::self()->fetchQueue());
+}
+
+void View::slotFetchingStarted()
+{
+ m_mainFrame->setState(Frame::Started);
+ m_actionManager->action("feed_stop")->setEnabled(true);
+ m_mainFrame->setStatusText(i18n("Fetching Feeds..."));
+}
+
+void View::slotFetchingStopped()
+{
+ m_mainFrame->setState(Frame::Completed);
+ m_actionManager->action("feed_stop")->setEnabled(false);
+ m_mainFrame->setStatusText(QString::null);
+}
+
+void View::slotFeedFetched(Feed *feed)
+{
+ // iterate through the articles (once again) to do notifications properly
+ if (feed->articles().count() > 0)
+ {
+ QValueList<Article> articles = feed->articles();
+ QValueList<Article>::ConstIterator it;
+ QValueList<Article>::ConstIterator end = articles.end();
+ for (it = articles.begin(); it != end; ++it)
+ {
+ if ((*it).status()==Article::New && ((*it).feed()->useNotification() || Settings::useNotifications()))
+ {
+ NotificationManager::self()->slotNotifyArticle(*it);
+ }
+ }
+ }
+}
+
+void View::slotMouseButtonPressed(int button, const Article& article, const QPoint &, int)
+{
+ if (button == Qt::MidButton)
+ {
+ KURL link = article.link();
+ switch (Settings::mMBBehaviour())
+ {
+ case Settings::EnumMMBBehaviour::OpenInExternalBrowser:
+ slotOpenURL(link, 0L, BrowserRun::EXTERNAL);
+ break;
+ case Settings::EnumMMBBehaviour::OpenInBackground:
+ slotOpenURL(link, 0L, BrowserRun::NEW_TAB_BACKGROUND);
+ break;
+ default:
+ slotOpenURL(link, 0L, BrowserRun::NEW_TAB_FOREGROUND);
+ }
+ }
+}
+
+void View::slotAssignTag(const Tag& tag, bool assign)
+{
+ kdDebug() << (assign ? "assigned" : "removed") << " tag \"" << tag.id() << "\"" << endl;
+ QValueList<Article> selectedArticles = m_articleList->selectedArticles();
+ for (QValueList<Article>::Iterator it = selectedArticles.begin(); it != selectedArticles.end(); ++it)
+ {
+ if (assign)
+ (*it).addTag(tag.id());
+ else
+ (*it).removeTag(tag.id());
+ }
+ updateTagActions();
+}
+/*
+void View::slotRemoveTag(const Tag& tag)
+{
+ kdDebug() << "remove tag \"" << tag.id() << "\" from selected articles" << endl;
+ QValueList<Article> selectedArticles = m_articleList->selectedArticles();
+ for (QValueList<Article>::Iterator it = selectedArticles.begin(); it != selectedArticles.end(); ++it)
+ (*it).removeTag(tag.id());
+
+ updateTagActions();
+}
+*/
+void View::slotNewTag()
+{
+ Tag tag(KApplication::randomString(8), "New Tag");
+ Kernel::self()->tagSet()->insert(tag);
+ TagNode* node = m_tagNodeList->findByTagID(tag.id());
+ if (node)
+ m_tagNodeListView->startNodeRenaming(node);
+}
+
+void View::slotTagCreated(const Tag& tag)
+{
+ if (m_tagNodeList && !m_tagNodeList->containsTagId(tag.id()))
+ {
+ TagNode* tagNode = new TagNode(tag, m_feedList->rootNode());
+ m_tagNodeList->rootNode()->appendChild(tagNode);
+ }
+}
+
+void View::slotTagRemoved(const Tag& /*tag*/)
+{
+}
+
+void View::slotArticleSelected(const Article& article)
+{
+ if (m_viewMode == CombinedView)
+ return;
+
+ m_markReadTimer->stop();
+
+ Feed *feed = article.feed();
+ if (!feed)
+ return;
+
+ Article a(article);
+ if (a.status() != Article::Read)
+ {
+ int delay;
+
+ if ( Settings::useMarkReadDelay() )
+ {
+ delay = Settings::markReadDelay();
+
+ if (delay > 0)
+ m_markReadTimer->start( delay*1000, true );
+ else
+ a.setStatus(Article::Read);
+ }
+ }
+
+ KToggleAction* maai = dynamic_cast<KToggleAction*>(m_actionManager->action("article_set_status_important"));
+ maai->setChecked(a.keep());
+
+ kdDebug() << "selected: " << a.guid() << endl;
+
+ updateTagActions();
+
+ m_articleViewer->slotShowArticle(a);
+}
+
+void View::slotOpenArticleExternal(const Article& article, const QPoint&, int)
+{
+ if (!article.isNull())
+ Viewer::displayInExternalBrowser(article.link());
+}
+
+
+void View::slotOpenCurrentArticle()
+{
+ Article article = m_articleList->currentArticle();
+
+ if (article.isNull())
+ return;
+
+ KURL link;
+ if (article.link().isValid())
+ link = article.link();
+ else if (article.guidIsPermaLink())
+ link = KURL(article.guid());
+
+ if (link.isValid())
+ {
+ slotOpenURL(link, 0L, BrowserRun::NEW_TAB_FOREGROUND);
+ }
+}
+
+void View::slotOpenCurrentArticleExternal()
+{
+ slotOpenArticleExternal(m_articleList->currentArticle(), QPoint(), 0);
+}
+
+void View::slotOpenCurrentArticleBackgroundTab()
+{
+ Article article = m_articleList->currentArticle();
+
+ if (article.isNull())
+ return;
+
+ KURL link;
+
+ if (article.link().isValid())
+ link = article.link();
+ else if (article.guidIsPermaLink())
+ link = KURL(article.guid());
+
+ if (link.isValid())
+ {
+ slotOpenURL(link, 0L, BrowserRun::NEW_TAB_BACKGROUND);
+ }
+}
+
+void View::slotCopyLinkAddress()
+{
+ Article article = m_articleList->currentArticle();
+
+ if(article.isNull())
+ return;
+
+ QString link;
+ if (article.link().isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
+ {
+ // in case link isn't valid, fall back to the guid permaLink.
+ if (article.link().isValid())
+ link = article.link().url();
+ else
+ link = article.guid();
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText(link, QClipboard::Clipboard);
+ cb->setText(link, QClipboard::Selection);
+ }
+}
+
+void View::slotFeedURLDropped(KURL::List &urls, TreeNode* after, Folder* parent)
+{
+ KURL::List::iterator it;
+ for ( it = urls.begin(); it != urls.end(); ++it )
+ {
+ addFeed((*it).prettyURL(), after, parent, false);
+ }
+}
+
+void View::slotToggleShowQuickFilter()
+{
+ if ( Settings::showQuickFilter() )
+ {
+ Settings::setShowQuickFilter(false);
+ m_searchBar->slotClearSearch();
+ m_searchBar->hide();
+ }
+ else
+ {
+ Settings::setShowQuickFilter(true);
+ if (!m_displayingAboutPage)
+ m_searchBar->show();
+ }
+
+}
+
+void View::slotArticleDelete()
+{
+
+ if ( m_viewMode == CombinedView )
+ return;
+
+ QValueList<Article> articles = m_articleList->selectedArticles();
+
+ QString msg;
+ switch (articles.count())
+ {
+ case 0:
+ return;
+ case 1:
+ msg = i18n("<qt>Are you sure you want to delete article <b>%1</b>?</qt>").arg(QStyleSheet::escape(articles.first().title()));
+ break;
+ default:
+ msg = i18n("<qt>Are you sure you want to delete the selected article?</qt>",
+ "<qt>Are you sure you want to delete the %n selected articles?</qt>",
+ articles.count());
+ }
+
+ if (KMessageBox::warningContinueCancel(0, msg, i18n("Delete Article"), KStdGuiItem::del()) == KMessageBox::Continue)
+ {
+ if (m_listTabWidget->activeView()->selectedNode())
+ m_listTabWidget->activeView()->selectedNode()->setNotificationMode(false);
+
+ QValueList<Feed*> feeds;
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ {
+ Feed* feed = (*it).feed();
+ if (!feeds.contains(feed))
+ feeds.append(feed);
+ feed->setNotificationMode(false);
+ (*it).setDeleted();
+ }
+
+ for (QValueList<Feed*>::Iterator it = feeds.begin(); it != feeds.end(); ++it)
+ {
+ (*it)->setNotificationMode(true);
+ }
+
+ if (m_listTabWidget->activeView()->selectedNode())
+ m_listTabWidget->activeView()->selectedNode()->setNotificationMode(true);
+ }
+}
+
+
+void View::slotArticleToggleKeepFlag(bool /*enabled*/)
+{
+ QValueList<Article> articles = m_articleList->selectedArticles();
+
+ if (articles.isEmpty())
+ return;
+
+ bool allFlagsSet = true;
+ for (QValueList<Article>::Iterator it = articles.begin(); allFlagsSet && it != articles.end(); ++it)
+ if (!(*it).keep())
+ allFlagsSet = false;
+
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ (*it).setKeep(!allFlagsSet);
+}
+
+void View::slotSetSelectedArticleRead()
+{
+ QValueList<Article> articles = m_articleList->selectedArticles();
+
+ if (articles.isEmpty())
+ return;
+
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ (*it).setStatus(Article::Read);
+}
+
+void View::slotTextToSpeechRequest()
+{
+ if (m_currentFrame == m_mainFrame)
+ {
+ if (m_viewMode != CombinedView)
+ {
+ // in non-combined view, read selected articles
+ SpeechClient::self()->slotSpeak(m_articleList->selectedArticles());
+ // TODO: if article viewer has a selection, read only the selected text?
+ }
+ else
+ {
+ if (m_listTabWidget->activeView()->selectedNode())
+ {
+ //TODO: read articles in current node, respecting quick filter!
+ }
+ }
+ }
+ else
+ {
+ QString selectedText = static_cast<PageViewer *>(m_currentFrame->part())->selectedText();
+
+ if (!selectedText.isEmpty())
+ SpeechClient::self()->slotSpeak(selectedText, "en");
+ }
+}
+
+void View::slotSetSelectedArticleUnread()
+{
+ QValueList<Article> articles = m_articleList->selectedArticles();
+
+ if (articles.isEmpty())
+ return;
+
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ (*it).setStatus(Article::Unread);
+}
+
+void View::slotSetSelectedArticleNew()
+{
+ QValueList<Article> articles = m_articleList->selectedArticles();
+
+ if (articles.isEmpty())
+ return;
+
+ for (QValueList<Article>::Iterator it = articles.begin(); it != articles.end(); ++it)
+ (*it).setStatus(Article::New);
+}
+
+void View::slotSetCurrentArticleReadDelayed()
+{
+ Article article = m_articleList->currentArticle();
+
+ if (article.isNull())
+ return;
+
+ article.setStatus(Article::Read);
+}
+
+void View::slotMouseOverInfo(const KFileItem *kifi)
+{
+ if (kifi)
+ {
+ KFileItem *k=(KFileItem*)kifi;
+ m_mainFrame->setStatusText(k->url().prettyURL());//getStatusBarInfo());
+ }
+ else
+ {
+ m_mainFrame->setStatusText(QString::null);
+ }
+}
+
+void View::readProperties(KConfig* config)
+{
+
+ if (!Settings::resetQuickFilterOnNodeChange())
+ {
+ m_searchBar->slotSetText(config->readEntry("searchLine"));
+ int statusfilter = config->readNumEntry("searchCombo", -1);
+ if (statusfilter != -1)
+ m_searchBar->slotSetStatus(statusfilter);
+ }
+
+ int selectedID = config->readNumEntry("selectedNodeID", -1);
+ if (selectedID != -1)
+ {
+ TreeNode* selNode = m_feedList->findByID(selectedID);
+ if (selNode)
+ m_listTabWidget->activeView()->setSelectedNode(selNode);
+ }
+
+ QStringList urls = config->readListEntry("FeedBrowserURLs");
+ QStringList::ConstIterator it = urls.begin();
+ for (; it != urls.end(); ++it)
+ {
+ KURL url = KURL::fromPathOrURL(*it);
+ if (url.isValid())
+ slotOpenNewTab(url, true); // open in background
+ }
+}
+
+void View::saveProperties(KConfig* config)
+{
+ // save filter settings
+ config->writeEntry("searchLine", m_searchBar->text());
+ config->writeEntry("searchCombo", m_searchBar->status());
+
+ TreeNode* sel = m_listTabWidget->activeView()->selectedNode();
+
+ if (sel)
+ {
+ config->writeEntry("selectedNodeID", sel->id() );
+ }
+
+ // save browser URLs
+ QStringList urls;
+ QPtrList<Frame> frames = m_tabs->frames();
+ QPtrList<Frame>::ConstIterator it = frames.begin();
+ for (; it != frames.end(); ++it)
+ {
+ Frame *frame = *it;
+ KParts::ReadOnlyPart *part = frame->part();
+ PageViewer *pageViewer = dynamic_cast<PageViewer*>(part); // don't save the ArticleViewer
+ if (pageViewer)
+ {
+ KURL url = pageViewer->url();
+ if (url.isValid())
+ urls.append(url.prettyURL());
+ }
+ }
+
+ config->writeEntry("FeedBrowserURLs", urls);
+}
+
+void View::connectToFeedList(FeedList* feedList)
+{
+ connect(feedList->rootNode(), SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotSetTotalUnread()));
+ slotSetTotalUnread();
+}
+
+void View::disconnectFromFeedList(FeedList* feedList)
+{
+ disconnect(feedList->rootNode(), SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotSetTotalUnread()));
+}
+
+void View::updateTagActions()
+{
+ QStringList tags;
+
+ QValueList<Article> selectedArticles = m_articleList->selectedArticles();
+
+ for (QValueList<Article>::ConstIterator it = selectedArticles.begin(); it != selectedArticles.end(); ++it)
+ {
+ QStringList atags = (*it).tags();
+ for (QStringList::ConstIterator it2 = atags.begin(); it2 != atags.end(); ++it2)
+ {
+ if (!tags.contains(*it2))
+ tags += *it2;
+ }
+ }
+ m_actionManager->slotUpdateTagActions(!selectedArticles.isEmpty(), tags);
+}
+
+} // namespace Akregator
+
+#include "akregator_view.moc"