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

akregator

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

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