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 <kaboutdata.h> 00030 #include <kapplication.h> 00031 #include <kdebug.h> 00032 #include <kiconloader.h> 00033 #include <klibloader.h> 00034 #include <klocale.h> 00035 #include <kmessagebox.h> 00036 #include <kprocess.h> 00037 #include <krun.h> 00038 #include <kstdguiitem.h> 00039 #include <kuser.h> 00040 00041 #include "kcmoduleloader.h" 00042 #include "kcmoduleproxy.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 KCModuleProxy* 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 KCModuleProxy * 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 docPath = ( *it ).kcm->moduleInfo().docPath(); 00193 break; 00194 } 00195 00196 KURL url( KURL("help:/"), docPath ); 00197 00198 if (url.protocol() == "help" || url.protocol() == "man" || url.protocol() == "info") { 00199 KProcess process; 00200 process << "khelpcenter" 00201 << url.url(); 00202 process.start(KProcess::DontCare); 00203 process.detach(); 00204 } else { 00205 new KRun(url); 00206 } 00207 } 00208 00209 void KCMultiDialog::clientChanged(bool state) 00210 { 00211 kdDebug( 710 ) << k_funcinfo << state << endl; 00212 ModuleList::Iterator end = m_modules.end(); 00213 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00214 if( ( *it ).kcm->changed() ) 00215 { 00216 enableButton( Apply, true ); 00217 return; 00218 } 00219 enableButton( Apply, false ); 00220 } 00221 00222 void KCMultiDialog::addModule(const TQString& path, bool withfallback) 00223 { 00224 TQString complete = path; 00225 00226 if( !path.endsWith( ".desktop" )) 00227 complete += ".desktop"; 00228 00229 KService::Ptr service = KService::serviceByStorageId( complete ); 00230 00231 addModule( KCModuleInfo( service ), TQStringList(), withfallback); 00232 } 00233 00234 void KCMultiDialog::addModule(const KCModuleInfo& moduleinfo, 00235 TQStringList parentmodulenames, bool withfallback) 00236 { 00237 kdDebug(710) << "KCMultiDialog::addModule " 00238 << moduleinfo.moduleName() << endl; 00239 00240 if( !moduleinfo.service() ) 00241 return; 00242 00243 if ( !kapp->authorizeControlModule( moduleinfo.service()->menuId() )) 00244 return; 00245 00246 if( !KCModuleLoader::testModule( moduleinfo )) 00247 return; 00248 00249 TQFrame* page = 0; 00250 if (!moduleinfo.service()->noDisplay()) 00251 switch( dialogface ) 00252 { 00253 case TreeList: 00254 parentmodulenames += moduleinfo.moduleName(); 00255 page = addHBoxPage( parentmodulenames, moduleinfo.comment(), 00256 SmallIcon( moduleinfo.icon(), 00257 IconSize( KIcon::Small ) ) ); 00258 break; 00259 case IconList: 00260 page = addHBoxPage( moduleinfo.moduleName(), 00261 moduleinfo.comment(), DesktopIcon( moduleinfo.icon(), 00262 KIcon::SizeMedium ) ); 00263 break; 00264 case Plain: 00265 page = plainPage(); 00266 ( new TQHBoxLayout( page ) )->setAutoAdd( true ); 00267 break; 00268 default: 00269 kdError( 710 ) << "unsupported dialog face for KCMultiDialog" 00270 << endl; 00271 break; 00272 } 00273 if(!page) { 00274 KCModuleLoader::unloadModule(moduleinfo); 00275 return; 00276 } 00277 KCModuleProxy * module; 00278 if( m_orphanModules.contains( moduleinfo.service() ) ) 00279 { 00280 // the KCModule already exists - it was removed from the dialog in 00281 // removeAllModules 00282 module = m_orphanModules[ moduleinfo.service() ]; 00283 m_orphanModules.remove( moduleinfo.service() ); 00284 kdDebug( 710 ) << "Use KCModule from the list of orphans for " << 00285 moduleinfo.moduleName() << ": " << module << endl; 00286 00287 module->reparent( page, 0, TQPoint( 0, 0 ), true ); 00288 00289 if( module->changed() ) 00290 clientChanged( true ); 00291 00292 if( activePageIndex() == -1 ) 00293 showPage( pageIndex( page ) ); 00294 } 00295 else 00296 { 00297 module = new KCModuleProxy( moduleinfo, withfallback, page ); 00298 TQStringList parentComponents = moduleinfo.service()->property( 00299 "X-KDE-ParentComponents" ).toStringList(); 00300 moduleParentComponents.insert( module, 00301 new TQStringList( parentComponents ) ); 00302 00303 connect(module, TQT_SIGNAL(changed(bool)), this, TQT_SLOT(clientChanged(bool))); 00304 00305 if( m_modules.count() == 0 ) 00306 aboutToShowPage( page ); 00307 } 00308 CreatedModule cm; 00309 cm.kcm = module; 00310 cm.service = moduleinfo.service(); 00311 m_modules.append( cm ); 00312 if ( moduleinfo.needsRootPrivileges() && 00313 !d->hasRootKCM && 00314 !KUser().isSuperUser() ) /* If we're embedded, it's true */ 00315 { 00316 d->hasRootKCM = true; 00317 showButton( User2, true ); 00318 if( plainPage() ) // returns 0 if we're not a Plain dialog 00319 slotAboutToShow( page ); // Won't be called otherwise, necessary for adminMode button 00320 } 00321 } 00322 00323 void KCMultiDialog::removeAllModules() 00324 { 00325 kdDebug( 710 ) << k_funcinfo << endl; 00326 ModuleList::Iterator end = m_modules.end(); 00327 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00328 { 00329 kdDebug( 710 ) << "remove 2" << endl; 00330 KCModuleProxy * kcm = ( *it ).kcm; 00331 TQObject * page = TQT_TQOBJECT(kcm->parent()); 00332 kcm->hide(); 00333 if( page ) 00334 { 00335 // I hate this 00336 kcm->reparent( 0, TQPoint( 0, 0 ), false ); 00337 delete page; 00338 } 00339 m_orphanModules[ ( *it ).service ] = kcm; 00340 kdDebug( 710 ) << "added KCModule to the list of orphans: " << 00341 kcm << endl; 00342 } 00343 m_modules.clear(); 00344 // all modules are gone, none can be changed 00345 clientChanged( false ); 00346 } 00347 00348 void KCMultiDialog::show() 00349 { /* KDE 4 Remove..? */ 00350 KDialogBase::show(); 00351 } 00352 00353 void KCMultiDialog::slotAboutToShow(TQWidget *page) 00354 { 00355 kdDebug(710) << k_funcinfo << endl; 00356 00357 TQObject * obj = page->child( 0, "KCModuleProxy" ); 00358 if( ! obj ) 00359 return; 00360 00361 KCModuleProxy * module = ::tqqt_cast<KCModuleProxy*>(obj); 00362 if( ! module ) 00363 return; 00364 d->currentModule = module; 00365 00366 enableButton( KDialogBase::Help, 00367 d->currentModule->buttons() & KCModule::Help ); 00368 enableButton( KDialogBase::Default, 00369 d->currentModule->buttons() & KCModule::Default ); 00370 00371 disconnect( this, TQT_SIGNAL(user2Clicked()), 0, 0 ); 00372 00373 if (d->currentModule->moduleInfo().needsRootPrivileges()) 00374 { 00375 if ( !d->currentModule->rootMode() ) 00376 { /* Enable the Admin Mode button */ 00377 enableButton( User2, true ); 00378 connect( this, TQT_SIGNAL(user2Clicked()), d->currentModule, TQT_SLOT( runAsRoot() )); 00379 connect( this, TQT_SIGNAL(user2Clicked()), TQT_SLOT( disableRModeButton() )); 00380 } 00381 else 00382 enableButton( User2, false); 00383 } 00384 } 00385 00386 void KCMultiDialog::rootExit() 00387 { 00388 enableButton( User2, true); 00389 } 00390 00391 void KCMultiDialog::disableRModeButton() 00392 { 00393 enableButton( User2, false ); 00394 connect ( d->currentModule, TQT_SIGNAL( childClosed() ), TQT_SLOT( rootExit() )); 00395 } 00396 00397 void KCMultiDialog::dialogClosed() 00398 { 00399 kdDebug(710) << k_funcinfo << endl; 00400 00401 /* If we don't delete them, the DCOP registration stays, and trying to load the KCMs 00402 * in other situations will lead to "module already loaded in Foo," while to the user 00403 * doesn't appear so(the dialog is hidden) */ 00404 ModuleList::Iterator end = m_modules.end(); 00405 for( ModuleList::Iterator it = m_modules.begin(); it != end; ++it ) 00406 ( *it ).kcm->deleteClient(); 00407 } 00408 00409 00410 // vim: sw=4 et sts=4