00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qclipboard.h>
00025 #include <qeventloop.h>
00026 #include <qhbox.h>
00027 #include <qlayout.h>
00028 #include <qpixmap.h>
00029 #include <qpopupmenu.h>
00030 #include <qcursor.h>
00031
00032 #include <dcopclient.h>
00033 #include <kapplication.h>
00034 #include <kcharsets.h>
00035 #include <kconfig.h>
00036 #include <kdebug.h>
00037 #include <kglobal.h>
00038 #include <kiconloader.h>
00039 #include <klocale.h>
00040 #include <kurllabel.h>
00041
00042 #include "summarywidget.h"
00043
00044 SummaryWidget::SummaryWidget( QWidget *parent, const char *name )
00045 : Kontact::Summary( parent, name ),
00046 DCOPObject( "NewsTickerPlugin" ), mLayout( 0 ), mFeedCounter( 0 )
00047 {
00048 QVBoxLayout *vlay = new QVBoxLayout( this, 3, 3 );
00049
00050 QPixmap icon = KGlobal::iconLoader()->loadIcon( "kontact_news",
00051 KIcon::Desktop, KIcon::SizeMedium );
00052
00053 QWidget *header = createHeader( this, icon, i18n( "News Feeds" ) );
00054 vlay->addWidget( header );
00055
00056 QString error;
00057 QCString appID;
00058
00059 bool dcopAvailable = true;
00060 if ( !kapp->dcopClient()->isApplicationRegistered( "rssservice" ) ) {
00061 if ( KApplication::startServiceByDesktopName( "rssservice", QStringList(), &error, &appID ) ) {
00062 QLabel *label = new QLabel( i18n( "No rss dcop service available.\nYou need rssservice to use this plugin." ), this );
00063 vlay->addWidget( label, Qt::AlignHCenter );
00064 dcopAvailable = false;
00065 }
00066 }
00067
00068 mBaseWidget = new QWidget( this, "baseWidget" );
00069 vlay->addWidget( mBaseWidget );
00070
00071 connect( &mTimer, SIGNAL( timeout() ), this, SLOT( updateDocuments() ) );
00072
00073 readConfig();
00074
00075 connectDCOPSignal( 0, 0, "documentUpdateError(DCOPRef,int)", "documentUpdateError(DCOPRef, int)", false );
00076
00077 if ( dcopAvailable )
00078 initDocuments();
00079
00080 connectDCOPSignal( 0, 0, "added(QString)", "documentAdded(QString)", false );
00081 connectDCOPSignal( 0, 0, "removed(QString)", "documentRemoved(QString)", false );
00082 }
00083
00084 int SummaryWidget::summaryHeight() const
00085 {
00086 return ( mFeeds.count() == 0 ? 1 : mFeeds.count() );
00087 }
00088
00089 void SummaryWidget::documentAdded( QString )
00090 {
00091 initDocuments();
00092 }
00093
00094 void SummaryWidget::documentRemoved( QString )
00095 {
00096 initDocuments();
00097 }
00098
00099 void SummaryWidget::configChanged()
00100 {
00101 readConfig();
00102
00103 updateView();
00104 }
00105
00106 void SummaryWidget::readConfig()
00107 {
00108 KConfig config( "kcmkontactkntrc" );
00109 config.setGroup( "General" );
00110
00111 mUpdateInterval = config.readNumEntry( "UpdateInterval", 600 );
00112 mArticleCount = config.readNumEntry( "ArticleCount", 4 );
00113 }
00114
00115 void SummaryWidget::initDocuments()
00116 {
00117 mFeeds.clear();
00118
00119 DCOPRef dcopCall( "rssservice", "RSSService" );
00120 QStringList urls;
00121 dcopCall.call( "list()" ).get( urls );
00122
00123 if ( urls.isEmpty() ) {
00124 urls.append( "http://www.kde.org/dotkdeorg.rdf" );
00125 dcopCall.send( "add(QString)", urls[ 0 ] );
00126 }
00127
00128 QStringList::Iterator it;
00129 for ( it = urls.begin(); it != urls.end(); ++it ) {
00130 DCOPRef feedRef = dcopCall.call( "document(QString)", *it );
00131
00132 Feed feed;
00133 feed.ref = feedRef;
00134 feedRef.call( "title()" ).get( feed.title );
00135 feedRef.call( "link()" ).get( feed.url );
00136 feedRef.call( "pixmap()" ).get( feed.logo );
00137 mFeeds.append( feed );
00138
00139 disconnectDCOPSignal( "rssservice", feedRef.obj(), "documentUpdated(DCOPRef)", 0 );
00140 connectDCOPSignal( "rssservice", feedRef.obj(), "documentUpdated(DCOPRef)",
00141 "documentUpdated(DCOPRef)", false );
00142
00143 qApp->processEvents( QEventLoop::ExcludeUserInput |
00144 QEventLoop::ExcludeSocketNotifiers );
00145 }
00146
00147 updateDocuments();
00148 }
00149
00150 void SummaryWidget::updateDocuments()
00151 {
00152 mTimer.stop();
00153
00154 FeedList::Iterator it;
00155 for ( it = mFeeds.begin(); it != mFeeds.end(); ++it )
00156 (*it).ref.send( "refresh()" );
00157
00158 mTimer.start( 1000 * mUpdateInterval );
00159 }
00160
00161 void SummaryWidget::documentUpdated( DCOPRef feedRef )
00162 {
00163 ArticleMap map;
00164
00165 int numArticles = feedRef.call( "count()" );
00166 for ( int i = 0; i < numArticles; ++i ) {
00167 DCOPRef artRef = feedRef.call( "article(int)", i );
00168 QString title, url;
00169
00170 qApp->processEvents( QEventLoop::ExcludeUserInput |
00171 QEventLoop::ExcludeSocketNotifiers );
00172
00173 artRef.call( "title()" ).get( title );
00174 artRef.call( "link()" ).get( url );
00175
00176 QPair<QString, KURL> article(title, KURL( url ));
00177 map.append( article );
00178 }
00179
00180 FeedList::Iterator it;
00181 for ( it = mFeeds.begin(); it != mFeeds.end(); ++it )
00182 if ( (*it).ref.obj() == feedRef.obj() ) {
00183 (*it).map = map;
00184 if ( (*it).title.isEmpty() )
00185 feedRef.call( "title()" ).get( (*it).title );
00186 if ( (*it).url.isEmpty() )
00187 feedRef.call( "link()" ).get( (*it).url );
00188 if ( (*it).logo.isNull() )
00189 feedRef.call( "pixmap()" ).get( (*it).logo );
00190 }
00191
00192 mFeedCounter++;
00193 if ( mFeedCounter == mFeeds.count() ) {
00194 mFeedCounter = 0;
00195 updateView();
00196 }
00197 }
00198
00199 void SummaryWidget::updateView()
00200 {
00201 mLabels.setAutoDelete( true );
00202 mLabels.clear();
00203 mLabels.setAutoDelete( false );
00204
00205 delete mLayout;
00206 mLayout = new QVBoxLayout( mBaseWidget, 3 );
00207
00208 QFont boldFont;
00209 boldFont.setBold( true );
00210 boldFont.setPointSize( boldFont.pointSize() + 2 );
00211
00212 FeedList::Iterator it;
00213 for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) {
00214 QHBox *hbox = new QHBox( mBaseWidget );
00215 mLayout->addWidget( hbox );
00216
00217
00218 KURLLabel *urlLabel = new KURLLabel( hbox );
00219 urlLabel->setURL( (*it).url );
00220 urlLabel->setPixmap( (*it).logo );
00221 urlLabel->setMaximumSize( urlLabel->minimumSizeHint() );
00222 mLabels.append( urlLabel );
00223
00224 connect( urlLabel, SIGNAL( leftClickedURL( const QString& ) ),
00225 kapp, SLOT( invokeBrowser( const QString& ) ) );
00226 connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ),
00227 this, SLOT( rmbMenu( const QString& ) ) );
00228
00229
00230 QLabel *label = new QLabel( hbox );
00231 label->setText( KCharsets::resolveEntities( (*it).title ) );
00232 label->setAlignment( AlignLeft|AlignVCenter );
00233 label->setFont( boldFont );
00234 label->setIndent( 6 );
00235 label->setMaximumSize( label->minimumSizeHint() );
00236 mLabels.append( label );
00237
00238 hbox->setMaximumWidth( hbox->minimumSizeHint().width() );
00239 hbox->show();
00240
00241
00242 ArticleMap articles = (*it).map;
00243 ArticleMap::Iterator artIt;
00244 int numArticles = 0;
00245 for ( artIt = articles.begin(); artIt != articles.end() && numArticles < mArticleCount; ++artIt ) {
00246 urlLabel = new KURLLabel( (*artIt).second.url(), (*artIt).first, mBaseWidget );
00247 urlLabel->setTextFormat( RichText );
00248 mLabels.append( urlLabel );
00249 mLayout->addWidget( urlLabel );
00250
00251 connect( urlLabel, SIGNAL( leftClickedURL( const QString& ) ),
00252 kapp, SLOT( invokeBrowser( const QString& ) ) );
00253 connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ),
00254 this, SLOT( rmbMenu( const QString& ) ) );
00255
00256
00257 numArticles++;
00258 }
00259 }
00260
00261 for ( QLabel *label = mLabels.first(); label; label = mLabels.next() )
00262 label->show();
00263 }
00264
00265 void SummaryWidget::documentUpdateError( DCOPRef feedRef, int errorCode )
00266 {
00267 kdDebug() << " error while updating document, error code: " << errorCode << endl;
00268 FeedList::Iterator it;
00269 for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) {
00270 if ( (*it).ref.obj() == feedRef.obj() ) {
00271 mFeeds.remove( it );
00272 break;
00273 }
00274 }
00275
00276 if ( mFeedCounter == mFeeds.count() ) {
00277 mFeedCounter = 0;
00278 updateView();
00279 }
00280
00281 }
00282
00283 QStringList SummaryWidget::configModules() const
00284 {
00285 return "kcmkontactknt.desktop";
00286 }
00287
00288 void SummaryWidget::updateSummary( bool )
00289 {
00290 updateDocuments();
00291 }
00292
00293 void SummaryWidget::rmbMenu( const QString& url )
00294 {
00295 QPopupMenu menu;
00296 menu.insertItem( i18n( "Copy URL to Clipboard" ) );
00297 int id = menu.exec( QCursor::pos() );
00298 if ( id != -1 )
00299 kapp->clipboard()->setText( url, QClipboard::Clipboard );
00300 }
00301
00302 #include "summarywidget.moc"