kcmultidialog.cpp
00001 /* 00002 Copyright (c) 2000 Matthias Elter <elter@kde.org> 00003 Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> 00004 Copyright (c) 2003 Matthias Kretz <kretz@kde.org> 00005 Copyright (c) 2004 Frans Englich <frans.erglich.com> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 00022 */ 00023 00024 #include <tqcursor.h> 00025 #include <tqhbox.h> 00026 #include <tqlayout.h> 00027 #include <tqpushbutton.h> 00028 00029 #include <tdeaboutdata.h> 00030 #include <tdeapplication.h> 00031 #include <kdebug.h> 00032 #include <kiconloader.h> 00033 #include <klibloader.h> 00034 #include <tdelocale.h> 00035 #include <tdemessagebox.h> 00036 #include <kprocess.h> 00037 #include <krun.h> 00038 #include <kstdguiitem.h> 00039 #include <kuser.h> 00040 00041 #include "tdecmoduleloader.h" 00042 #include "tdecmoduleproxy.h" 00043 #include "kcmultidialog.h" 00044 #include "kcmultidialog.moc" 00045 00046 class KCMultiDialog::KCMultiDialogPrivate 00047 { 00048 public: 00049 KCMultiDialogPrivate() 00050 : hasRootKCM( false ), currentModule( 0 ) 00051 {} 00052 00053 bool hasRootKCM; 00054 TDECModuleProxy* currentModule; 00055 }; 00056 00057 00058 KCMultiDialog::KCMultiDialog(TQWidget *parent, const char *name, bool modal) 00059 : KDialogBase(IconList, i18n("Configure"), Help | Default |Cancel | Apply | 00060 Ok | User1 | User2, Ok, parent, name, modal, true, 00061 KStdGuiItem::reset(), KStdGuiItem::adminMode()) 00062 , dialogface( IconList ), d( new KCMultiDialogPrivate ) 00063 { 00064 init(); 00065 } 00066 00067 KCMultiDialog::KCMultiDialog( int dialogFace, const TQString & caption, TQWidget * parent, const char * name, bool modal ) 00068 : KDialogBase( dialogFace, caption, Help | Default | Cancel | Apply | Ok | 00069 User1 | User2, Ok, parent, name, modal, true, 00070 KStdGuiItem::reset(), KStdGuiItem::adminMode()) 00071 , dialogface( dialogFace ), d( new KCMultiDialogPrivate ) 00072 { 00073 init(); 00074 } 00075 00076 KCMultiDialog::KCMultiDialog( int dialogFace, const KGuiItem &user2, 00077 const KGuiItem &user3, int buttonMask, const TQString &caption, 00078 TQWidget *parent, const char *name, bool modal ) 00079 : KDialogBase( dialogFace, caption, buttonMask | Help | Default | Cancel | 00080 Apply | Ok | User1, Ok, parent, name, modal, true, 00081 KStdGuiItem::reset(), user2, user3 ) 00082 , dialogface( dialogFace ), d( new KCMultiDialogPrivate ) 00083 { 00084 kdDebug( 710 ) << "Root modules will not work with this constructor. See the API documentation." << endl; 00085 init(); 00086 if ( buttonMask & User2 ) 00087 showButton( User2, true ); 00088 } 00089 00090 inline void KCMultiDialog::init() 00091 { 00092 connect( this, TQT_SIGNAL( finished()), TQT_SLOT( dialogClosed())); 00093 showButton( User1, false ); 00094 showButton( User2, false ); 00095 enableButton(Apply, false); 00096 connect(this, TQT_SIGNAL(aboutToShowPage(TQWidget *)), this, TQT_SLOT(slotAboutToShow(TQWidget *))); 00097 setInitialSize(TQSize(640,480)); 00098 moduleParentComponents.setAutoDelete( true ); 00099 00100 } 00101 00102 KCMultiDialog::~KCMultiDialog() 00103 { 00104 OrphanMap::Iterator end2 = m_orphanModules.end(); 00105 for( OrphanMap::Iterator it = m_orphanModules.begin(); it != end2; ++it ) 00106 delete ( *it ); 00107 delete d; 00108 } 00109 00110 void KCMultiDialog::slotDefault() 00111 { 00112 int curPageIndex = activePageIndex(); 00113 00114 ModuleList::Iterator end = m_modules.end(); 00115 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00116 if( pageIndex( ( TQWidget * )( *it ).kcm->parent() ) == curPageIndex ) 00117 { 00118 ( *it ).kcm->defaults(); 00119 clientChanged( true ); 00120 return; 00121 } 00122 } 00123 00124 void KCMultiDialog::slotUser1() 00125 { 00126 int curPageIndex = activePageIndex(); 00127 00128 ModuleList::Iterator end = m_modules.end(); 00129 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00130 if( pageIndex( ( TQWidget * )( *it ).kcm->parent() ) == curPageIndex ) 00131 { 00132 ( *it ).kcm->load(); 00133 clientChanged( false ); 00134 return; 00135 } 00136 } 00137 00138 void KCMultiDialog::apply() 00139 { 00140 TQStringList updatedModules; 00141 ModuleList::Iterator end = m_modules.end(); 00142 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00143 { 00144 TDECModuleProxy * m = ( *it ).kcm; 00145 if( m->changed() ) 00146 { 00147 m->save(); 00148 TQStringList * names = moduleParentComponents[ m ]; 00149 kdDebug(710) << k_funcinfo << *names << " saved and added to the list" << endl; 00150 for( TQStringList::ConstIterator it = names->begin(); it != names->end(); ++it ) 00151 if( updatedModules.find( *it ) == updatedModules.end() ) 00152 updatedModules.append( *it ); 00153 } 00154 } 00155 for( TQStringList::const_iterator it = updatedModules.begin(); it != updatedModules.end(); ++it ) 00156 { 00157 kdDebug(710) << k_funcinfo << *it << " " << ( *it ).latin1() << endl; 00158 emit configCommitted( ( *it ).latin1() ); 00159 } 00160 emit configCommitted(); 00161 } 00162 00163 void KCMultiDialog::slotApply() 00164 { 00165 TQPushButton *button = actionButton(Apply); 00166 if (button) 00167 button->setFocus(); 00168 emit applyClicked(); 00169 apply(); 00170 } 00171 00172 00173 void KCMultiDialog::slotOk() 00174 { 00175 TQPushButton *button = actionButton(Ok); 00176 if (button) 00177 button->setFocus(); 00178 emit okClicked(); 00179 apply(); 00180 accept(); 00181 } 00182 00183 void KCMultiDialog::slotHelp() 00184 { 00185 TQString docPath; 00186 00187 int curPageIndex = activePageIndex(); 00188 ModuleList::Iterator end = m_modules.end(); 00189 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) { 00190 if( pageIndex( ( TQWidget * )( *it ).kcm->parent() ) == curPageIndex ) 00191 { 00192 TDECModuleProxy *m = (*it).kcm; 00193 00194 docPath = m->handbookDocPath(); 00195 if (docPath == TQString::null) 00196 docPath = m->moduleInfo().docPath(); 00197 00198 TQString section = m->handbookSection(); 00199 if (section != TQString::null) { 00200 docPath = TQString( "%1#%2" ).arg( docPath ).arg( section ); 00201 } 00202 break; 00203 } 00204 } 00205 00206 KURL url( KURL("help:/"), docPath ); 00207 00208 if (url.protocol() == "help" || url.protocol() == "man" || url.protocol() == "info") { 00209 TDEProcess process; 00210 process << "khelpcenter" 00211 << url.url(); 00212 process.start(TDEProcess::DontCare); 00213 process.detach(); 00214 } else { 00215 new KRun(url); 00216 } 00217 } 00218 00219 void KCMultiDialog::clientChanged(bool state) 00220 { 00221 kdDebug( 710 ) << k_funcinfo << state << endl; 00222 ModuleList::Iterator end = m_modules.end(); 00223 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00224 if( ( *it ).kcm->changed() ) 00225 { 00226 enableButton( Apply, true ); 00227 return; 00228 } 00229 enableButton( Apply, false ); 00230 } 00231 00232 void KCMultiDialog::addModule(const TQString& path, bool withfallback, TQStringList args) 00233 { 00234 TQString complete = path; 00235 00236 if( !path.endsWith( ".desktop" )) 00237 complete += ".desktop"; 00238 00239 KService::Ptr service = KService::serviceByStorageId( complete ); 00240 00241 addModule( TDECModuleInfo( service ), TQStringList(), withfallback, args ); 00242 } 00243 00244 void KCMultiDialog::addModule(const TDECModuleInfo& moduleinfo, 00245 TQStringList parentmodulenames, bool withfallback, TQStringList args) 00246 { 00247 kdDebug(710) << "KCMultiDialog::addModule " 00248 << moduleinfo.moduleName() << endl; 00249 00250 if( !moduleinfo.service() ) 00251 return; 00252 00253 if ( !kapp->authorizeControlModule( moduleinfo.service()->menuId() )) 00254 return; 00255 00256 if( !TDECModuleLoader::testModule( moduleinfo )) 00257 return; 00258 00259 TQFrame* page = 0; 00260 if (!moduleinfo.service()->noDisplay()) 00261 switch( dialogface ) 00262 { 00263 case TreeList: 00264 parentmodulenames += moduleinfo.moduleName(); 00265 page = addHBoxPage( parentmodulenames, moduleinfo.comment(), 00266 SmallIcon( moduleinfo.icon(), 00267 IconSize( TDEIcon::Small ) ) ); 00268 break; 00269 case IconList: 00270 page = addHBoxPage( moduleinfo.moduleName(), 00271 moduleinfo.comment(), DesktopIcon( moduleinfo.icon(), 00272 TDEIcon::SizeMedium ) ); 00273 break; 00274 case Plain: 00275 page = plainPage(); 00276 ( new TQHBoxLayout( page ) )->setAutoAdd( true ); 00277 break; 00278 default: 00279 kdError( 710 ) << "unsupported dialog face for KCMultiDialog" 00280 << endl; 00281 break; 00282 } 00283 if(!page) { 00284 TDECModuleLoader::unloadModule(moduleinfo); 00285 return; 00286 } 00287 TDECModuleProxy * module; 00288 if( m_orphanModules.contains( moduleinfo.service() ) ) 00289 { 00290 // the TDECModule already exists - it was removed from the dialog in 00291 // removeAllModules 00292 module = m_orphanModules[ moduleinfo.service() ]; 00293 m_orphanModules.remove( moduleinfo.service() ); 00294 kdDebug( 710 ) << "Use TDECModule from the list of orphans for " << 00295 moduleinfo.moduleName() << ": " << module << endl; 00296 00297 module->reparent( page, 0, TQPoint( 0, 0 ), true ); 00298 00299 if( module->changed() ) 00300 clientChanged( true ); 00301 00302 if( activePageIndex() == -1 ) 00303 showPage( pageIndex( page ) ); 00304 } 00305 else 00306 { 00307 module = new TDECModuleProxy( moduleinfo, withfallback, page, 0, args ); 00308 TQStringList parentComponents = moduleinfo.service()->property( 00309 "X-TDE-ParentComponents" ).toStringList(); 00310 moduleParentComponents.insert( module, 00311 new TQStringList( parentComponents ) ); 00312 00313 connect(module, TQT_SIGNAL(changed(bool)), this, TQT_SLOT(clientChanged(bool))); 00314 00315 if( m_modules.count() == 0 ) 00316 aboutToShowPage( page ); 00317 } 00318 CreatedModule cm; 00319 cm.kcm = module; 00320 cm.service = moduleinfo.service(); 00321 m_modules.append( cm ); 00322 if ( moduleinfo.needsRootPrivileges() && 00323 !d->hasRootKCM && 00324 !KUser().isSuperUser() ) /* If we're embedded, it's true */ 00325 { 00326 d->hasRootKCM = true; 00327 showButton( User2, true ); 00328 if( plainPage() ) // returns 0 if we're not a Plain dialog 00329 slotAboutToShow( page ); // Won't be called otherwise, necessary for adminMode button 00330 } 00331 } 00332 00333 void KCMultiDialog::removeAllModules() 00334 { 00335 kdDebug( 710 ) << k_funcinfo << endl; 00336 ModuleList::Iterator end = m_modules.end(); 00337 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00338 { 00339 kdDebug( 710 ) << "remove 2" << endl; 00340 TDECModuleProxy * kcm = ( *it ).kcm; 00341 TQObject * page = TQT_TQOBJECT(kcm->parent()); 00342 kcm->hide(); 00343 if( page ) 00344 { 00345 // I hate this 00346 kcm->reparent( 0, TQPoint( 0, 0 ), false ); 00347 delete page; 00348 } 00349 m_orphanModules[ ( *it ).service ] = kcm; 00350 kdDebug( 710 ) << "added TDECModule to the list of orphans: " << 00351 kcm << endl; 00352 } 00353 m_modules.clear(); 00354 // all modules are gone, none can be changed 00355 clientChanged( false ); 00356 } 00357 00358 void KCMultiDialog::show() 00359 { /* KDE 4 Remove..? */ 00360 KDialogBase::show(); 00361 } 00362 00363 void KCMultiDialog::slotAboutToShow(TQWidget *page) 00364 { 00365 kdDebug(710) << k_funcinfo << endl; 00366 00367 TQObject * obj = page->child( 0, "TDECModuleProxy" ); 00368 if( ! obj ) 00369 return; 00370 00371 TDECModuleProxy * module = ::tqqt_cast<TDECModuleProxy*>(obj); 00372 if( ! module ) 00373 return; 00374 d->currentModule = module; 00375 00376 enableButton( KDialogBase::Help, 00377 d->currentModule->buttons() & TDECModule::Help ); 00378 enableButton( KDialogBase::Default, 00379 d->currentModule->buttons() & TDECModule::Default ); 00380 00381 disconnect( this, TQT_SIGNAL(user2Clicked()), 0, 0 ); 00382 00383 if (d->currentModule->moduleInfo().needsRootPrivileges()) 00384 { 00385 if ( !d->currentModule->rootMode() ) 00386 { /* Enable the Admin Mode button */ 00387 enableButton( User2, true ); 00388 connect( this, TQT_SIGNAL(user2Clicked()), d->currentModule, TQT_SLOT( runAsRoot() )); 00389 connect( this, TQT_SIGNAL(user2Clicked()), TQT_SLOT( disableRModeButton() )); 00390 } 00391 else 00392 enableButton( User2, false); 00393 } 00394 } 00395 00396 void KCMultiDialog::rootExit() 00397 { 00398 enableButton( User2, true); 00399 } 00400 00401 void KCMultiDialog::disableRModeButton() 00402 { 00403 enableButton( User2, false ); 00404 connect ( d->currentModule, TQT_SIGNAL( childClosed() ), TQT_SLOT( rootExit() )); 00405 } 00406 00407 void KCMultiDialog::dialogClosed() 00408 { 00409 kdDebug(710) << k_funcinfo << endl; 00410 00411 /* If we don't delete them, the DCOP registration stays, and trying to load the KCMs 00412 * in other situations will lead to "module already loaded in Foo," while to the user 00413 * doesn't appear so(the dialog is hidden) */ 00414 ModuleList::Iterator end = m_modules.end(); 00415 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00416 ( *it ).kcm->deleteClient(); 00417 } 00418 00419 00420 // vim: sw=4 et sts=4