diff options
Diffstat (limited to 'kontact/plugins/newsticker/summarywidget.cpp')
-rw-r--r-- | kontact/plugins/newsticker/summarywidget.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/kontact/plugins/newsticker/summarywidget.cpp b/kontact/plugins/newsticker/summarywidget.cpp new file mode 100644 index 000000000..14b7bc27a --- /dev/null +++ b/kontact/plugins/newsticker/summarywidget.cpp @@ -0,0 +1,319 @@ +/* + This file is part of Kontact. + Copyright (c) 2003 Tobias Koenig <[email protected]> + + 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 Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qclipboard.h> +#include <qeventloop.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qpopupmenu.h> +#include <qcursor.h> + +#include <dcopclient.h> +#include <kapplication.h> +#include <kcharsets.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kurllabel.h> + +#include "summarywidget.h" + +SummaryWidget::SummaryWidget( QWidget *parent, const char *name ) + : Kontact::Summary( parent, name ), + DCOPObject( "NewsTickerPlugin" ), mLayout( 0 ), mFeedCounter( 0 ) +{ + QVBoxLayout *vlay = new QVBoxLayout( this, 3, 3 ); + + QPixmap icon = KGlobal::iconLoader()->loadIcon( "kontact_news", + KIcon::Desktop, KIcon::SizeMedium ); + + QWidget *header = createHeader( this, icon, i18n( "News Feeds" ) ); + vlay->addWidget( header ); + + QString error; + QCString appID; + + bool dcopAvailable = true; + if ( !kapp->dcopClient()->isApplicationRegistered( "rssservice" ) ) { + if ( KApplication::startServiceByDesktopName( "rssservice", QStringList(), &error, &appID ) ) { + QLabel *label = new QLabel( i18n( "No rss dcop service available.\nYou need rssservice to use this plugin." ), this ); + vlay->addWidget( label, Qt::AlignHCenter ); + dcopAvailable = false; + } + } + + mBaseWidget = new QWidget( this, "baseWidget" ); + vlay->addWidget( mBaseWidget ); + + connect( &mTimer, SIGNAL( timeout() ), this, SLOT( updateDocuments() ) ); + + readConfig(); + + connectDCOPSignal( 0, 0, "documentUpdateError(DCOPRef,int)", "documentUpdateError(DCOPRef, int)", false ); + + if ( dcopAvailable ) + initDocuments(); + + connectDCOPSignal( 0, 0, "added(QString)", "documentAdded(QString)", false ); + connectDCOPSignal( 0, 0, "removed(QString)", "documentRemoved(QString)", false ); +} + +int SummaryWidget::summaryHeight() const +{ + return ( mFeeds.count() == 0 ? 1 : mFeeds.count() ); +} + +void SummaryWidget::documentAdded( QString ) +{ + initDocuments(); +} + +void SummaryWidget::documentRemoved( QString ) +{ + initDocuments(); +} + +void SummaryWidget::configChanged() +{ + readConfig(); + + updateView(); +} + +void SummaryWidget::readConfig() +{ + KConfig config( "kcmkontactkntrc" ); + config.setGroup( "General" ); + + mUpdateInterval = config.readNumEntry( "UpdateInterval", 600 ); + mArticleCount = config.readNumEntry( "ArticleCount", 4 ); +} + +void SummaryWidget::initDocuments() +{ + mFeeds.clear(); + + DCOPRef dcopCall( "rssservice", "RSSService" ); + QStringList urls; + dcopCall.call( "list()" ).get( urls ); + + if ( urls.isEmpty() ) { // add default + urls.append( "http://www.kde.org/dotkdeorg.rdf" ); + dcopCall.send( "add(QString)", urls[ 0 ] ); + } + + QStringList::Iterator it; + for ( it = urls.begin(); it != urls.end(); ++it ) { + DCOPRef feedRef = dcopCall.call( "document(QString)", *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 ( qApp ) + qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput | + QEventLoop::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 ); + QString title, url; + + if ( qApp ) + qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput | + QEventLoop::ExcludeSocketNotifiers ); + + artRef.call( "title()" ).get( title ); + artRef.call( "link()" ).get( url ); + + QPair<QString, KURL> 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 QVBoxLayout( mBaseWidget, 3 ); + + QFont boldFont; + boldFont.setBold( true ); + boldFont.setPointSize( boldFont.pointSize() + 2 ); + + FeedList::Iterator it; + for ( it = mFeeds.begin(); it != mFeeds.end(); ++it ) { + QHBox *hbox = new QHBox( 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, SIGNAL( leftClickedURL( const QString& ) ), + kapp, SLOT( invokeBrowser( const QString& ) ) ); + connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ), + this, SLOT( rmbMenu( const QString& ) ) ); + + // header + QLabel *label = new QLabel( 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, SIGNAL( leftClickedURL( const QString& ) ), + kapp, SLOT( invokeBrowser( const QString& ) ) ); + connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ), + this, SLOT( rmbMenu( const QString& ) ) ); + + + numArticles++; + } + } + + for ( QLabel *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(); + } + +} + +QStringList SummaryWidget::configModules() const +{ + return "kcmkontactknt.desktop"; +} + +void SummaryWidget::updateSummary( bool ) +{ + updateDocuments(); +} + +void SummaryWidget::rmbMenu( const QString& url ) +{ + QPopupMenu menu; + menu.insertItem( i18n( "Copy URL to Clipboard" ) ); + int id = menu.exec( QCursor::pos() ); + if ( id != -1 ) + kapp->clipboard()->setText( url, QClipboard::Clipboard ); +} + +bool SummaryWidget::eventFilter( QObject *obj, QEvent* e ) +{ + if ( obj->inherits( "KURLLabel" ) ) { + KURLLabel* label = static_cast<KURLLabel*>( obj ); + if ( e->type() == QEvent::Enter ) + emit message( label->url() ); + if ( e->type() == QEvent::Leave ) + emit message( QString::null ); + } + + return Kontact::Summary::eventFilter( obj, e ); +} + +#include "summarywidget.moc" |