• 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
articlemodel.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 #include "articlemodel.h"
25 
26 #include "article.h"
27 #include "articlematcher.h"
28 #include "akregatorconfig.h"
29 #include "feed.h"
30 
31 #include <syndication/tools.h>
32 
33 #include <QMimeData>
34 #include <QString>
35 #include <QVector>
36 
37 #include <KLocale>
38 #include <KGlobal>
39 
40 #include <memory>
41 
42 #include <cassert>
43 #include <cmath>
44 
45 using namespace Akregator;
46 
47 class ArticleModel::Private {
48 private:
49  ArticleModel* const q;
50 public:
51  Private( const QList<Article>& articles, ArticleModel* qq );
52  QList<Article> articles;
53  QVector<QString> titleCache;
54 
55  void articlesAdded( const QList<Article>& );
56  void articlesRemoved( const QList<Article>& );
57  void articlesUpdated( const QList<Article>& );
58 
59 };
60 
61 //like Syndication::htmlToPlainText, but without linebreaks
62 
63 static QString stripHtml( const QString& html ) {
64  QString str(html);
65  //TODO: preserve some formatting, such as line breaks
66  str.remove(QRegExp(QLatin1String("<[^>]*>"))); // remove tags
67  str = Syndication::resolveEntities(str);
68  return str.simplified();
69 }
70 
71 ArticleModel::Private::Private( const QList<Article>& articles_, ArticleModel* qq )
72  : q( qq ), articles( articles_ )
73 {
74  titleCache.resize( articles.count() );
75  for ( int i = 0; i < articles.count(); ++i )
76  titleCache[i] = stripHtml( articles[i].title() );
77 }
78 
79 Akregator::ArticleModel::ArticleModel(const QList<Article>& articles, QObject* parent) : QAbstractTableModel( parent ), d( new Private( articles, this ) )
80 {
81 }
82 
83 Akregator::ArticleModel::~ArticleModel()
84 {
85  delete d;
86 }
87 
88 int Akregator::ArticleModel::columnCount( const QModelIndex& parent ) const
89 {
90  return parent.isValid() ? 0 : ColumnCount;
91 }
92 
93 int Akregator::ArticleModel::rowCount( const QModelIndex& parent ) const
94 {
95  return parent.isValid() ? 0 : d->articles.count();
96 }
97 
98 QVariant Akregator::ArticleModel::headerData( int section, Qt::Orientation, int role ) const
99 {
100  if ( role != Qt::DisplayRole )
101  return QVariant();
102 
103  switch (section)
104  {
105  case ItemTitleColumn:
106  return i18nc("Articlelist's column header", "Title");
107  case FeedTitleColumn:
108  return i18nc("Articlelist's column header", "Feed");
109  case DateColumn:
110  return i18nc("Articlelist's column header", "Date");
111  case AuthorColumn:
112  return i18nc("Articlelist's column header", "Author");
113  case DescriptionColumn:
114  return i18nc("Articlelist's column header", "Description");
115  case ContentColumn:
116  return i18nc("Articlelist's column header", "Content");
117  }
118 
119  return QVariant();
120 }
121 
122 QVariant Akregator::ArticleModel::data( const QModelIndex& index, int role ) const
123 {
124  if ( !index.isValid() || index.row() < 0 || index.row() >= d->articles.count() )
125  return QVariant();
126  const int row = index.row();
127  const Akregator::Article& article( d->articles[row] );
128 
129  if ( article.isNull() )
130  return QVariant();
131 
132  switch ( role )
133  {
134  case SortRole:
135  if ( index.column() == DateColumn )
136  return article.pubDate();
137  // no break
138  case Qt::DisplayRole:
139  {
140  switch ( index.column() )
141  {
142  case FeedTitleColumn:
143  return article.feed() ? article.feed()->title() : QVariant();
144  case DateColumn:
145  return KGlobal::locale()->formatDateTime(article.pubDate(),
146  KLocale::FancyShortDate );
147  case ItemTitleColumn:
148  return d->titleCache[row];
149  case AuthorColumn:
150  return article.authorShort();
151  case DescriptionColumn:
152  case ContentColumn:
153  return article.description();
154  }
155  }
156  case LinkRole:
157  {
158  return article.link();
159  }
160  case ItemIdRole:
161  case GuidRole:
162  {
163  return article.guid();
164  }
165  case FeedIdRole:
166  {
167  return article.feed() ? article.feed()->xmlUrl() : QVariant();
168  }
169  case StatusRole:
170  {
171  return article.status();
172  }
173  case IsImportantRole:
174  {
175  return article.keep();
176  }
177  case IsDeletedRole:
178  {
179  return article.isDeleted();
180  }
181  }
182 
183  return QVariant();
184 }
185 
186 void ArticleModel::clear()
187 {
188  d->articles.clear();
189  d->titleCache.clear();
190  reset();
191 }
192 
193 void ArticleModel::articlesAdded( TreeNode*, const QList<Article>& l ) {
194  d->articlesAdded( l );
195 }
196 
197 void ArticleModel::articlesRemoved( TreeNode*, const QList<Article>& l ) {
198  d->articlesRemoved( l );
199 }
200 void ArticleModel::articlesUpdated( TreeNode*, const QList<Article>& l ) {
201  d->articlesUpdated( l );
202 }
203 
204 void ArticleModel::Private::articlesAdded( const QList<Article>& list )
205 {
206  if ( list.isEmpty() ) //assert?
207  return;
208  const int first = static_cast<int>( articles.count() );
209  q->beginInsertRows( QModelIndex(), first, first + list.size() - 1 );
210 
211  const int oldSize = articles.size();
212  articles << list;
213  titleCache.resize( articles.count() );
214  for ( int i = oldSize; i < articles.count(); ++i )
215  titleCache[i] = stripHtml( articles[i].title() );
216  q->endInsertRows();
217 }
218 
219 void ArticleModel::Private::articlesRemoved( const QList<Article>& list )
220 {
221  //might want to avoid indexOf() in case of performance problems
222  Q_FOREACH ( const Article& i, list )
223  {
224  const int row = articles.indexOf( i );
225  assert( row != -1 );
226  q->removeRow( row, QModelIndex() );
227  }
228 }
229 
230 
231 void ArticleModel::Private::articlesUpdated( const QList<Article>& list )
232 {
233  int rmin = 0;
234  int rmax = 0;
235 
236  if ( articles.count() > 0 )
237  {
238  rmin = articles.count() - 1;
239  //might want to avoid indexOf() in case of performance problems
240  Q_FOREACH ( const Article& i, list )
241  {
242  const int row = articles.indexOf( i );
243  //TODO: figure out how why the Article might not be found in
244  //TODO: the articles list because we should need this conditional.
245  if ( row >= 0 )
246  {
247  titleCache[row] = stripHtml( articles[row].title() );
248  rmin = std::min( row, rmin );
249  rmax = std::max( row, rmax );
250  }
251  }
252  }
253  emit q->dataChanged( q->index( rmin, 0 ), q->index( rmax, ColumnCount-1 ) );
254 }
255 
256 
257 bool ArticleModel::rowMatches( int row, const boost::shared_ptr<const Akregator::Filters::AbstractMatcher>& matcher ) const
258 {
259  assert( matcher );
260  return matcher->matches( article( row ) );
261 }
262 
263 Article ArticleModel::article( int row ) const
264 {
265  if ( row < 0 || row >= d->articles.count() )
266  return Article();
267  return d->articles[row];
268 }
269 
270 QStringList ArticleModel::mimeTypes() const
271 {
272  return QStringList() << QString::fromLatin1( "text/uri-list" );
273 }
274 
275 QMimeData* ArticleModel::mimeData( const QModelIndexList& indexes ) const
276 {
277  std::auto_ptr<QMimeData> md( new QMimeData );
278  QList<QUrl> urls;
279  Q_FOREACH( const QModelIndex& i, indexes ) {
280  const QUrl url = i.data( ArticleModel::LinkRole ).value<KUrl>();
281  if ( url.isValid() )
282  urls.push_back( url );
283  else {
284  const QUrl guid( i.data( ArticleModel::GuidRole ).toString() );
285  if ( guid.isValid() )
286  urls.push_back( guid );
287  }
288  }
289  md->setUrls( urls );
290  return md.release();
291 }
292 
293 Qt::ItemFlags ArticleModel::flags( const QModelIndex& idx ) const
294 {
295  const Qt::ItemFlags f = QAbstractTableModel::flags( idx );
296  if ( !idx.isValid() )
297  return f;
298  return f | Qt::ItemIsDragEnabled;
299 }
300 
301 #include "articlemodel.moc"
Akregator::ArticleModel::~ArticleModel
~ArticleModel()
Definition: articlemodel.cpp:83
articlematcher.h
Akregator::ArticleModel::article
Article article(int row) const
Definition: articlemodel.cpp:263
Akregator::ArticleModel::mimeTypes
QStringList mimeTypes() const
Definition: articlemodel.cpp:270
Akregator::ArticleModel::mimeData
QMimeData * mimeData(const QModelIndexList &indexes) const
Definition: articlemodel.cpp:275
Akregator::Article::link
KUrl link() const
Definition: article.cpp:447
Akregator::TreeNode::title
QString title() const
Get title of node.
Definition: treenode.cpp:87
Akregator::ArticleModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: articlemodel.cpp:93
Akregator::ArticleModel::flags
Qt::ItemFlags flags(const QModelIndex &idx) const
Definition: articlemodel.cpp:293
Akregator::ArticleModel::ArticleModel
ArticleModel(const QList< Article > &articles, QObject *parent=0)
Definition: articlemodel.cpp:79
QObject
feed.h
Akregator::Article::feed
Feed * feed() const
Definition: article.cpp:508
Akregator::ArticleModel::headerData
QVariant headerData(int section, Qt::Orientation, int role) const
Definition: articlemodel.cpp:98
Akregator::Article::isNull
bool isNull() const
Definition: article.cpp:253
Akregator::ArticleModel::GuidRole
Definition: articlemodel.h:63
Akregator::ArticleModel::clear
void clear()
Definition: articlemodel.cpp:186
akregatorconfig.h
Akregator::Article::keep
bool keep() const
if true, the article should be kept even when expired
Definition: article.cpp:495
stripHtml
static QString stripHtml(const QString &html)
Definition: articlemodel.cpp:63
Akregator::Feed::xmlUrl
QString xmlUrl() const
returns the url of the actual feed source (rss/rdf/atom file)
Definition: feed.cpp:374
article.h
Akregator::Article::isDeleted
bool isDeleted() const
Definition: article.cpp:279
Akregator::Article::guid
QString guid() const
Definition: article.cpp:463
Akregator::ArticleModel::LinkRole
Definition: articlemodel.h:62
Akregator::ArticleModel::rowMatches
bool rowMatches(int row, const boost::shared_ptr< const Akregator::Filters::AbstractMatcher > &matcher) const
Definition: articlemodel.cpp:257
Akregator::ArticleModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const
Definition: articlemodel.cpp:88
Akregator::Article::pubDate
QDateTime pubDate() const
Definition: article.cpp:511
Akregator::Article::description
QString description() const
Definition: article.cpp:452
Akregator::ArticleModel::articlesAdded
void articlesAdded(Akregator::TreeNode *, const QList< Akregator::Article > &)
Definition: articlemodel.cpp:193
Akregator::Article::authorShort
QString authorShort() const
Definition: article.cpp:410
articlemodel.h
Akregator::ArticleModel::articlesUpdated
void articlesUpdated(Akregator::TreeNode *, const QList< Akregator::Article > &)
Definition: articlemodel.cpp:200
Akregator::Article
A proxy class for Syndication::ItemPtr with some additional methods to assist sorting.
Definition: article.h:61
Akregator::Article::status
int status() const
Definition: article.cpp:338
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
Akregator::ArticleModel
Definition: articlemodel.h:44
QAbstractTableModel
Akregator::ArticleModel::articlesRemoved
void articlesRemoved(Akregator::TreeNode *, const QList< Akregator::Article > &)
Definition: articlemodel.cpp:197
QList
Definition: article.h:39
Akregator::ArticleModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Definition: articlemodel.cpp:122
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