kpluginselector.cpp
00001 /* This file is part of the KDE project 00002 Copyright (C) 2002-2003 Matthias Kretz <kretz@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 00018 */ 00019 00020 #include "kpluginselector.h" 00021 #include "kpluginselector_p.h" 00022 00023 #include <qtooltip.h> 00024 #include <qvbox.h> 00025 #include <qlabel.h> 00026 #include <qstrlist.h> 00027 #include <qfile.h> 00028 #include <qstring.h> 00029 #include <qlayout.h> 00030 #include <qptrlist.h> 00031 #include <qwidgetstack.h> 00032 #include <qcursor.h> 00033 #include <qapplication.h> 00034 #include <qobjectlist.h> 00035 #include <qcstring.h> 00036 00037 #include <kdebug.h> 00038 #include <klocale.h> 00039 #include <klistview.h> 00040 #include <ksimpleconfig.h> 00041 #include <kdialog.h> 00042 #include <kglobal.h> 00043 #include <kglobalsettings.h> 00044 #include <kstandarddirs.h> 00045 #include <ktabctl.h> 00046 #include <kcmoduleinfo.h> 00047 #include <qvaluelist.h> 00048 #include <kservice.h> 00049 #include <ktrader.h> 00050 #include <ktabwidget.h> 00051 #include <kiconloader.h> 00052 #include <kcmodule.h> 00053 #include "kcmoduleinfo.h" 00054 #include "kcmoduleloader.h" 00055 #include <qsplitter.h> 00056 #include <qframe.h> 00057 #include "kplugininfo.h" 00058 #include <kinstance.h> 00059 #include <qptrdict.h> 00060 #include <qstringlist.h> 00061 #include "kcmoduleproxy.h" 00062 00063 /* 00064 QCheckListViewItem that holds a pointer to the KPluginInfo object. 00065 Used in the tooltip code to access additional fields 00066 */ 00067 class KPluginInfoLVI : public QCheckListItem 00068 { 00069 public: 00070 KPluginInfoLVI( KPluginInfo *pluginInfo, KListView *parent ) 00071 : QCheckListItem( parent, pluginInfo->name(), QCheckListItem::CheckBox ), m_pluginInfo( pluginInfo ) 00072 { 00073 } 00074 00075 KPluginInfo * pluginInfo() { return m_pluginInfo; } 00076 00077 private: 00078 KPluginInfo *m_pluginInfo; 00079 }; 00080 00081 /* 00082 Custom QToolTip for the list view. 00083 The decision whether or not to show tooltips is taken in 00084 maybeTip(). See also the QListView sources from Qt itself. 00085 */ 00086 class KPluginListViewToolTip : public QToolTip 00087 { 00088 public: 00089 KPluginListViewToolTip( QWidget *parent, KListView *lv ); 00090 00091 void maybeTip( const QPoint &pos ); 00092 00093 private: 00094 KListView *m_listView; 00095 }; 00096 00097 KPluginListViewToolTip::KPluginListViewToolTip( QWidget *parent, KListView *lv ) 00098 : QToolTip( parent ), m_listView( lv ) 00099 { 00100 } 00101 00102 void KPluginListViewToolTip::maybeTip( const QPoint &pos ) 00103 { 00104 if ( !parentWidget() || !m_listView ) 00105 return; 00106 00107 KPluginInfoLVI *item = dynamic_cast<KPluginInfoLVI *>( m_listView->itemAt( pos ) ); 00108 if ( !item ) 00109 return; 00110 00111 QString toolTip = i18n( "<qt><table>" 00112 "<tr><td><b>Description:</b></td><td>%1</td></tr>" 00113 "<tr><td><b>Author:</b></td><td>%2</td></tr>" 00114 "<tr><td><b>Version:</b></td><td>%3</td></tr>" 00115 "<tr><td><b>License:</b></td><td>%4</td></tr></table></qt>" ).arg( item->pluginInfo()->comment(), 00116 item->pluginInfo()->author(), item->pluginInfo()->version(), item->pluginInfo()->license() ); 00117 00118 //kdDebug( 702 ) << k_funcinfo << "Adding tooltip: itemRect: " << itemRect << ", tooltip: " << toolTip << endl; 00119 tip( m_listView->itemRect( item ), toolTip ); 00120 } 00121 00122 struct KPluginSelectionWidget::KPluginSelectionWidgetPrivate 00123 { 00124 KPluginSelectionWidgetPrivate( KPluginSelector * _kps, 00125 const QString & _cat, 00126 KConfigGroup * _config ) 00127 : widgetstack( 0 ) 00128 , kps( _kps ) 00129 , config( _config ) 00130 , tooltip( 0 ) 00131 , catname( _cat ) 00132 , currentplugininfo( 0 ) 00133 , visible( true ) 00134 , currentchecked( false ) 00135 , changed( 0 ) 00136 { 00137 moduleParentComponents.setAutoDelete( true ); 00138 } 00139 00140 ~KPluginSelectionWidgetPrivate() 00141 { 00142 delete config; 00143 } 00144 00145 QMap<QCheckListItem*, KPluginInfo*> pluginInfoMap; 00146 00147 QWidgetStack * widgetstack; 00148 KPluginSelector * kps; 00149 KConfigGroup * config; 00150 KPluginListViewToolTip *tooltip; 00151 00152 QDict<KCModuleInfo> pluginconfigmodules; 00153 QMap<QString, int> widgetIDs; 00154 QMap<KPluginInfo*, bool> plugincheckedchanged; 00155 QString catname; 00156 QValueList<KCModuleProxy*> modulelist; 00157 QPtrDict<QStringList> moduleParentComponents; 00158 00159 KPluginInfo * currentplugininfo; 00160 bool visible; 00161 bool currentchecked; 00162 int changed; 00163 }; 00164 00165 KPluginSelectionWidget::KPluginSelectionWidget( 00166 const QValueList<KPluginInfo*> & plugininfos, KPluginSelector * kps, 00167 QWidget * parent, const QString & catname, const QString & category, 00168 KConfigGroup * config, const char * name ) 00169 : QWidget( parent, name ) 00170 , d( new KPluginSelectionWidgetPrivate( kps, catname, config ) ) 00171 { 00172 init( plugininfos, category ); 00173 } 00174 00175 inline QString KPluginSelectionWidget::catName() const 00176 { 00177 return d->catname; 00178 } 00179 00180 void KPluginSelectionWidget::init( const QValueList<KPluginInfo*> & plugininfos, 00181 const QString & category ) 00182 { 00183 // setup Widgets 00184 ( new QVBoxLayout( this, 0, KDialog::spacingHint() ) )->setAutoAdd( true ); 00185 KListView * listview = new KListView( this ); 00186 d->tooltip = new KPluginListViewToolTip( listview->viewport(), listview ); 00187 connect( listview, SIGNAL( pressed( QListViewItem * ) ), this, 00188 SLOT( executed( QListViewItem * ) ) ); 00189 connect( listview, SIGNAL( spacePressed( QListViewItem * ) ), this, 00190 SLOT( executed( QListViewItem * ) ) ); 00191 connect( listview, SIGNAL( returnPressed( QListViewItem * ) ), this, 00192 SLOT( executed( QListViewItem * ) ) ); 00193 connect( listview, SIGNAL( selectionChanged( QListViewItem * ) ), this, 00194 SLOT( executed( QListViewItem * ) ) ); 00195 listview->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred ); 00196 listview->setAcceptDrops( false ); 00197 listview->setFullWidth( true ); 00198 listview->setSelectionModeExt( KListView::Single ); 00199 listview->setAllColumnsShowFocus( true ); 00200 listview->addColumn( i18n( "Name" ) ); 00201 for( QValueList<KPluginInfo*>::ConstIterator it = plugininfos.begin(); 00202 it != plugininfos.end(); ++it ) 00203 { 00204 d->plugincheckedchanged[ *it ] = false; 00205 if( !( *it )->isHidden() && 00206 ( category.isNull() || ( *it )->category() == category ) ) 00207 { 00208 QCheckListItem * item = new KPluginInfoLVI( *it, listview ); 00209 if( ! ( *it )->icon().isEmpty() ) 00210 item->setPixmap( 0, SmallIcon( ( *it )->icon(), IconSize( KIcon::Small ) ) ); 00211 item->setOn( ( *it )->isPluginEnabled() ); 00212 d->pluginInfoMap.insert( item, *it ); 00213 } 00214 } 00215 00216 // widgetstack 00217 d->widgetstack = d->kps->widgetStack(); 00218 load(); 00219 // select and highlight the first item in the plugin list 00220 if( listview->firstChild() ) 00221 listview->setSelected( listview->firstChild(), true ); 00222 } 00223 00224 KPluginSelectionWidget::~KPluginSelectionWidget() 00225 { 00226 delete d->tooltip; 00227 delete d; 00228 } 00229 00230 bool KPluginSelectionWidget::pluginIsLoaded( const QString & pluginName ) const 00231 { 00232 for( QMap<QCheckListItem*, KPluginInfo*>::ConstIterator it = 00233 d->pluginInfoMap.begin(); it != d->pluginInfoMap.end(); ++it ) 00234 if( it.data()->pluginName() == pluginName ) 00235 return it.data()->isPluginEnabled(); 00236 return false; 00237 } 00238 00239 00240 QWidget * KPluginSelectionWidget::insertKCM( QWidget * parent, 00241 const KCModuleInfo & moduleinfo ) 00242 { 00243 KCModuleProxy * module = new KCModuleProxy( moduleinfo, false, 00244 parent ); 00245 if( !module->realModule() ) 00246 { 00247 //FIXME: not very verbose 00248 QLabel * label = new QLabel( i18n( "Error" ), parent ); 00249 label->setAlignment( Qt::AlignCenter ); 00250 00251 return label; 00252 } 00253 // add the KCM to the list so that we can call load/save/defaults on it 00254 d->modulelist.append( module ); 00255 QStringList * parentComponents = new QStringList( 00256 moduleinfo.service()->property( 00257 "X-KDE-ParentComponents" ).toStringList() ); 00258 d->moduleParentComponents.insert( module, parentComponents ); 00259 connect( module, SIGNAL( changed( bool ) ), SLOT( clientChanged( bool ) ) ); 00260 return module; 00261 } 00262 00263 void KPluginSelectionWidget::embeddPluginKCMs( KPluginInfo * plugininfo, bool checked ) 00264 { 00265 //if we have Services for the plugin we should be able to 00266 //create KCM(s) 00267 QApplication::setOverrideCursor( Qt::WaitCursor ); 00268 if( plugininfo->kcmServices().size() > 1 ) 00269 { 00270 // we need a tabwidget 00271 KTabWidget * tabwidget = new KTabWidget( d->widgetstack ); 00272 tabwidget->setEnabled( checked ); 00273 00274 int id = d->widgetstack->addWidget( tabwidget ); 00275 d->kps->configPage( id ); 00276 d->widgetIDs[ plugininfo->pluginName() ] = id; 00277 00278 for( QValueList<KService::Ptr>::ConstIterator it = 00279 plugininfo->kcmServices().begin(); 00280 it != plugininfo->kcmServices().end(); ++it ) 00281 { 00282 if( !( *it )->noDisplay() ) 00283 { 00284 KCModuleInfo moduleinfo( *it ); 00285 QWidget * module = insertKCM( tabwidget, moduleinfo ); 00286 tabwidget->addTab( module, moduleinfo.moduleName() ); 00287 } 00288 } 00289 } 00290 else 00291 { 00292 if( !plugininfo->kcmServices().front()->noDisplay() ) 00293 { 00294 KCModuleInfo moduleinfo( 00295 plugininfo->kcmServices().front() ); 00296 QWidget * module = insertKCM( d->widgetstack, moduleinfo ); 00297 module->setEnabled( checked ); 00298 00299 int id = d->widgetstack->addWidget( module ); 00300 d->kps->configPage( id ); 00301 d->widgetIDs[ plugininfo->pluginName() ] = id; 00302 } 00303 } 00304 QApplication::restoreOverrideCursor(); 00305 } 00306 00307 inline void KPluginSelectionWidget::updateConfigPage() 00308 { 00309 updateConfigPage( d->currentplugininfo, d->currentchecked ); 00310 } 00311 00312 void KPluginSelectionWidget::updateConfigPage( KPluginInfo * plugininfo, 00313 bool checked ) 00314 { 00315 //kdDebug( 702 ) << k_funcinfo << endl; 00316 d->currentplugininfo = plugininfo; 00317 d->currentchecked = checked; 00318 00319 // if this widget is not currently visible (meaning that it's in a tabwidget 00320 // and another tab is currently opened) it's not allowed to change the 00321 // widgetstack 00322 if( ! d->visible ) 00323 return; 00324 00325 if( 0 == plugininfo ) 00326 { 00327 d->kps->configPage( 1 ); 00328 return; 00329 } 00330 00331 if( plugininfo->kcmServices().empty() ) 00332 d->kps->configPage( 1 ); 00333 else 00334 { 00335 if( !d->widgetIDs.contains( plugininfo->pluginName() ) ) 00336 // if no widget exists for the plugin create it 00337 embeddPluginKCMs( plugininfo, checked ); 00338 else 00339 { 00340 // the page already exists 00341 int id = d->widgetIDs[ plugininfo->pluginName() ]; 00342 d->kps->configPage( id ); 00343 d->widgetstack->widget( id )->setEnabled( checked ); 00344 } 00345 } 00346 } 00347 00348 void KPluginSelectionWidget::clientChanged( bool didchange ) 00349 { 00350 kdDebug( 702 ) << k_funcinfo << endl; 00351 d->changed += didchange ? 1 : -1; 00352 if( d->changed == 1 ) 00353 emit changed( true ); 00354 else if( d->changed == 0 ) 00355 emit changed( false ); 00356 else if( d->changed < 0 ) 00357 kdError( 702 ) << "negative changed value: " << d->changed << endl; 00358 } 00359 00360 void KPluginSelectionWidget::tabWidgetChanged( QWidget * widget ) 00361 { 00362 if( widget == this ) 00363 { 00364 d->visible = true; 00365 updateConfigPage(); 00366 } 00367 else 00368 d->visible = false; 00369 } 00370 00371 void KPluginSelectionWidget::executed( QListViewItem * item ) 00372 { 00373 kdDebug( 702 ) << k_funcinfo << endl; 00374 if( item == 0 ) 00375 return; 00376 00377 // Why not a dynamic_cast? - Martijn 00378 // because this is what the Qt API suggests; and since gcc 3.x I don't 00379 // trust dynamic_cast anymore - mkretz 00380 if( item->rtti() != 1 ) //check for a QCheckListItem 00381 return; 00382 00383 QCheckListItem * citem = static_cast<QCheckListItem *>( item ); 00384 bool checked = citem->isOn(); 00385 //kdDebug( 702 ) << "it's a " << ( checked ? "checked" : "unchecked" ) 00386 // << " QCheckListItem" << endl; 00387 00388 KPluginInfo * info = d->pluginInfoMap[ citem ]; 00389 Q_ASSERT( !info->isHidden() ); 00390 00391 if ( info->isPluginEnabled() != checked ) 00392 { 00393 kdDebug( 702 ) << "Item changed state, emitting changed()" << endl; 00394 00395 if( ! d->plugincheckedchanged[ info ] ) 00396 { 00397 ++d->changed; 00398 if ( d->changed == 1 ) 00399 emit changed( true ); 00400 } 00401 d->plugincheckedchanged[ info ] = true; 00402 00403 checkDependencies( info ); 00404 } 00405 else 00406 { 00407 if( d->plugincheckedchanged[ info ] ) 00408 { 00409 --d->changed; 00410 if ( d->changed == 0 ) 00411 emit changed( false ); 00412 } 00413 d->plugincheckedchanged[ info ] = false; 00414 // FIXME: plugins that depend on this plugin need to be disabled, too 00415 } 00416 00417 updateConfigPage( info, checked ); 00418 } 00419 00420 void KPluginSelectionWidget::load() 00421 { 00422 //kdDebug( 702 ) << k_funcinfo << endl; 00423 00424 for( QMap<QCheckListItem*, KPluginInfo*>::Iterator it = 00425 d->pluginInfoMap.begin(); it != d->pluginInfoMap.end(); ++it ) 00426 { 00427 KPluginInfo * info = it.data(); 00428 info->load( d->config ); 00429 it.key()->setOn( info->isPluginEnabled() ); 00430 if( d->visible && info == d->currentplugininfo ) 00431 d->currentchecked = info->isPluginEnabled(); 00432 } 00433 00434 for( QValueList<KCModuleProxy*>::Iterator it = d->modulelist.begin(); 00435 it != d->modulelist.end(); ++it ) 00436 if( ( *it )->changed() ) 00437 ( *it )->load(); 00438 00439 updateConfigPage(); 00440 // TODO: update changed state 00441 } 00442 00443 void KPluginSelectionWidget::save() 00444 { 00445 kdDebug( 702 ) << k_funcinfo << endl; 00446 00447 for( QMap<QCheckListItem*, KPluginInfo*>::Iterator it = 00448 d->pluginInfoMap.begin(); it != d->pluginInfoMap.end(); ++it ) 00449 { 00450 KPluginInfo * info = it.data(); 00451 bool checked = it.key()->isOn(); 00452 info->setPluginEnabled( checked ); 00453 info->save( d->config ); 00454 d->plugincheckedchanged[ info ] = false; 00455 } 00456 QStringList updatedModules; 00457 for( QValueList<KCModuleProxy*>::Iterator it = d->modulelist.begin(); 00458 it != d->modulelist.end(); ++it ) 00459 if( ( *it )->changed() ) 00460 { 00461 ( *it )->save(); 00462 QStringList * names = d->moduleParentComponents[ *it ]; 00463 if( names->size() == 0 ) 00464 names->append( QString::null ); 00465 for( QStringList::ConstIterator nameit = names->begin(); 00466 nameit != names->end(); ++nameit ) 00467 if( updatedModules.find( *nameit ) == updatedModules.end() ) 00468 updatedModules.append( *nameit ); 00469 } 00470 for( QStringList::ConstIterator it = updatedModules.begin(); it != updatedModules.end(); ++it ) 00471 emit configCommitted( ( *it ).latin1() ); 00472 00473 updateConfigPage(); 00474 kdDebug( 702 ) << "syncing config file" << endl; 00475 d->config->sync(); 00476 d->changed = 0; 00477 emit changed( false ); 00478 } 00479 00480 void KPluginSelectionWidget::checkDependencies( const KPluginInfo * info ) 00481 { 00482 if( info->dependencies().isEmpty() ) 00483 return; 00484 00485 for( QStringList::ConstIterator it = info->dependencies().begin(); 00486 it != info->dependencies().end(); ++it ) 00487 for( QMap<QCheckListItem*, 00488 KPluginInfo*>::Iterator infoIt = d->pluginInfoMap.begin(); 00489 infoIt != d->pluginInfoMap.end(); ++infoIt ) 00490 if( infoIt.data()->pluginName() == *it ) 00491 { 00492 if( !infoIt.key()->isOn() ) 00493 { 00494 infoIt.key()->setOn( true ); 00495 checkDependencies( infoIt.data() ); 00496 } 00497 continue; 00498 } 00499 } 00500 00501 class KPluginSelector::KPluginSelectorPrivate 00502 { 00503 public: 00504 KPluginSelectorPrivate() 00505 : frame( 0 ) 00506 , tabwidget( 0 ) 00507 , widgetstack( 0 ) 00508 , hideconfigpage( false ) 00509 { 00510 } 00511 00512 QFrame * frame; 00513 KTabWidget * tabwidget; 00514 QWidgetStack * widgetstack; 00515 QValueList<KPluginSelectionWidget *> pswidgets; 00516 bool hideconfigpage; 00517 }; 00518 00519 KPluginSelector::KPluginSelector( QWidget * parent, const char * name ) 00520 : QWidget( parent, name ) 00521 , d( new KPluginSelectorPrivate ) 00522 { 00523 QBoxLayout * hbox = new QHBoxLayout( this, 0, KDialog::spacingHint() ); 00524 hbox->setAutoAdd( true ); 00525 00526 QSplitter* splitter = new QSplitter( QSplitter::Horizontal, this ); 00527 d->frame = new QFrame( splitter, "KPluginSelector left frame" ); 00528 d->frame->setFrameStyle( QFrame::NoFrame ); 00529 ( new QVBoxLayout( d->frame, 0, KDialog::spacingHint() ) )->setAutoAdd( true ); 00530 00531 // widgetstack 00532 d->widgetstack = new QWidgetStack( splitter, "KPluginSelector Config Pages" ); 00533 d->widgetstack->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 00534 d->widgetstack->setMinimumSize( 200, 200 ); 00535 00536 QLabel * label = new QLabel( i18n( "(This plugin is not configurable)" ), 00537 d->widgetstack ); 00538 ( new QVBoxLayout( label, 0, KDialog::spacingHint() ) )->setAutoAdd( true ); 00539 label->setAlignment( Qt::AlignCenter ); 00540 label->setMinimumSize( 200, 200 ); 00541 00542 d->widgetstack->addWidget( label, 1 ); 00543 00544 configPage( 1 ); 00545 } 00546 00547 KPluginSelector::~KPluginSelector() 00548 { 00549 delete d; 00550 } 00551 00552 void KPluginSelector::checkNeedForTabWidget() 00553 { 00554 kdDebug( 702 ) << k_funcinfo << endl; 00555 if( ! d->tabwidget && d->pswidgets.size() == 1 ) 00556 { 00557 kdDebug( 702 ) << "no TabWidget and one KPluginSelectionWidget" << endl; 00558 // there's only one KPluginSelectionWidget yet, we need a TabWidget 00559 KPluginSelectionWidget * w = d->pswidgets.first(); 00560 if( w ) 00561 { 00562 kdDebug( 702 ) << "create TabWidget" << endl; 00563 d->tabwidget = new KTabWidget( d->frame, 00564 "KPluginSelector TabWidget" ); 00565 w->reparent( d->tabwidget, QPoint( 0, 0 ) ); 00566 d->tabwidget->addTab( w, w->catName() ); 00567 connect( d->tabwidget, SIGNAL( currentChanged( QWidget * ) ), w, 00568 SLOT( tabWidgetChanged( QWidget * ) ) ); 00569 } 00570 } 00571 } 00572 00573 static QValueList<KPluginInfo*> kpartsPluginInfos( const QString& instanceName ) 00574 { 00575 if( instanceName.isNull() ) 00576 return QValueList<KPluginInfo*>(); //nothing 00577 00578 const QStringList desktopfilenames = KGlobal::dirs()->findAllResources( "data", 00579 instanceName + "/kpartplugins/*.desktop", true, false ); 00580 return KPluginInfo::fromFiles( desktopfilenames ); 00581 } 00582 00583 void KPluginSelector::addPlugins( const QString & instanceName, 00584 const QString & catname, const QString & category, KConfig * config ) 00585 { 00586 const QValueList<KPluginInfo*> plugininfos = kpartsPluginInfos( instanceName ); 00587 if ( plugininfos.isEmpty() ) 00588 return; 00589 checkNeedForTabWidget(); 00590 Q_ASSERT( config ); // please set config, or use addPlugins( instance, ... ) which takes care of it 00591 if ( !config ) // KDE4: ensure that config is always set; make it second in the arg list? 00592 config = new KSimpleConfig( instanceName ); // memleak! 00593 KConfigGroup * cfgGroup = new KConfigGroup( config, "KParts Plugins" ); 00594 kdDebug( 702 ) << k_funcinfo << "cfgGroup = " << cfgGroup << endl; 00595 addPluginsInternal( plugininfos, catname, category, cfgGroup ); 00596 } 00597 00598 void KPluginSelector::addPluginsInternal( const QValueList<KPluginInfo*> plugininfos, 00599 const QString & catname, const QString & category, 00600 KConfigGroup* cfgGroup ) 00601 { 00602 KPluginSelectionWidget * w; 00603 if( d->tabwidget ) 00604 { 00605 w = new KPluginSelectionWidget( plugininfos, this, 00606 d->tabwidget, catname, category, cfgGroup ); 00607 d->tabwidget->addTab( w, catname ); 00608 connect( d->tabwidget, SIGNAL( currentChanged( QWidget * ) ), w, 00609 SLOT( tabWidgetChanged( QWidget * ) ) ); 00610 } 00611 else 00612 w = new KPluginSelectionWidget( plugininfos, this, d->frame, 00613 catname, category, cfgGroup ); 00614 w->setMinimumSize( 200, 200 ); 00615 connect( w, SIGNAL( changed( bool ) ), this, SIGNAL( changed( bool ) ) ); 00616 connect( w, SIGNAL( configCommitted( const QCString & ) ), this, 00617 SIGNAL( configCommitted( const QCString & ) ) ); 00618 d->pswidgets += w; 00619 } 00620 00621 void KPluginSelector::addPlugins( const KInstance * instance, const QString & 00622 catname, const QString & category, KConfig * config ) 00623 { 00624 if ( !config ) 00625 config = instance->config(); 00626 addPlugins( instance->instanceName(), catname, category, config ); 00627 } 00628 00629 void KPluginSelector::addPlugins( const QValueList<KPluginInfo*> & plugininfos, 00630 const QString & catname, const QString & category, KConfig * config ) 00631 { 00632 checkNeedForTabWidget(); 00633 // the KConfigGroup becomes owned by KPluginSelectionWidget 00634 KConfigGroup * cfgGroup = new KConfigGroup( config ? config : KGlobal::config(), "Plugins" ); 00635 kdDebug( 702 ) << k_funcinfo << "cfgGroup = " << cfgGroup << endl; 00636 addPluginsInternal( plugininfos, catname, category, cfgGroup ); 00637 } 00638 00639 QWidgetStack * KPluginSelector::widgetStack() 00640 { 00641 return d->widgetstack; 00642 } 00643 00644 inline void KPluginSelector::configPage( int id ) 00645 { 00646 if( id == 1 ) 00647 { 00648 // no config page 00649 if( d->hideconfigpage ) 00650 { 00651 d->widgetstack->hide(); 00652 return; 00653 } 00654 } 00655 else 00656 d->widgetstack->show(); 00657 00658 d->widgetstack->raiseWidget( id ); 00659 } 00660 00661 void KPluginSelector::setShowEmptyConfigPage( bool show ) 00662 { 00663 d->hideconfigpage = !show; 00664 if( d->hideconfigpage ) 00665 if( d->widgetstack->id( d->widgetstack->visibleWidget() ) == 1 ) 00666 d->widgetstack->hide(); 00667 } 00668 00669 void KPluginSelector::load() 00670 { 00671 for( QValueList<KPluginSelectionWidget *>::Iterator it = 00672 d->pswidgets.begin(); it != d->pswidgets.end(); ++it ) 00673 { 00674 ( *it )->load(); 00675 } 00676 } 00677 00678 void KPluginSelector::save() 00679 { 00680 for( QValueList<KPluginSelectionWidget *>::Iterator it = 00681 d->pswidgets.begin(); it != d->pswidgets.end(); ++it ) 00682 { 00683 ( *it )->save(); 00684 } 00685 } 00686 00687 void KPluginSelector::defaults() 00688 { 00689 kdDebug( 702 ) << k_funcinfo << endl; 00690 00691 // what should defaults do? here's what I think: 00692 // Pressing a button in the dialog should not change any widgets that are 00693 // not visible for the user. Therefor we may only change the currently 00694 // visible plugin's KCM. Restoring the default plugin selections is therefor 00695 // not possible. (if the plugin has multiple KCMs they will be shown in a 00696 // tabwidget - defaults() will be called for all of them) 00697 00698 QWidget * pluginconfig = d->widgetstack->visibleWidget(); 00699 KCModuleProxy * kcm = ( KCModuleProxy* )pluginconfig->qt_cast( 00700 "KCModuleProxy" ); 00701 if( kcm ) 00702 { 00703 kdDebug( 702 ) << "call KCModule::defaults() for the plugins KCM" 00704 << endl; 00705 kcm->defaults(); 00706 return; 00707 } 00708 00709 // if we get here the visible Widget must be a tabwidget holding more than 00710 // one KCM 00711 QObjectList * kcms = pluginconfig->queryList( "KCModuleProxy", 00712 0, false, false ); 00713 QObjectListIt it( *kcms ); 00714 QObject * obj; 00715 while( ( obj = it.current() ) != 0 ) 00716 { 00717 ++it; 00718 ( ( KCModule* )obj )->defaults(); 00719 } 00720 delete kcms; 00721 // FIXME: update changed state 00722 } 00723 00724 // vim: sw=4 sts=4 et 00725 00726 #include "kpluginselector.moc" 00727 #include "kpluginselector_p.moc"