/* This file is part of Kontact. Copyright (c) 2003 Tobias Koenig This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "summarywidget.h" SummaryWidget::SummaryWidget( TQWidget *parent, const char *name ) : Kontact::Summary( parent, name ), DCOPObject( "NewsTickerPlugin" ), mLayout( 0 ), mFeedCounter( 0 ) { TQVBoxLayout *vlay = new TQVBoxLayout( this, 3, 3 ); TQPixmap icon = TDEGlobal::iconLoader()->loadIcon( "kontact_news", TDEIcon::Desktop, TDEIcon::SizeMedium ); TQWidget *header = createHeader( this, icon, i18n( "News Feeds" ) ); vlay->addWidget( header ); TQString error; TQCString appID; bool dcopAvailable = true; if ( !kapp->dcopClient()->isApplicationRegistered( "rssservice" ) ) { if ( TDEApplication::startServiceByDesktopName( "rssservice", TQStringList(), &error, &appID ) ) { TQLabel *label = new TQLabel( i18n( "No rss dcop service available.\nYou need rssservice to use this plugin." ), this ); vlay->addWidget( label, TQt::AlignHCenter ); dcopAvailable = false; } } mBaseWidget = new TQWidget( this, "baseWidget" ); vlay->addWidget( mBaseWidget ); connect( &mTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( updateDocuments() ) ); readConfig(); connectDCOPSignal( 0, 0, "documentUpdateError(DCOPRef,int)", "documentUpdateError(DCOPRef, int)", false ); if ( dcopAvailable ) initDocuments(); connectDCOPSignal( 0, 0, "added(TQString)", "documentAdded(TQString)", false ); connectDCOPSignal( 0, 0, "removed(TQString)", "documentRemoved(TQString)", false ); } int SummaryWidget::summaryHeight() const { return ( mFeeds.count() == 0 ? 1 : mFeeds.count() ); } void SummaryWidget::documentAdded( TQString ) { initDocuments(); } void SummaryWidget::documentRemoved( TQString ) { initDocuments(); } void SummaryWidget::configChanged() { readConfig(); updateView(); } void SummaryWidget::readConfig() { TDEConfig config( "kcmkontactkntrc" ); config.setGroup( "General" ); mUpdateInterval = config.readNumEntry( "UpdateInterval", 600 ); mArticleCount = config.readNumEntry( "ArticleCount", 4 ); } void SummaryWidget::initDocuments() { mFeeds.clear(); DCOPRef dcopCall( "rssservice", "RSSService" ); TQStringList urls; dcopCall.call( "list()" ).get( urls ); if ( urls.isEmpty() ) { // add default urls.append( "http://www.kde.org/dotkdeorg.rdf" ); dcopCall.send( "add(TQString)", urls[ 0 ] ); } TQStringList::Iterator it; for ( it = urls.begin(); it != urls.end(); ++it ) { DCOPRef feedRef = dcopCall.call( "document(TQString)", *it ); Feed feed; feed.ref = feedRef; feedRef.call( "title()" ).get( feed.title ); feedRef.call( "link()" ).get( feed.url ); feedRef.call( "pixmap()" ).get( feed.logo ); mFeeds.append( feed ); disconnectDCOPSignal( "rssservice", feedRef.obj(), "documentUpdated(DCOPRef)", 0 ); connectDCOPSignal( "rssservice", feedRef.obj(), "documentUpdated(DCOPRef)", "documentUpdated(DCOPRef)", false ); if ( tqApp ) tqApp->eventLoop()->processEvents( TQEventLoop::ExcludeUserInput | TQEventLoop::ExcludeSocketNotifiers ); } updateDocuments(); } void SummaryWidget::updateDocuments() { mTimer.stop(); FeedList::Iterator it; for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) (*it).ref.send( "refresh()" ); mTimer.start( 1000 * mUpdateInterval ); } void SummaryWidget::documentUpdated( DCOPRef feedRef ) { ArticleMap map; int numArticles = feedRef.call( "count()" ); for ( int i = 0; i < numArticles; ++i ) { DCOPRef artRef = feedRef.call( "article(int)", i ); TQString title, url; if ( tqApp ) tqApp->eventLoop()->processEvents( TQEventLoop::ExcludeUserInput | TQEventLoop::ExcludeSocketNotifiers ); artRef.call( "title()" ).get( title ); artRef.call( "link()" ).get( url ); TQPair article(title, KURL( url )); map.append( article ); } FeedList::Iterator it; for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) if ( (*it).ref.obj() == feedRef.obj() ) { (*it).map = map; if ( (*it).title.isEmpty() ) feedRef.call( "title()" ).get( (*it).title ); if ( (*it).url.isEmpty() ) feedRef.call( "link()" ).get( (*it).url ); if ( (*it).logo.isNull() ) feedRef.call( "pixmap()" ).get( (*it).logo ); } mFeedCounter++; if ( mFeedCounter == mFeeds.count() ) { mFeedCounter = 0; updateView(); } } void SummaryWidget::updateView() { mLabels.setAutoDelete( true ); mLabels.clear(); mLabels.setAutoDelete( false ); delete mLayout; mLayout = new TQVBoxLayout( mBaseWidget, 3 ); TQFont boldFont; boldFont.setBold( true ); boldFont.setPointSize( boldFont.pointSize() + 2 ); FeedList::Iterator it; for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) { TQHBox *hbox = new TQHBox( mBaseWidget ); mLayout->addWidget( hbox ); // icon KURLLabel *urlLabel = new KURLLabel( hbox ); urlLabel->setURL( (*it).url ); urlLabel->setPixmap( (*it).logo ); urlLabel->setMaximumSize( urlLabel->minimumSizeHint() ); mLabels.append( urlLabel ); connect( urlLabel, TQ_SIGNAL( leftClickedURL( const TQString& ) ), kapp, TQ_SLOT( invokeBrowser( const TQString& ) ) ); connect( urlLabel, TQ_SIGNAL( rightClickedURL( const TQString& ) ), this, TQ_SLOT( rmbMenu( const TQString& ) ) ); // header TQLabel *label = new TQLabel( hbox ); label->setText( KCharsets::resolveEntities( (*it).title ) ); label->setAlignment( AlignLeft|AlignVCenter ); label->setFont( boldFont ); label->setIndent( 6 ); label->setMaximumSize( label->minimumSizeHint() ); mLabels.append( label ); hbox->setMaximumWidth( hbox->minimumSizeHint().width() ); hbox->show(); // articles ArticleMap articles = (*it).map; ArticleMap::Iterator artIt; int numArticles = 0; for ( artIt = articles.begin(); artIt != articles.end() && numArticles < mArticleCount; ++artIt ) { urlLabel = new KURLLabel( (*artIt).second.url(), (*artIt).first, mBaseWidget ); urlLabel->installEventFilter( this ); //TODO: RichText causes too much horizontal space between articles //urlLabel->setTextFormat( RichText ); mLabels.append( urlLabel ); mLayout->addWidget( urlLabel ); connect( urlLabel, TQ_SIGNAL( leftClickedURL( const TQString& ) ), kapp, TQ_SLOT( invokeBrowser( const TQString& ) ) ); connect( urlLabel, TQ_SIGNAL( rightClickedURL( const TQString& ) ), this, TQ_SLOT( rmbMenu( const TQString& ) ) ); numArticles++; } } for ( TQLabel *label = mLabels.first(); label; label = mLabels.next() ) label->show(); } void SummaryWidget::documentUpdateError( DCOPRef feedRef, int errorCode ) { kdDebug() << " error while updating document, error code: " << errorCode << endl; FeedList::Iterator it; for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) { if ( (*it).ref.obj() == feedRef.obj() ) { mFeeds.remove( it ); break; } } if ( mFeedCounter == mFeeds.count() ) { mFeedCounter = 0; updateView(); } } TQStringList SummaryWidget::configModules() const { return "kcmkontactknt.desktop"; } void SummaryWidget::updateSummary( bool ) { updateDocuments(); } void SummaryWidget::rmbMenu( const TQString& url ) { TQPopupMenu menu; menu.insertItem( i18n( "Copy URL to Clipboard" ) ); int id = menu.exec( TQCursor::pos() ); if ( id != -1 ) kapp->clipboard()->setText( url, TQClipboard::Clipboard ); } bool SummaryWidget::eventFilter( TQObject *obj, TQEvent* e ) { if ( obj->inherits( "KURLLabel" ) ) { KURLLabel* label = static_cast( obj ); if ( e->type() == TQEvent::Enter ) emit message( label->url() ); if ( e->type() == TQEvent::Leave ) emit message( TQString() ); } return Kontact::Summary::eventFilter( obj, e ); } #include "summarywidget.moc"