• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

akregator

  • sources
  • kde-4.12
  • kdepim
  • akregator
  • src
selectioncontroller.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Akregator.
3 
4  Copyright (C) 2007 Frank Osterfeld <osterfeld@kde.org>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of Qt, and distribute the resulting executable,
22  without including the source code for Qt in the source distribution.
23 */
24 
25 #include "selectioncontroller.h"
26 
27 #include "actionmanager.h"
28 #include "article.h"
29 #include "articlejobs.h"
30 #include "articlemodel.h"
31 #include "feedlist.h"
32 #include "subscriptionlistmodel.h"
33 #include "treenode.h"
34 
35 #include <KRandom>
36 #include <KDebug>
37 
38 #include <QAbstractItemView>
39 #include <QMenu>
40 #include <QTimer>
41 
42 using namespace boost;
43 using namespace Akregator;
44 
45 namespace {
46  static Akregator::Article articleForIndex( const QModelIndex& index, FeedList* feedList )
47  {
48  if ( !index.isValid() )
49  return Akregator::Article();
50 
51  const QString guid = index.data( ArticleModel::GuidRole ).toString();
52  const QString feedId = index.data( ArticleModel::FeedIdRole ).toString();
53  return feedList->findArticle( feedId, guid );
54  }
55 
56  static QList<Akregator::Article> articlesForIndexes( const QModelIndexList& indexes, FeedList* feedList )
57  {
58  QList<Akregator::Article> articles;
59  Q_FOREACH ( const QModelIndex& i, indexes )
60  {
61  const Article a = articleForIndex( i, feedList );
62  if ( a.isNull() )
63  continue;
64  articles.append( articleForIndex( i, feedList ) );
65  }
66 
67  return articles;
68  }
69 
70  static Akregator::TreeNode* subscriptionForIndex( const QModelIndex& index, Akregator::FeedList* feedList )
71  {
72  if ( !index.isValid() )
73  return 0L;
74 
75  return feedList->findByID( index.data( Akregator::SubscriptionListModel::SubscriptionIdRole ).toInt() );
76  }
77 } // anon namespace
78 
79 Akregator::SelectionController::SelectionController( QObject* parent )
80  : AbstractSelectionController( parent ),
81  m_feedList(),
82  m_feedSelector(),
83  m_articleLister( 0 ),
84  m_singleDisplay( 0 ),
85  m_subscriptionModel ( new SubscriptionListModel( shared_ptr<FeedList>(), this ) ),
86  m_folderExpansionHandler( 0 ),
87  m_articleModel( 0 ),
88  m_selectedSubscription()
89 {
90 }
91 
92 Akregator::SelectionController::~SelectionController()
93 {
94  delete m_articleModel;
95 }
96 
97 
98 void Akregator::SelectionController::setFeedSelector( QAbstractItemView* feedSelector )
99 {
100  if ( m_feedSelector == feedSelector )
101  return;
102 
103  if ( m_feedSelector ) {
104  m_feedSelector->disconnect( this );
105  m_feedSelector->selectionModel()->disconnect( this );
106  }
107 
108  m_feedSelector = feedSelector;
109 
110  if ( !m_feedSelector )
111  return;
112 
113  m_feedSelector->setModel( m_subscriptionModel );
114 
115  connect( m_feedSelector, SIGNAL(customContextMenuRequested(QPoint)),
116  this, SLOT(subscriptionContextMenuRequested(QPoint)) );
117  connect( m_feedSelector->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
118  this, SLOT(selectedSubscriptionChanged(QModelIndex)) );
119  connect( m_feedSelector, SIGNAL(activated(QModelIndex)),
120  this, SLOT(selectedSubscriptionChanged(QModelIndex)) );
121 
122 }
123 
124 void Akregator::SelectionController::setArticleLister( Akregator::ArticleLister* lister )
125 {
126  if ( m_articleLister == lister )
127  return;
128 
129  if ( m_articleLister )
130  m_articleLister->articleSelectionModel()->disconnect( this );
131  if ( m_articleLister && m_articleLister->itemView() )
132  m_articleLister->itemView()->disconnect( this );
133 
134  m_articleLister = lister;
135 
136  if ( m_articleLister && m_articleLister->itemView() )
137  connect( m_articleLister->itemView(), SIGNAL(doubleClicked(QModelIndex)),
138  this, SLOT(articleIndexDoubleClicked(QModelIndex)) );
139 }
140 
141 void Akregator::SelectionController::setSingleArticleDisplay( Akregator::SingleArticleDisplay* display )
142 {
143  m_singleDisplay = display;
144 }
145 
146 Akregator::Article Akregator::SelectionController::currentArticle() const
147 {
148  if ( !m_articleLister || !m_articleLister->articleSelectionModel() )
149  return Article();
150  return ::articleForIndex( m_articleLister->articleSelectionModel()->currentIndex(), m_feedList.get() );
151 }
152 
153 QModelIndex SelectionController::currentArticleIndex() const
154 {
155  return m_articleLister->articleSelectionModel()->currentIndex();
156 }
157 
158 QList<Akregator::Article> Akregator::SelectionController::selectedArticles() const
159 {
160  if ( !m_articleLister || !m_articleLister->articleSelectionModel() )
161  return QList<Akregator::Article>();
162  return ::articlesForIndexes( m_articleLister->articleSelectionModel()->selectedRows(), m_feedList.get() );
163 }
164 
165 Akregator::TreeNode* Akregator::SelectionController::selectedSubscription() const
166 {
167  return ::subscriptionForIndex( m_feedSelector->selectionModel()->currentIndex(), m_feedList.get() );
168 }
169 
170 void Akregator::SelectionController::setFeedList( const shared_ptr<FeedList>& list )
171 {
172  if ( m_feedList == list )
173  return;
174 
175  m_feedList = list;
176  std::auto_ptr<SubscriptionListModel> oldModel( m_subscriptionModel );
177  m_subscriptionModel = new SubscriptionListModel( m_feedList, this );
178 
179  if ( m_folderExpansionHandler ) {
180  m_folderExpansionHandler->setFeedList( m_feedList );
181  m_folderExpansionHandler->setModel( m_subscriptionModel );
182  }
183 
184  if ( m_feedSelector ) {
185  m_feedSelector->setModel( m_subscriptionModel );
186  disconnect( m_feedSelector->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
187  this, SLOT(selectedSubscriptionChanged(QModelIndex)) );
188  connect( m_feedSelector->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
189  this, SLOT(selectedSubscriptionChanged(QModelIndex)) );
190  }
191 }
192 
193 void Akregator::SelectionController::setFolderExpansionHandler( Akregator::FolderExpansionHandler* handler )
194 {
195  if ( handler == m_folderExpansionHandler )
196  return;
197  m_folderExpansionHandler = handler;
198  if ( !m_folderExpansionHandler )
199  return;
200  handler->setFeedList( m_feedList );
201  handler->setModel( m_subscriptionModel );
202 }
203 
204 void Akregator::SelectionController::articleHeadersAvailable( KJob* job )
205 {
206  assert( job );
207  assert( job == m_listJob );
208 
209 
210  if ( job->error() ) {
211  kWarning() << job->errorText();
212  return;
213  }
214  TreeNode* const node = m_listJob->node();
215 
216  assert( node ); // if there was no error, the node must still exist
217  assert( node == m_selectedSubscription ); //...and equal the previously selected node
218 
219  ArticleModel* const newModel = new ArticleModel( m_listJob->articles() );
220 
221  connect( node, SIGNAL(destroyed()),
222  newModel, SLOT(clear()) );
223  connect( node, SIGNAL(signalArticlesAdded(Akregator::TreeNode*,QList<Akregator::Article>)),
224  newModel, SLOT(articlesAdded(Akregator::TreeNode*,QList<Akregator::Article>)) );
225  connect( node, SIGNAL(signalArticlesRemoved(Akregator::TreeNode*,QList<Akregator::Article>)),
226  newModel, SLOT(articlesRemoved(Akregator::TreeNode*,QList<Akregator::Article>)) );
227  connect( node, SIGNAL(signalArticlesUpdated(Akregator::TreeNode*,QList<Akregator::Article>)),
228  newModel, SLOT(articlesUpdated(Akregator::TreeNode*,QList<Akregator::Article>)) );
229 
230  m_articleLister->setIsAggregation( node->isAggregation() );
231  m_articleLister->setArticleModel( newModel );
232  delete m_articleModel; //order is important: do not delete the old model before the new model is set in the view
233  m_articleModel = newModel;
234 
235  disconnect( m_articleLister->articleSelectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
236  this, SLOT(articleSelectionChanged()) );
237  connect( m_articleLister->articleSelectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
238  this, SLOT(articleSelectionChanged()) );
239 
240  if ( node )
241  m_articleLister->setScrollBarPositions( node->listViewScrollBarPositions() );
242 }
243 
244 
245 void Akregator::SelectionController::selectedSubscriptionChanged( const QModelIndex& index )
246 {
247  if ( !index.isValid() )
248  return;
249 
250  if ( m_selectedSubscription && m_articleLister )
251  m_selectedSubscription->setListViewScrollBarPositions( m_articleLister->scrollBarPositions() );
252 
253  m_selectedSubscription = selectedSubscription();
254  emit currentSubscriptionChanged( m_selectedSubscription );
255 
256  // using a timer here internally to simulate async data fetching (which is still synchronous),
257  // to ensure the UI copes with async behavior later on
258 
259  m_listJob->disconnect( this ); //Ignore if ~KJob() emits finished()
260  delete m_listJob;
261 
262  if ( !m_selectedSubscription )
263  return;
264 
265  ArticleListJob* const job( new ArticleListJob( m_selectedSubscription ) );
266  connect( job, SIGNAL(finished(KJob*)),
267  this, SLOT(articleHeadersAvailable(KJob*)) );
268  m_listJob = job;
269  m_listJob->start();
270 
271 }
272 
273 void Akregator::SelectionController::subscriptionContextMenuRequested( const QPoint& point )
274 {
275  Q_ASSERT( m_feedSelector );
276  const TreeNode* const node = ::subscriptionForIndex( m_feedSelector->indexAt( point ), m_feedList.get() );
277  if ( !node )
278  return;
279 
280  QWidget* w = ActionManager::getInstance()->container( node->isGroup() ? "feedgroup_popup" : "feeds_popup" );
281  QMenu* popup = qobject_cast<QMenu*>( w );
282  if ( popup )
283  {
284  const QPoint globalPos = m_feedSelector->viewport()->mapToGlobal( point );
285  popup->exec( globalPos );
286  }
287 }
288 
289 void Akregator::SelectionController::articleSelectionChanged()
290 {
291  const Akregator::Article article = currentArticle();
292  if ( m_singleDisplay )
293  m_singleDisplay->showArticle( article );
294  emit currentArticleChanged( article );
295 }
296 
297 void Akregator::SelectionController::articleIndexDoubleClicked( const QModelIndex& index )
298 {
299  const Akregator::Article article = ::articleForIndex( index, m_feedList.get() );
300  emit articleDoubleClicked( article );
301 }
302 
303 void SelectionController::setFilters( const std::vector<boost::shared_ptr<const Filters::AbstractMatcher> >& matchers )
304 {
305  Q_ASSERT( m_articleLister );
306  m_articleLister->setFilters( matchers );
307 }
308 
309 void SelectionController::forceFilterUpdate()
310 {
311  Q_ASSERT( m_articleLister );
312  m_articleLister->forceFilterUpdate();
313 }
314 
315 #include "selectioncontroller.moc"
treenode.h
Akregator::SelectionController::SelectionController
SelectionController(QObject *parent=0)
Definition: selectioncontroller.cpp:79
feedlist.h
Akregator::SelectionController::setFilters
void setFilters(const std::vector< boost::shared_ptr< const Akregator::Filters::AbstractMatcher > > &)
Definition: selectioncontroller.cpp:303
Akregator::SingleArticleDisplay
Definition: abstractselectioncontroller.h:75
Akregator::SelectionController::forceFilterUpdate
void forceFilterUpdate()
Definition: selectioncontroller.cpp:309
Akregator::ArticleLister::forceFilterUpdate
virtual void forceFilterUpdate()=0
Akregator::SelectionController::~SelectionController
~SelectionController()
Definition: selectioncontroller.cpp:92
QWidget
articlejobs.h
Akregator::SelectionController::selectedSubscription
Akregator::TreeNode * selectedSubscription() const
Definition: selectioncontroller.cpp:165
Akregator::TreeNode::isAggregation
virtual bool isAggregation() const =0
returns if the node represents an aggregation, i.e.
Akregator::SubscriptionListModel::SubscriptionIdRole
Definition: subscriptionlistmodel.h:46
Akregator::FeedList::findArticle
const Article findArticle(const QString &feedURL, const QString &guid) const
Definition: feedlist.cpp:337
Akregator::FolderExpansionHandler
Definition: subscriptionlistmodel.h:134
Akregator::ArticleLister::articleSelectionModel
virtual QItemSelectionModel * articleSelectionModel() const =0
Akregator::SubscriptionListModel
Definition: subscriptionlistmodel.h:40
actionmanager.h
QObject
Akregator::AbstractSelectionController
Definition: abstractselectioncontroller.h:92
Akregator::FeedList
The model of a feed tree, represents an OPML document.
Definition: feedlist.h:77
Akregator::Article::isNull
bool isNull() const
Definition: article.cpp:253
Akregator::SelectionController::setFolderExpansionHandler
void setFolderExpansionHandler(Akregator::FolderExpansionHandler *handler)
Definition: selectioncontroller.cpp:193
Akregator::ArticleListJob
Definition: articlejobs.h:108
Akregator::SelectionController::setArticleLister
void setArticleLister(Akregator::ArticleLister *lister)
Definition: selectioncontroller.cpp:124
Akregator::ActionManager::container
virtual QWidget * container(const char *name)=0
article.h
Akregator::FolderExpansionHandler::setFeedList
void setFeedList(const boost::shared_ptr< FeedList > &feedList)
Definition: subscriptionlistmodel.cpp:361
Akregator::SelectionController::currentArticle
Akregator::Article currentArticle() const
Definition: selectioncontroller.cpp:146
Akregator::FolderExpansionHandler::setModel
void setModel(Akregator::SubscriptionListModel *model)
Definition: subscriptionlistmodel.cpp:356
Akregator::ArticleLister
Definition: abstractselectioncontroller.h:50
Akregator::FeedList::findByID
const TreeNode * findByID(int id) const
Definition: feedlist.cpp:386
Akregator::SelectionController::currentArticleIndex
QModelIndex currentArticleIndex() const
Definition: selectioncontroller.cpp:153
selectioncontroller.h
Akregator::TreeNode::listViewScrollBarPositions
QPoint listViewScrollBarPositions() const
Definition: treenode.cpp:228
Akregator::ActionManager::getInstance
static ActionManager * getInstance()
Definition: actionmanager.cpp:35
Akregator::TreeNode::isGroup
virtual bool isGroup() const =0
Helps the rest of the app to decide if node should be handled as group or not.
articlemodel.h
Akregator::Article
A proxy class for Syndication::ItemPtr with some additional methods to assist sorting.
Definition: article.h:61
Akregator::SelectionController::selectedArticles
QList< Akregator::Article > selectedArticles() const
Definition: selectioncontroller.cpp:158
Akregator::SelectionController::setFeedList
void setFeedList(const boost::shared_ptr< FeedList > &list)
Definition: selectioncontroller.cpp:170
Akregator::SelectionController::setSingleArticleDisplay
void setSingleArticleDisplay(Akregator::SingleArticleDisplay *display)
Definition: selectioncontroller.cpp:141
Akregator::SelectionController::setFeedSelector
void setFeedSelector(QAbstractItemView *feedSelector)
Definition: selectioncontroller.cpp:98
subscriptionlistmodel.h
Akregator::TreeNode
Abstract base class for all kind of elements in the feed tree, like feeds and feed groups (and search...
Definition: treenode.h:59
KJob
Akregator::ArticleLister::setFilters
virtual void setFilters(const std::vector< boost::shared_ptr< const Filters::AbstractMatcher > > &)=0
Akregator::ArticleModel
Definition: articlemodel.h:44
QList< Akregator::Article >
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:14 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal