kcmkontactknt.cpp
00001 /* 00002 This file is part of Kontact. 00003 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 00019 As a special exception, permission is given to link this program 00020 with any edition of TQt, and distribute the resulting executable, 00021 without including the source code for TQt in the source distribution. 00022 */ 00023 00024 #include <tqgroupbox.h> 00025 #include <tqlabel.h> 00026 #include <tqlayout.h> 00027 #include <tqlineedit.h> 00028 #include <tqvaluevector.h> 00029 #include <tqspinbox.h> 00030 00031 #include <dcopref.h> 00032 #include <dcopclient.h> 00033 00034 #include <tdeaboutdata.h> 00035 #include <tdeapplication.h> 00036 #include <tdeaccelmanager.h> 00037 #include <tdeconfig.h> 00038 #include <kdebug.h> 00039 #include <kdialogbase.h> 00040 #include <tdelistview.h> 00041 #include <tdelocale.h> 00042 #include <kpushbutton.h> 00043 00044 #include "kcmkontactknt.h" 00045 00046 #include "newsfeeds.h" 00047 00048 #include <tdepimmacros.h> 00049 00050 extern "C" 00051 { 00052 KDE_EXPORT TDECModule *create_kontactknt( TQWidget *parent, const char * ) 00053 { 00054 return new KCMKontactKNT( parent, "kcmkontactknt" ); 00055 } 00056 } 00057 00058 NewsEditDialog::NewsEditDialog( const TQString& title, const TQString& url, TQWidget *parent ) 00059 : KDialogBase( Plain, i18n( "New News Feed" ), Ok | Cancel, 00060 Ok, parent, 0, true, true ) 00061 { 00062 TQWidget *page = plainPage(); 00063 TQGridLayout *layout = new TQGridLayout( page, 2, 3, marginHint(), 00064 spacingHint() ); 00065 00066 TQLabel *label = new TQLabel( i18n( "Name:" ), page ); 00067 layout->addWidget( label, 0, 0 ); 00068 00069 mTitle = new TQLineEdit( page ); 00070 label->setBuddy( mTitle ); 00071 layout->addMultiCellWidget( mTitle, 0, 0, 1, 2 ); 00072 00073 label = new TQLabel( i18n( "URL:" ), page ); 00074 layout->addWidget( label, 1, 0 ); 00075 00076 mURL = new TQLineEdit( page ); 00077 label->setBuddy( mURL ); 00078 layout->addMultiCellWidget( mURL, 1, 1, 1, 2 ); 00079 00080 mTitle->setText( title ); 00081 mURL->setText( url ); 00082 mTitle->setFocus(); 00083 connect( mTitle, TQT_SIGNAL( textChanged( const TQString& ) ), 00084 this, TQT_SLOT( modified() ) ); 00085 connect( mURL, TQT_SIGNAL( textChanged( const TQString& ) ), 00086 this, TQT_SLOT( modified() ) ); 00087 00088 modified(); 00089 } 00090 00091 void NewsEditDialog::modified() 00092 { 00093 enableButton( KDialogBase::Ok, !title().isEmpty() && !url().isEmpty() ); 00094 } 00095 00096 TQString NewsEditDialog::title() const 00097 { 00098 return mTitle->text(); 00099 } 00100 00101 TQString NewsEditDialog::url() const 00102 { 00103 return mURL->text(); 00104 } 00105 00106 class NewsItem : public TQListViewItem 00107 { 00108 public: 00109 NewsItem( TQListView *parent, const TQString& title, const TQString& url, bool custom ) 00110 : TQListViewItem( parent ), mTitle( title ), mUrl( url ), mCustom( custom ) 00111 { 00112 setText( 0, mTitle ); 00113 } 00114 00115 NewsItem( TQListViewItem *parent, const TQString& title, const TQString& url, bool custom ) 00116 : TQListViewItem( parent ), mTitle( title ), mUrl( url ), mCustom( custom ) 00117 { 00118 setText( 0, mTitle ); 00119 } 00120 00121 TQString title() const { return mTitle; } 00122 TQString url() const { return mUrl; } 00123 bool custom() const { return mCustom; } 00124 00125 private: 00126 TQString mTitle; 00127 TQString mUrl; 00128 bool mCustom; 00129 }; 00130 00131 KCMKontactKNT::KCMKontactKNT( TQWidget *parent, const char *name ) 00132 : TDECModule( parent, name ) 00133 { 00134 initGUI(); 00135 00136 connect( mAllNews, TQT_SIGNAL( currentChanged( TQListViewItem* ) ), 00137 this, TQT_SLOT( allCurrentChanged( TQListViewItem* ) ) ); 00138 connect( mSelectedNews, TQT_SIGNAL( selectionChanged( TQListViewItem* ) ), 00139 this, TQT_SLOT( selectedChanged( TQListViewItem* ) ) ); 00140 00141 connect( mUpdateInterval, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( modified() ) ); 00142 connect( mArticleCount, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( modified() ) ); 00143 00144 connect( mAddButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( addNews() ) ); 00145 connect( mRemoveButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( removeNews() ) ); 00146 connect( mNewButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( newFeed() ) ); 00147 connect( mDeleteButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( deleteFeed() ) ); 00148 00149 TDEAcceleratorManager::manage( this ); 00150 00151 load(); 00152 } 00153 00154 void KCMKontactKNT::loadNews() 00155 { 00156 TQValueVector<TQListViewItem*> parents; 00157 TQValueVector<TQListViewItem*>::Iterator it; 00158 00159 parents.append( new TQListViewItem( mAllNews, i18n( "Arts" ) ) ); 00160 parents.append( new TQListViewItem( mAllNews, i18n( "Business" ) ) ); 00161 parents.append( new TQListViewItem( mAllNews, i18n( "Computers" ) ) ); 00162 parents.append( new TQListViewItem( mAllNews, i18n( "Misc" ) ) ); 00163 parents.append( new TQListViewItem( mAllNews, i18n( "Recreation" ) ) ); 00164 parents.append( new TQListViewItem( mAllNews, i18n( "Society" ) ) ); 00165 00166 for ( it = parents.begin(); it != parents.end(); ++it ) 00167 (*it)->setSelectable( false ); 00168 00169 for ( int i = 0; i < DEFAULT_NEWSSOURCES; ++i ) { 00170 NewsSourceData data = NewsSourceDefault[ i ]; 00171 new NewsItem( parents[ data.category() ], data.name(), data.url(), false ); 00172 mFeedMap.insert( data.url(), data.name() ); 00173 } 00174 } 00175 00176 void KCMKontactKNT::loadCustomNews() 00177 { 00178 TDEConfig config( "kcmkontactkntrc" ); 00179 TQMap<TQString, TQString> customFeeds = config.entryMap( "CustomFeeds" ); 00180 config.setGroup( "CustomFeeds" ); 00181 00182 mCustomItem = new TQListViewItem( mAllNews, i18n( "Custom" ) ); 00183 mCustomItem->setSelectable( false ); 00184 00185 if ( customFeeds.count() == 0 ) 00186 mCustomItem->setVisible( false ); 00187 00188 TQMap<TQString, TQString>::Iterator it; 00189 for ( it = customFeeds.begin(); it != customFeeds.end(); ++it ) { 00190 TQStringList value = config.readListEntry( it.key() ); 00191 mCustomFeeds.append( new NewsItem( mCustomItem, value[ 0 ], value[ 1 ], true ) ); 00192 mFeedMap.insert( value[ 1 ], value[ 0 ] ); 00193 mCustomItem->setVisible( true ); 00194 } 00195 } 00196 00197 void KCMKontactKNT::storeCustomNews() 00198 { 00199 TDEConfig config( "kcmkontactkntrc" ); 00200 config.deleteGroup( "CustomFeeds" ); 00201 config.setGroup( "CustomFeeds" ); 00202 00203 int counter = 0; 00204 TQValueList<NewsItem*>::Iterator it; 00205 for ( it = mCustomFeeds.begin(); it != mCustomFeeds.end(); ++it ) { 00206 TQStringList value; 00207 value << (*it)->title() << (*it)->url(); 00208 config.writeEntry( TQString::number( counter ), value ); 00209 00210 ++counter; 00211 } 00212 00213 config.sync(); 00214 } 00215 00216 void KCMKontactKNT::addNews() 00217 { 00218 if ( !dcopActive() ) 00219 return; 00220 00221 NewsItem *item = dynamic_cast<NewsItem*>( mAllNews->selectedItem() ); 00222 if ( item == 0 ) 00223 return; 00224 00225 DCOPRef service( "rssservice", "RSSService" ); 00226 service.send( "add(TQString)", item->url() ); 00227 00228 scanNews(); 00229 00230 emit changed( true ); 00231 } 00232 00233 void KCMKontactKNT::removeNews() 00234 { 00235 if ( !dcopActive() ) 00236 return; 00237 00238 NewsItem *item = dynamic_cast<NewsItem*>( mSelectedNews->selectedItem() ); 00239 if ( item == 0 ) 00240 return; 00241 00242 DCOPRef service( "rssservice", "RSSService" ); 00243 service.send( "remove(TQString)", item->url() ); 00244 00245 scanNews(); 00246 00247 emit changed( true ); 00248 } 00249 00250 void KCMKontactKNT::newFeed() 00251 { 00252 NewsEditDialog dlg( "", "", this ); 00253 00254 if ( dlg.exec() ) { 00255 NewsItem *item = new NewsItem( mCustomItem, dlg.title(), dlg.url(), true ); 00256 mCustomFeeds.append( item ); 00257 mFeedMap.insert( dlg.url(), dlg.title() ); 00258 00259 mCustomItem->setVisible( true ); 00260 mCustomItem->setOpen( true ); 00261 mAllNews->ensureItemVisible( item ); 00262 mAllNews->setSelected( item, true ); 00263 00264 emit changed( true ); 00265 } 00266 } 00267 00268 void KCMKontactKNT::deleteFeed() 00269 { 00270 NewsItem *item = dynamic_cast<NewsItem*>( mAllNews->selectedItem() ); 00271 if ( !item ) 00272 return; 00273 00274 if ( mCustomFeeds.find( item ) == mCustomFeeds.end() ) 00275 return; 00276 00277 mCustomFeeds.remove( item ); 00278 mFeedMap.remove( item->url() ); 00279 delete item; 00280 00281 if ( mCustomFeeds.count() == 0 ) 00282 mCustomItem->setVisible( false ); 00283 00284 emit changed( true ); 00285 } 00286 00287 void KCMKontactKNT::scanNews() 00288 { 00289 if ( !dcopActive() ) 00290 return; 00291 00292 mSelectedNews->clear(); 00293 00294 DCOPRef service( "rssservice", "RSSService" ); 00295 TQStringList urls = service.call( "list()" ); 00296 00297 for ( uint i = 0; i < urls.count(); ++i ) 00298 { 00299 TQString url = urls[ i ]; 00300 TQString feedName = mFeedMap[ url ]; 00301 if ( feedName.isEmpty() ) 00302 feedName = url; 00303 new NewsItem( mSelectedNews, feedName, url, false ); 00304 } 00305 } 00306 00307 void KCMKontactKNT::selectedChanged( TQListViewItem *item ) 00308 { 00309 mRemoveButton->setEnabled( item && item->isSelected() ); 00310 } 00311 00312 void KCMKontactKNT::allCurrentChanged( TQListViewItem *item ) 00313 { 00314 NewsItem *newsItem = dynamic_cast<NewsItem*>( item ); 00315 00316 bool addState = false; 00317 bool delState = false; 00318 if ( newsItem && newsItem->isSelected() ) { 00319 addState = true; 00320 delState = (mCustomFeeds.find( newsItem ) != mCustomFeeds.end()); 00321 } 00322 00323 mAddButton->setEnabled( addState ); 00324 mDeleteButton->setEnabled( delState ); 00325 } 00326 00327 void KCMKontactKNT::modified() 00328 { 00329 emit changed( true ); 00330 } 00331 00332 void KCMKontactKNT::initGUI() 00333 { 00334 TQGridLayout *layout = new TQGridLayout( this, 2, 3, KDialog::marginHint(), 00335 KDialog::spacingHint() ); 00336 00337 mAllNews = new TDEListView( this ); 00338 mAllNews->addColumn( i18n( "All" ) ); 00339 mAllNews->setRootIsDecorated( true ); 00340 mAllNews->setFullWidth( true ); 00341 layout->addWidget( mAllNews, 0, 0 ); 00342 00343 TQVBoxLayout *vbox = new TQVBoxLayout( layout, KDialog::spacingHint() ); 00344 00345 vbox->addStretch(); 00346 mAddButton = new KPushButton( i18n( "Add" ), this ); 00347 mAddButton->setEnabled( false ); 00348 vbox->addWidget( mAddButton ); 00349 mRemoveButton = new KPushButton( i18n( "Remove" ), this ); 00350 mRemoveButton->setEnabled( false ); 00351 vbox->addWidget( mRemoveButton ); 00352 vbox->addStretch(); 00353 00354 mSelectedNews = new TDEListView( this ); 00355 mSelectedNews->addColumn( i18n( "Selected" ) ); 00356 mSelectedNews->setFullWidth( true ); 00357 layout->addWidget( mSelectedNews, 0, 2 ); 00358 00359 TQGroupBox *box = new TQGroupBox( 0, Qt::Vertical, 00360 i18n( "News Feed Settings" ), this ); 00361 00362 TQGridLayout *boxLayout = new TQGridLayout( box->layout(), 2, 3, 00363 KDialog::spacingHint() ); 00364 00365 TQLabel *label = new TQLabel( i18n( "Refresh time:" ), box ); 00366 boxLayout->addWidget( label, 0, 0 ); 00367 00368 mUpdateInterval = new TQSpinBox( 1, 3600, 1, box ); 00369 mUpdateInterval->setSuffix( " sec." ); 00370 label->setBuddy( mUpdateInterval ); 00371 boxLayout->addWidget( mUpdateInterval, 0, 1 ); 00372 00373 label = new TQLabel( i18n( "Number of items shown:" ), box ); 00374 boxLayout->addWidget( label, 1, 0 ); 00375 00376 mArticleCount = new TQSpinBox( box ); 00377 label->setBuddy( mArticleCount ); 00378 boxLayout->addWidget( mArticleCount, 1, 1 ); 00379 00380 mNewButton = new KPushButton( i18n( "New Feed..." ), box ); 00381 boxLayout->addWidget( mNewButton, 0, 2 ); 00382 00383 mDeleteButton = new KPushButton( i18n( "Delete Feed" ), box ); 00384 mDeleteButton->setEnabled( false ); 00385 boxLayout->addWidget( mDeleteButton, 1, 2 ); 00386 00387 layout->addMultiCellWidget( box, 1, 1, 0, 2 ); 00388 } 00389 00390 bool KCMKontactKNT::dcopActive() const 00391 { 00392 TQString error; 00393 TQCString appID; 00394 bool isGood = true; 00395 DCOPClient *client = kapp->dcopClient(); 00396 if ( !client->isApplicationRegistered( "rssservice" ) ) { 00397 if ( TDEApplication::startServiceByDesktopName( "rssservice", TQStringList(), &error, &appID ) ) 00398 isGood = false; 00399 } 00400 00401 return isGood; 00402 } 00403 00404 void KCMKontactKNT::load() 00405 { 00406 mAllNews->clear(); 00407 00408 loadNews(); 00409 loadCustomNews(); 00410 scanNews(); 00411 00412 TDEConfig config( "kcmkontactkntrc" ); 00413 config.setGroup( "General" ); 00414 00415 mUpdateInterval->setValue( config.readNumEntry( "UpdateInterval", 600 ) ); 00416 mArticleCount->setValue( config.readNumEntry( "ArticleCount", 4 ) ); 00417 00418 emit changed( false ); 00419 } 00420 00421 void KCMKontactKNT::save() 00422 { 00423 storeCustomNews(); 00424 00425 TDEConfig config( "kcmkontactkntrc" ); 00426 config.setGroup( "General" ); 00427 00428 config.writeEntry( "UpdateInterval", mUpdateInterval->value() ); 00429 config.writeEntry( "ArticleCount", mArticleCount->value() ); 00430 00431 config.sync(); 00432 00433 emit changed( false ); 00434 } 00435 00436 void KCMKontactKNT::defaults() 00437 { 00438 } 00439 00440 const TDEAboutData* KCMKontactKNT::aboutData() const 00441 { 00442 TDEAboutData *about = new TDEAboutData( I18N_NOOP( "kcmkontactknt" ), 00443 I18N_NOOP( "Newsticker Configuration Dialog" ), 00444 0, 0, TDEAboutData::License_GPL, 00445 I18N_NOOP( "(c) 2003 - 2004 Tobias Koenig" ) ); 00446 00447 about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" ); 00448 00449 return about; 00450 } 00451 00452 #include "kcmkontactknt.moc"