00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qapplication.h>
00021 #include <qcursor.h>
00022 #include <qdatastream.h>
00023 #include <qevent.h>
00024 #include <qfileinfo.h>
00025 #include <qframe.h>
00026 #include <qlabel.h>
00027 #include <qlayout.h>
00028 #include <qpoint.h>
00029 #include <qscrollview.h>
00030 #include <qtextstream.h>
00031 #include <qvbox.h>
00032 #include <qwhatsthis.h>
00033 #include <qwidget.h>
00034
00035 #include <dcopclient.h>
00036 #include <qxembed.h>
00037
00038 #include <kapplication.h>
00039 #include <kaboutdata.h>
00040 #include <kcmodule.h>
00041 #include <kcmoduleinfo.h>
00042 #include <kcmoduleloader.h>
00043 #include <kdebug.h>
00044 #include <kdialog.h>
00045 #include <klocale.h>
00046 #include <kprocess.h>
00047 #include <kservice.h>
00048 #include <kstandarddirs.h>
00049 #include <kuser.h>
00050
00051 #include <X11/Xlib.h>
00052
00053 #include "kcmoduleproxy.h"
00054 #include "kcmoduleproxyIface.h"
00055 #include "kcmoduleproxyIfaceImpl.h"
00056
00057
00058 class KCModuleProxy::KCModuleProxyPrivate
00059 {
00060 public:
00061 KCModuleProxyPrivate( const KCModuleInfo & info )
00062 : args( 0 )
00063 , kcm( 0 )
00064
00065 , embedWidget( 0 )
00066 , rootProcess ( 0 )
00067 , embedFrame ( 0 )
00068 , dcopObject( 0 )
00069 , dcopClient( 0 )
00070 , topLayout( 0 )
00071 , rootCommunicator( 0 )
00072 , rootInfo( 0 )
00073 , modInfo( info )
00074 , withFallback( false )
00075 , changed( false )
00076 , rootMode( false )
00077 , bogusOccupier( false )
00078 , isInitialized( false )
00079 {}
00080
00081 ~KCModuleProxyPrivate()
00082 {
00083 delete rootInfo;
00084 delete embedWidget;
00085 delete embedFrame;
00086 delete dcopClient;
00087 delete dcopObject;
00088 delete rootCommunicator;
00089 delete rootProcess;
00090 delete kcm;
00091 }
00092
00093 QStringList args;
00094 KCModule *kcm;
00095 QXEmbed *embedWidget;
00096 KProcess *rootProcess;
00097 QVBox *embedFrame;
00098 KCModuleProxyIfaceImpl *dcopObject;
00099 DCOPClient *dcopClient;
00100 QVBoxLayout *topLayout;
00101 KCModuleProxyRootCommunicatorImpl *rootCommunicator;
00102 QLabel *rootInfo;
00103 QCString dcopName;
00104 KCModuleInfo modInfo;
00105 bool withFallback;
00106 bool changed;
00107 bool rootMode;
00108 bool bogusOccupier;
00109 bool isInitialized;
00110 };
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 KCModule * KCModuleProxy::realModule() const
00141 {
00142
00143
00144
00145
00146
00147
00148 kdDebug(711) << k_funcinfo << endl;
00149
00150
00151 if( d->kcm )
00152 return d->kcm;
00153
00154
00155 if( d->rootMode )
00156 return 0;
00157
00158 QApplication::setOverrideCursor( Qt::WaitCursor );
00159
00160 KCModuleProxy * that = const_cast<KCModuleProxy*>( this );
00161
00162 if( !d->isInitialized )
00163 {
00164 d->dcopName = moduleInfo().handle().prepend("KCModuleProxy-").utf8();
00165 d->topLayout = new QVBoxLayout( that, 0, 0, "topLayout" );
00166
00167 d->isInitialized = true;
00168 }
00169
00170 if( !d->dcopClient )
00171 d->dcopClient = new DCOPClient();
00172
00173 if( !d->dcopClient->isRegistered() )
00174 d->dcopClient->registerAs( d->dcopName, false );
00175
00176 d->dcopClient->setAcceptCalls( true );
00177
00178 if( d->dcopClient->appId() == d->dcopName || d->bogusOccupier )
00179 {
00180
00181 kdDebug(711) << "Module not already loaded, loading module" << endl;
00182
00183 d->dcopObject = new KCModuleProxyIfaceImpl( d->dcopName, that );
00184
00185 d->kcm = KCModuleLoader::loadModule( moduleInfo(), KCModuleLoader::Inline, d->withFallback,
00186 that, name(), d->args );
00187
00188 connect( d->kcm, SIGNAL( changed( bool ) ),
00189 SLOT(moduleChanged(bool)) );
00190 connect( d->kcm, SIGNAL( destroyed() ),
00191 SLOT( moduleDestroyed() ) );
00192 connect( d->kcm, SIGNAL(quickHelpChanged()),
00193 SIGNAL(quickHelpChanged()));
00194 QWhatsThis::add( that, d->kcm->quickHelp() );
00195
00196 d->topLayout->addWidget( d->kcm );
00197
00198 if ( !d->rootInfo &&
00199 moduleInfo().needsRootPrivileges() &&
00200 !KUser().isSuperUser() )
00201 {
00202
00203 d->rootInfo = new QLabel( that, "rootInfo" );
00204 d->topLayout->insertWidget( 0, d->rootInfo );
00205
00206 d->rootInfo->setFrameShape(QFrame::Box);
00207 d->rootInfo->setFrameShadow(QFrame::Raised);
00208
00209 const QString msg = d->kcm->rootOnlyMsg();
00210 if( msg.isEmpty() )
00211 d->rootInfo->setText(i18n(
00212 "<b>Changes in this section requires root access.</b><br />"
00213 "Click the \"Administrator Mode\" button to "
00214 "allow modifications."));
00215 else
00216 d->rootInfo->setText(msg);
00217
00218 QWhatsThis::add( d->rootInfo, i18n(
00219 "This section requires special permissions, probably "
00220 "for system-wide changes; therefore, it is "
00221 "required that you provide the root password to be "
00222 "able to change the module's properties. If "
00223 "you do not provide the password, the module will be "
00224 "disabled."));
00225 }
00226 }
00227 else
00228 {
00229 kdDebug(711) << "Module already loaded, loading KCMError" << endl;
00230
00231 d->dcopClient->detach();
00232
00233 d->dcopClient->attach();
00234
00235 d->dcopClient->setNotifications( true );
00236 connect( d->dcopClient, SIGNAL( applicationRemoved( const QCString& )),
00237 SLOT( applicationRemoved( const QCString& )));
00238
00239
00240 QByteArray replyData, data;
00241 QCString replyType;
00242 QString result;
00243 QDataStream arg, stream( replyData, IO_ReadOnly );
00244
00245 if( d->dcopClient->call( d->dcopName, d->dcopName, "applicationName()",
00246 data, replyType, replyData ))
00247 {
00248 stream >> result;
00249
00250 d->kcm = KCModuleLoader::reportError( KCModuleLoader::Inline,
00251 i18n( "Argument is application name", "This configuration section is "
00252 "already opened in %1" ).arg( result ), " ", that );
00253
00254 d->topLayout->addWidget( d->kcm );
00255 }
00256 else
00257 {
00258 kdDebug(711) << "Calling KCModuleProxy's DCOP interface for fetching the name failed." << endl;
00259 d->bogusOccupier = true;
00260 QApplication::restoreOverrideCursor();
00261 return realModule();
00262 }
00263 }
00264
00265 QApplication::restoreOverrideCursor();
00266
00267 return d->kcm;
00268 }
00269
00270 void KCModuleProxy::applicationRemoved( const QCString& app )
00271 {
00272 if( app == d->dcopName )
00273 {
00274
00275
00276 delete d->kcm;
00277 d->kcm = 0;
00278 d->dcopClient->setNotifications( false );
00279 realModule();
00280 d->kcm->show();
00281 }
00282 }
00283
00284 void KCModuleProxy::showEvent( QShowEvent * ev )
00285 {
00286
00287 kdDebug(711) << k_funcinfo << endl;
00288 ( void )realModule();
00289
00290
00291 if( d->kcm )
00292 d->kcm->show();
00293
00294 QWidget::showEvent( ev );
00295
00296 }
00297
00298 void KCModuleProxy::runAsRoot()
00299 {
00300 if ( !moduleInfo().needsRootPrivileges() )
00301 return;
00302
00303 QApplication::setOverrideCursor( Qt::WaitCursor );
00304
00305 delete d->rootProcess;
00306 delete d->embedWidget;
00307 delete d->embedFrame;
00308
00309 d->embedFrame = new QVBox( this, "embedFrame" );
00310 d->embedFrame->setFrameStyle( QFrame::Box | QFrame::Raised );
00311
00312 QPalette pal( red );
00313 pal.setColor( QColorGroup::Background,
00314 colorGroup().background() );
00315 d->embedFrame->setPalette( pal );
00316 d->embedFrame->setLineWidth( 2 );
00317 d->embedFrame->setMidLineWidth( 2 );
00318 d->topLayout->addWidget(d->embedFrame,1);
00319
00320 d->embedWidget = new QXEmbed( d->embedFrame, "embedWidget" );
00321
00322 d->embedFrame->show();
00323
00324 QLabel *lblBusy = new QLabel(i18n("<big>Loading...</big>"), d->embedWidget, "lblBusy" );
00325 lblBusy->setTextFormat(RichText);
00326 lblBusy->setAlignment(AlignCenter);
00327 lblBusy->setGeometry(0,0, d->kcm->width(), d->kcm->height());
00328 lblBusy->show();
00329
00330 deleteClient();
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 QString cmd = moduleInfo().service()->exec().stripWhiteSpace();
00344 if (cmd.left(5) == "kdesu")
00345 {
00346 cmd = cmd.remove(0,5).stripWhiteSpace();
00347
00348
00349 while( cmd.length() > 1 && cmd[ 0 ] == '-' )
00350 cmd = cmd.remove( 0, cmd.find( ' ' ) ).stripWhiteSpace();
00351 }
00352
00353 if (cmd.left(8) == "kcmshell")
00354 cmd = cmd.remove(0,8).stripWhiteSpace();
00355
00356
00357 QString kdesu = KStandardDirs::findExe("kdesu");
00358 if (!kdesu.isEmpty())
00359 {
00360
00361 d->rootProcess = new KProcess;
00362
00363 *d->rootProcess << kdesu;
00364 *d->rootProcess << "--nonewdcop" << "-n" << "-d" << QString( "-i%1" ).arg(moduleInfo().icon());
00365
00366 *d->rootProcess << QString("%1 %2 --embed-proxy %3 --lang %4").arg(locate("exe", "kcmshell"))
00367 .arg(cmd).arg(d->embedWidget->winId()).arg(KGlobal::locale()->language());
00368
00369 connect(d->rootProcess, SIGNAL(processExited(KProcess*)), SLOT(rootExited()));
00370
00371 if ( !d->rootProcess->start( KProcess::NotifyOnExit ))
00372 {
00373 d->rootMode = false;
00374 rootExited();
00375 }
00376 else
00377 {
00378 d->rootMode = true;
00379 kapp->dcopClient();
00380 d->rootCommunicator = new KCModuleProxyRootCommunicatorImpl( d->dcopName + "-RootCommunicator", this );
00381 }
00382
00383 delete lblBusy;
00384 QApplication::restoreOverrideCursor();
00385 return;
00386 }
00387
00388
00389 delete d->embedWidget;
00390 d->embedWidget = 0;
00391 delete d->embedFrame;
00392 d->embedFrame = 0;
00393
00394 QApplication::restoreOverrideCursor();
00395 }
00396
00397 void KCModuleProxy::rootExited()
00398 {
00399 kdDebug(711) << k_funcinfo << endl;
00400
00401 if ( d->embedWidget->embeddedWinId() )
00402 XDestroyWindow(qt_xdisplay(), d->embedWidget->embeddedWinId());
00403
00404 delete d->embedWidget;
00405 d->embedWidget = 0;
00406
00407 delete d->rootProcess;
00408 d->rootProcess = 0;
00409
00410 delete d->embedFrame;
00411 d->embedFrame=0;
00412
00413 delete d->rootCommunicator;
00414 d->rootCommunicator = 0;
00415
00416
00417 d->rootMode = false;
00418
00419 d->topLayout->invalidate();
00420
00421 QShowEvent ev;
00422 showEvent( &ev );
00423
00424 moduleChanged( false );
00425 emit childClosed();
00426 }
00427
00428 KCModuleProxy::~KCModuleProxy()
00429 {
00430 deleteClient();
00431 KCModuleLoader::unloadModule(moduleInfo());
00432
00433 delete d;
00434 }
00435
00436 void KCModuleProxy::deleteClient()
00437 {
00438 if( d->embedWidget )
00439 XKillClient(qt_xdisplay(), d->embedWidget->embeddedWinId());
00440
00441
00442 delete d->kcm;
00443 d->kcm = 0;
00444
00445 delete d->dcopObject;
00446 d->dcopObject = 0;
00447
00448 if( d->dcopClient && !d->dcopClient->detach() )
00449 kdDebug(711) << "Unregistering from DCOP failed." << endl;
00450
00451 delete d->dcopClient;
00452 d->dcopClient = 0;
00453
00454 kapp->syncX();
00455
00456 }
00457
00458 void KCModuleProxy::moduleChanged( bool c )
00459 {
00460 if( d->changed == c )
00461 return;
00462
00463 d->changed = c;
00464 emit changed( c );
00465 emit changed( this );
00466 }
00467
00468 void KCModuleProxy::moduleDestroyed()
00469 {
00470 d->kcm = 0;
00471 }
00472
00473 KCModuleProxy::KCModuleProxy( const KService::Ptr & service, bool withFallback,
00474 QWidget * parent, const char * name, const QStringList & args)
00475 : QWidget( parent, name )
00476 {
00477 init( KCModuleInfo( service ));
00478 d->args = args;
00479 d->withFallback = withFallback;
00480 }
00481
00482 KCModuleProxy::KCModuleProxy( const KCModuleInfo & info, bool withFallback,
00483 QWidget * parent, const char * name, const QStringList & args )
00484 : QWidget( parent, name )
00485 {
00486 init( info );
00487 d->args = args;
00488 d->withFallback = withFallback;
00489 }
00490
00491 KCModuleProxy::KCModuleProxy( const QString& serviceName, bool withFallback,
00492 QWidget * parent, const char * name,
00493 const QStringList & args)
00494 : QWidget( parent, name )
00495 {
00496 init( KCModuleInfo( serviceName ));
00497 d->args = args;
00498 d->withFallback = withFallback;
00499 }
00500
00501 void KCModuleProxy::init( const KCModuleInfo& info )
00502 {
00503 kdDebug(711) << k_funcinfo << endl;
00504
00505 d = new KCModuleProxyPrivate( info );
00506
00507
00508
00509
00510
00511
00512
00513 }
00514
00515 void KCModuleProxy::load()
00516 {
00517
00518 if( d->rootMode )
00519 callRootModule( "load()" );
00520 else if( realModule() )
00521 {
00522 d->kcm->load();
00523 moduleChanged( false );
00524 }
00525 }
00526
00527 void KCModuleProxy::save()
00528 {
00529 if( d->rootMode )
00530 callRootModule( "save()" );
00531 else if( d->changed && realModule() )
00532 {
00533 d->kcm->save();
00534 moduleChanged( false );
00535 }
00536 }
00537
00538 void KCModuleProxy::callRootModule( const QCString& function )
00539 {
00540 QByteArray sendData, replyData;
00541 QCString replyType;
00542
00543
00544
00545 if( !kapp->dcopClient()->call( d->dcopName, d->dcopName, function, sendData,
00546 replyType, replyData, true, -1 ))
00547 kdDebug(711) << "Calling function '" << function << "' failed." << endl;
00548
00549 }
00550
00551 void KCModuleProxy::defaults()
00552 {
00553 if( d->rootMode )
00554 callRootModule( "defaults()" );
00555 if( realModule() )
00556 d->kcm->defaults();
00557 }
00558
00559 QString KCModuleProxy::quickHelp() const
00560 {
00561
00562 if( !d->rootMode )
00563 return realModule() ? realModule()->quickHelp() : QString::null;
00564 else
00565 {
00566 QByteArray data, replyData;
00567 QCString replyType;
00568
00569 if (kapp->dcopClient()->call(d->dcopName, d->dcopName, "quickHelp()",
00570 data, replyType, replyData))
00571 kdDebug(711) << "Calling DCOP function bool changed() failed." << endl;
00572 else
00573 {
00574 QDataStream reply(replyData, IO_ReadOnly);
00575 if (replyType == "QString")
00576 {
00577 QString result;
00578 reply >> result;
00579 return result;
00580 }
00581 else
00582 kdDebug(711) << "DCOP function changed() returned mumbo jumbo." << endl;
00583 }
00584 return QString::null;
00585 }
00586 }
00587
00588 const KAboutData * KCModuleProxy::aboutData() const
00589 {
00590 if( !d->rootMode )
00591 return realModule() ? realModule()->aboutData() : 0;
00592 else
00593
00594
00595 return 0;
00596
00597
00598 }
00599
00600 int KCModuleProxy::buttons() const
00601 {
00602 return realModule() ? realModule()->buttons() :
00603 KCModule::Help | KCModule::Default | KCModule::Apply ;
00604 }
00605
00606 QString KCModuleProxy::rootOnlyMsg() const
00607 {
00608 return realModule() ? realModule()->rootOnlyMsg() : QString::null;
00609 }
00610
00611 bool KCModuleProxy::useRootOnlyMsg() const
00612 {
00613 return realModule() ? realModule()->useRootOnlyMsg() : true;
00614 }
00615
00616 KInstance * KCModuleProxy::instance() const
00617 {
00618 return realModule() ? realModule()->instance() : 0;
00619 }
00620
00621 bool KCModuleProxy::changed() const
00622 {
00623 return d->changed;
00624 }
00625
00626 const KCModuleInfo& KCModuleProxy::moduleInfo() const
00627 {
00628 return d->modInfo;
00629 }
00630
00631 bool KCModuleProxy::rootMode() const
00632 {
00633 return d->rootMode;
00634 }
00635
00636 QCString KCModuleProxy::dcopName() const
00637 {
00638 return d->dcopName;
00639 }
00640
00641 void KCModuleProxy::emitQuickHelpChanged()
00642 {
00643 emit quickHelpChanged();
00644 }
00645
00646
00647 #include "kcmoduleproxy.moc"
00648
00649