cmake head does not like kde4_add_library and kde4_add_plugin together... hope kde4_a...
[kdenetwork.git] / knewsticker / knewsticker.cpp
blobfd3d3c1a8acf6596faa55aa5d053694e0e096ac5
1 /*
2 * knewsticker.cpp
4 * Copyright (c) 2000, 2001, 2007 Frerich Raabe <raabe@kde.org>
6 * This program is distributed in the hope that it will be useful, but WITHOUT
7 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
9 * accompanying file 'COPYING'.
11 #include "knewsticker.h"
12 #include "feedsettingswidget.h"
13 #include "newsfeedmanager.h"
14 #include "settings.h"
15 #include "ui_visualsettings.h"
16 #include "itemviews.h"
18 #include <kconfigdialog.h>
19 #include <kiconloader.h>
20 #include <kmimetype.h>
21 #include <syndication/item.h>
23 #include <QDesktopServices>
24 #include <QGraphicsSceneContextMenuEvent>
25 #include <QMenu>
26 #include <QMessageBox>
27 #include <QSignalMapper>
28 #include <QTimer>
30 using namespace Syndication;
32 static QString unescape( const QString &s )
34 QString t = s;
35 t.replace( QLatin1String( "&amp;" ), QLatin1String( "&" ) );
36 t.replace( QLatin1String( "&quot;" ), QLatin1String( "'" ) );
37 t.replace( QLatin1String( "&apos;" ), QLatin1String( "\"" ) );
38 t.replace( QLatin1String( "&lt;" ), QLatin1String( "<" ) );
39 t.replace( QLatin1String( "&gt;" ), QLatin1String( ">" ) );
40 return t;
43 KNewsTicker::KNewsTicker( QObject *parent, const QVariantList &args )
44 : Plasma::Applet( parent, args ),
45 m_signalMapper( 0 ),
46 m_itemView( 0 )
48 setDrawStandardBackground( true );
50 setupItemView();
51 connect( NewsFeedManager::self(), SIGNAL( feedLoaded( const QUrl & ) ),
52 this, SLOT( feedLoaded( const QUrl & ) ) );
53 connect( NewsFeedManager::self(), SIGNAL( updateFinished() ),
54 this, SLOT( feedUpdateFinished() ) );
56 NewsFeedManager::self()->setSubscriptions( Settings::feedUrls() );
58 m_updateTimer = new QTimer( this );
59 connect( m_updateTimer, SIGNAL( timeout() ),
60 this, SLOT( updateFeeds() ) );
61 m_updateTimer->start( Settings::updateInterval() * 60 * 1000 );
63 setHasConfigurationInterface( true );
65 updateFeeds();
68 void KNewsTicker::showConfigurationInterface()
70 KConfigDialog dlg( 0, "settings", Settings::self() );
71 connect( &dlg, SIGNAL( settingsChanged( const QString & ) ),
72 this, SLOT( settingsChanged( const QString & ) ) );
73 dlg.setFaceType( KPageDialog::Tabbed );
75 QWidget *page = new QWidget( 0 );
77 Ui::VisualSettings ui;
78 ui.setupUi( page );
80 dlg.addPage( page, i18n( "Appearance" ) );
82 FeedSettingsWidget *feedSettingsWidget = new FeedSettingsWidget( 0 );
83 dlg.addPage( feedSettingsWidget, i18n( "Feed Access" ) );
85 QFont origFont = Settings::font();
86 const QStringList origFeedUrls = Settings::feedUrls();
88 if ( dlg.exec() == QDialog::Accepted ) {
89 Settings::setFeedUrls( feedSettingsWidget->feedUrls() );
91 if ( Settings::feedUrls() != origFeedUrls ) {
92 NewsFeedManager::self()->setSubscriptions( Settings::feedUrls() );
93 updateFeeds();
96 reloadSettings();
100 void KNewsTicker::settingsChanged( const QString & /* dialogName */ )
102 reloadSettings();
105 QSizeF KNewsTicker::contentSizeHint() const
107 return m_itemView->boundingRect().size();
110 QList<QAction *> KNewsTicker::contextActions()
112 QList<QAction *> actions;
114 delete m_signalMapper;
115 m_signalMapper = new QSignalMapper( this );
116 connect( m_signalMapper, SIGNAL( mapped( const QString & ) ),
117 this, SLOT( openFeedItem( const QString & ) ) );
119 QList<FeedPtr> availableFeeds = NewsFeedManager::self()->availableFeeds().values();
120 foreach ( FeedPtr feed, availableFeeds ) {
121 QMenu *feedMenu = new QMenu;
122 QList<ItemPtr> items = feed->items();
123 foreach ( ItemPtr item, items ) {
124 QString title = unescape( item->title() );
125 title.replace( "&", "&amp;" );
126 QAction *itemAction = feedMenu->addAction( title,
127 m_signalMapper, SLOT( map() ) );
129 m_signalMapper->setMapping( itemAction, item->link() );
132 QAction *feedAction = new QAction( feed->title(), 0 );
133 const QString favIcon = KMimeType::favIconForUrl( feed->link() );
134 if ( !favIcon.isEmpty() ) {
135 feedAction->setIcon( SmallIcon( favIcon ) );
137 feedAction->setMenu( feedMenu );
138 actions.append( feedAction );
141 return actions;
144 bool KNewsTicker::hideArticle( const QUrl &url )
146 return Settings::hideReadArticles() && m_readArticles.contains( url );
149 void KNewsTicker::feedLoaded( const QUrl &url )
151 FeedPtr feed = NewsFeedManager::self()->availableFeeds()[ url ];
152 foreach ( ItemPtr item, feed->items() ) {
153 NewsItem i;
154 i.text = unescape( item->title() );
155 i.url = item->link();
156 i.description = unescape( item->description() );
157 m_items.append( i );
161 void KNewsTicker::feedUpdateFinished()
163 /* Filter out unneded entries in our m_readArticles set; first find out
164 * which URLs are shown after the update. Then, create a new list of read
165 * articles in which only those articles get added which are available
166 * and read.
168 QSet<QUrl> allUrls;
169 foreach ( const NewsItem &item, m_items ) {
170 allUrls.insert( item.url );
173 QSet<QUrl> activeReadArticles;
174 foreach ( const QUrl &readUrl, m_readArticles ) {
175 if ( allUrls.contains( readUrl ) ) {
176 activeReadArticles.insert( readUrl );
179 m_readArticles = activeReadArticles;
181 m_itemView->setItems( m_items );
184 void KNewsTicker::updateFeeds()
186 m_items.clear();
187 NewsFeedManager::self()->update();
190 void KNewsTicker::openFeedItem( const QString &url )
192 QDesktopServices::openUrl( url );
193 if ( !m_readArticles.contains( url ) ) {
194 m_readArticles.insert( url );
198 void KNewsTicker::reloadSettings()
200 setupItemView();
201 m_updateTimer->setInterval( Settings::updateInterval() * 60 * 1000 );
204 void KNewsTicker::setupItemView()
206 delete m_itemView;
207 switch ( Settings::displayStyle() ) {
208 case Settings::EnumDisplayStyle::ScrollingText:
209 m_itemView = new ScrollingItemView( this );
210 break;
211 case Settings::EnumDisplayStyle::PagedText:
212 m_itemView = new PagingItemView( this );
213 break;
214 case Settings::EnumDisplayStyle::COUNT:
215 // Just used internally by KConfigXT
216 break;
218 connect( m_itemView, SIGNAL( itemActivated( const QString & ) ),
219 this, SLOT( openFeedItem( const QString & ) ) );
220 m_itemView->setRect( 0, 0, 512, QFontMetrics( Settings::font() ).height() * 2 );
221 m_itemView->reloadSettings();
222 m_itemView->setItems( m_items );
225 K_EXPORT_PLASMA_APPLET(knewsticker, KNewsTicker)
227 #include "knewsticker.moc"