00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <tqapplication.h>
00021 #include <tqcursor.h>
00022 #include <tqdatastream.h>
00023 #include <tqevent.h>
00024 #include <tqfileinfo.h>
00025 #include <tqframe.h>
00026 #include <tqlabel.h>
00027 #include <tqlayout.h>
00028 #include <tqpoint.h>
00029 #include <tqscrollview.h>
00030 #include <tqtextstream.h>
00031 #include <tqvbox.h>
00032 #include <tqwhatsthis.h>
00033 #include <tqwidget.h>
00034
00035 #include <dcopclient.h>
00036 #include <qxembed.h>
00037
00038 #include <tdeapplication.h>
00039 #include <tdeaboutdata.h>
00040 #include <tdecmodule.h>
00041 #include <tdecmoduleinfo.h>
00042 #include <tdecmoduleloader.h>
00043 #include <kdebug.h>
00044 #include <kdialog.h>
00045 #include <tdelocale.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 "tdecmoduleproxy.h"
00054 #include "tdecmoduleproxyIface.h"
00055 #include "tdecmoduleproxyIfaceImpl.h"
00056
00057
00058 class TDECModuleProxy::TDECModuleProxyPrivate
00059 {
00060 public:
00061 TDECModuleProxyPrivate( const TDECModuleInfo & 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 ~TDECModuleProxyPrivate()
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 TQStringList args;
00094 TDECModule *kcm;
00095 QXEmbed *embedWidget;
00096 TDEProcess *rootProcess;
00097 TQVBox *embedFrame;
00098 TDECModuleProxyIfaceImpl *dcopObject;
00099 DCOPClient *dcopClient;
00100 TQVBoxLayout *topLayout;
00101 TDECModuleProxyRootCommunicatorImpl *rootCommunicator;
00102 TQLabel *rootInfo;
00103 TQCString dcopName;
00104 TDECModuleInfo 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 TDECModule * TDECModuleProxy::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 TQApplication::setOverrideCursor( Qt::WaitCursor );
00159
00160 TDECModuleProxy * that = const_cast<TDECModuleProxy*>( this );
00161
00162 if( !d->isInitialized )
00163 {
00164 d->dcopName = TQString(moduleInfo().handle().prepend("TDECModuleProxy-")).utf8();
00165 d->topLayout = new TQVBoxLayout( 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 TDECModuleProxyIfaceImpl( d->dcopName, that );
00184
00185 d->kcm = TDECModuleLoader::loadModule( moduleInfo(), TDECModuleLoader::Inline, d->withFallback,
00186 that, name(), d->args );
00187
00188 connect( d->kcm, TQT_SIGNAL( changed( bool ) ),
00189 TQT_SLOT(moduleChanged(bool)) );
00190 connect( d->kcm, TQT_SIGNAL( destroyed() ),
00191 TQT_SLOT( moduleDestroyed() ) );
00192 connect( d->kcm, TQT_SIGNAL(quickHelpChanged()),
00193 TQT_SIGNAL(quickHelpChanged()));
00194 TQWhatsThis::add( that, d->kcm->quickHelp() );
00195
00196 d->topLayout->addWidget( d->kcm );
00197
00198 if ( !d->rootInfo &&
00199 d->kcm->useRootOnlyMsg() &&
00200 moduleInfo().needsRootPrivileges() &&
00201 !KUser().isSuperUser() )
00202 {
00203
00204 d->rootInfo = new TQLabel( that, "rootInfo" );
00205 d->topLayout->insertWidget( 0, d->rootInfo );
00206
00207 d->rootInfo->setFrameShape(TQFrame::Box);
00208 d->rootInfo->setFrameShadow(TQFrame::Raised);
00209
00210 const TQString msg = d->kcm->rootOnlyMsg();
00211 if( msg.isEmpty() )
00212 d->rootInfo->setText(i18n(
00213 "<b>Changes in this section requires root access.</b><br />"
00214 "Click the \"Administrator Mode\" button to "
00215 "allow modifications."));
00216 else
00217 d->rootInfo->setText(msg);
00218
00219 TQWhatsThis::add( d->rootInfo, i18n(
00220 "This section requires special permissions, probably "
00221 "for system-wide changes; therefore, it is "
00222 "required that you provide the root password to be "
00223 "able to change the module's properties. If "
00224 "you do not provide the password, the module will be "
00225 "disabled."));
00226 }
00227 }
00228 else
00229 {
00230 kdDebug(711) << "Module already loaded, loading KCMError" << endl;
00231
00232 d->dcopClient->detach();
00233
00234 d->dcopClient->attach();
00235
00236 d->dcopClient->setNotifications( true );
00237 connect( d->dcopClient, TQT_SIGNAL( applicationRemoved( const TQCString& )),
00238 TQT_SLOT( applicationRemoved( const TQCString& )));
00239
00240
00241 TQByteArray replyData, data;
00242 TQCString replyType;
00243 TQString result;
00244 TQDataStream arg, stream( replyData, IO_ReadOnly );
00245
00246 if( d->dcopClient->call( d->dcopName, d->dcopName, "applicationName()",
00247 data, replyType, replyData ))
00248 {
00249 stream >> result;
00250
00251 d->kcm = TDECModuleLoader::reportError( TDECModuleLoader::Inline,
00252 i18n( "Argument is application name", "This configuration section is "
00253 "already opened in %1" ).arg( result ), " ", that );
00254
00255 d->topLayout->addWidget( d->kcm );
00256 }
00257 else
00258 {
00259 kdDebug(711) << "Calling TDECModuleProxy's DCOP interface for fetching the name failed." << endl;
00260 d->bogusOccupier = true;
00261 TQApplication::restoreOverrideCursor();
00262 return realModule();
00263 }
00264 }
00265
00266 TQApplication::restoreOverrideCursor();
00267
00268 return d->kcm;
00269 }
00270
00271 void TDECModuleProxy::applicationRemoved( const TQCString& app )
00272 {
00273 if( app == d->dcopName )
00274 {
00275
00276
00277 delete d->kcm;
00278 d->kcm = 0;
00279 d->dcopClient->setNotifications( false );
00280 realModule();
00281 d->kcm->show();
00282 }
00283 }
00284
00285 void TDECModuleProxy::showEvent( TQShowEvent * ev )
00286 {
00287
00288 kdDebug(711) << k_funcinfo << endl;
00289 ( void )realModule();
00290
00291
00292 if( d->kcm )
00293 d->kcm->show();
00294
00295 TQWidget::showEvent( ev );
00296
00297 }
00298
00299 void TDECModuleProxy::runAsRoot()
00300 {
00301 if ( !moduleInfo().needsRootPrivileges() )
00302 return;
00303
00304 TQApplication::setOverrideCursor( Qt::WaitCursor );
00305
00306 delete d->rootProcess;
00307 delete d->embedWidget;
00308 delete d->embedFrame;
00309
00310 d->embedFrame = new TQVBox( this, "embedFrame" );
00311 d->embedFrame->setFrameStyle( TQFrame::Box | TQFrame::Raised );
00312
00313 TQPalette pal( red );
00314 pal.setColor( TQColorGroup::Background,
00315 colorGroup().background() );
00316 d->embedFrame->setPalette( pal );
00317 d->embedFrame->setLineWidth( 2 );
00318 d->embedFrame->setMidLineWidth( 2 );
00319 d->topLayout->addWidget(d->embedFrame,1);
00320
00321 d->embedWidget = new QXEmbed( d->embedFrame, "embedWidget" );
00322
00323 d->embedFrame->show();
00324
00325 TQLabel *lblBusy = new TQLabel(i18n("<big>Loading...</big>"), d->embedWidget, "lblBusy" );
00326 lblBusy->setTextFormat(RichText);
00327 lblBusy->setAlignment(AlignCenter);
00328 lblBusy->setGeometry(0,0, d->kcm->width(), d->kcm->height());
00329 lblBusy->show();
00330
00331 deleteClient();
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 TQString cmd = moduleInfo().service()->exec().stripWhiteSpace();
00345 if (cmd.left(5) == "tdesu")
00346 {
00347 cmd = TQString(cmd.remove(0,5)).stripWhiteSpace();
00348
00349
00350 while( cmd.length() > 1 && cmd[ 0 ] == '-' )
00351 cmd = TQString(cmd.remove( 0, cmd.find( ' ' ) )).stripWhiteSpace();
00352 }
00353
00354 if (cmd.left(8) == "tdecmshell")
00355 cmd = TQString(cmd.remove(0,8)).stripWhiteSpace();
00356
00357
00358 TQString tdesu = TDEStandardDirs::findExe("tdesu");
00359 if (!tdesu.isEmpty())
00360 {
00361
00362 d->rootProcess = new TDEProcess;
00363
00364 *d->rootProcess << tdesu;
00365 *d->rootProcess << "--nonewdcop" << "-n" << "-d" << TQString( "-i%1" ).arg(moduleInfo().icon());
00366
00367 *d->rootProcess << TQString("%1 %2 --embed-proxy %3 --lang %4").arg(locate("exe", "tdecmshell"))
00368 .arg(cmd).arg(d->embedWidget->winId()).arg(TDEGlobal::locale()->language());
00369
00370 connect(d->rootProcess, TQT_SIGNAL(processExited(TDEProcess*)), TQT_SLOT(rootExited()));
00371
00372 if ( !d->rootProcess->start( TDEProcess::NotifyOnExit ))
00373 {
00374 d->rootMode = false;
00375 rootExited();
00376 }
00377 else
00378 {
00379 d->rootMode = true;
00380 kapp->dcopClient();
00381 d->rootCommunicator = new TDECModuleProxyRootCommunicatorImpl( d->dcopName + "-RootCommunicator", this );
00382 }
00383
00384 delete lblBusy;
00385 TQApplication::restoreOverrideCursor();
00386 return;
00387 }
00388
00389
00390 delete d->embedWidget;
00391 d->embedWidget = 0;
00392 delete d->embedFrame;
00393 d->embedFrame = 0;
00394
00395 TQApplication::restoreOverrideCursor();
00396 }
00397
00398 void TDECModuleProxy::rootExited()
00399 {
00400 kdDebug(711) << k_funcinfo << endl;
00401
00402 if ( d->embedWidget->embeddedWinId() )
00403 XDestroyWindow(tqt_xdisplay(), d->embedWidget->embeddedWinId());
00404
00405 delete d->embedWidget;
00406 d->embedWidget = 0;
00407
00408 delete d->rootProcess;
00409 d->rootProcess = 0;
00410
00411 delete d->embedFrame;
00412 d->embedFrame=0;
00413
00414 delete d->rootCommunicator;
00415 d->rootCommunicator = 0;
00416
00417
00418 d->rootMode = false;
00419
00420 d->topLayout->invalidate();
00421
00422 TQShowEvent ev;
00423 showEvent( &ev );
00424
00425 moduleChanged( false );
00426 emit childClosed();
00427 }
00428
00429 TDECModuleProxy::~TDECModuleProxy()
00430 {
00431 deleteClient();
00432 TDECModuleLoader::unloadModule(moduleInfo());
00433
00434 delete d;
00435 }
00436
00437 void TDECModuleProxy::deleteClient()
00438 {
00439 if( d->embedWidget )
00440 XKillClient(tqt_xdisplay(), d->embedWidget->embeddedWinId());
00441
00442
00443 delete d->kcm;
00444 d->kcm = 0;
00445
00446 delete d->dcopObject;
00447 d->dcopObject = 0;
00448
00449 if( d->dcopClient && !d->dcopClient->detach() )
00450 kdDebug(711) << "Unregistering from DCOP failed." << endl;
00451
00452 delete d->dcopClient;
00453 d->dcopClient = 0;
00454
00455 kapp->syncX();
00456
00457 }
00458
00459 void TDECModuleProxy::moduleChanged( bool c )
00460 {
00461 if( d->changed == c )
00462 return;
00463
00464 d->changed = c;
00465 emit changed( c );
00466 emit changed( this );
00467 }
00468
00469 void TDECModuleProxy::moduleDestroyed()
00470 {
00471 d->kcm = 0;
00472 }
00473
00474 TDECModuleProxy::TDECModuleProxy( const KService::Ptr & service, bool withFallback,
00475 TQWidget * parent, const char * name, const TQStringList & args)
00476 : TQWidget( parent, name )
00477 {
00478 init( TDECModuleInfo( service ));
00479 d->args = args;
00480 d->withFallback = withFallback;
00481 }
00482
00483 TDECModuleProxy::TDECModuleProxy( const TDECModuleInfo & info, bool withFallback,
00484 TQWidget * parent, const char * name, const TQStringList & args )
00485 : TQWidget( parent, name )
00486 {
00487 init( info );
00488 d->args = args;
00489 d->withFallback = withFallback;
00490 }
00491
00492 TDECModuleProxy::TDECModuleProxy( const TQString& serviceName, bool withFallback,
00493 TQWidget * parent, const char * name,
00494 const TQStringList & args)
00495 : TQWidget( parent, name )
00496 {
00497 init( TDECModuleInfo( serviceName ));
00498 d->args = args;
00499 d->withFallback = withFallback;
00500 }
00501
00502 void TDECModuleProxy::init( const TDECModuleInfo& info )
00503 {
00504 kdDebug(711) << k_funcinfo << endl;
00505
00506 d = new TDECModuleProxyPrivate( info );
00507
00508
00509
00510
00511
00512
00513
00514 }
00515
00516 void TDECModuleProxy::load()
00517 {
00518
00519 if( d->rootMode )
00520 callRootModule( "load()" );
00521 else if( realModule() )
00522 {
00523 d->kcm->load();
00524 moduleChanged( false );
00525 }
00526 }
00527
00528 void TDECModuleProxy::save()
00529 {
00530 if( d->rootMode )
00531 callRootModule( "save()" );
00532 else if( d->changed && realModule() )
00533 {
00534 d->kcm->save();
00535 moduleChanged( false );
00536 }
00537 }
00538
00539 void TDECModuleProxy::callRootModule( const TQCString& function )
00540 {
00541 TQByteArray sendData, replyData;
00542 TQCString replyType;
00543
00544
00545
00546 if( !kapp->dcopClient()->call( d->dcopName, d->dcopName, function, sendData,
00547 replyType, replyData, true, -1 ))
00548 kdDebug(711) << "Calling function '" << function << "' failed." << endl;
00549
00550 }
00551
00552 void TDECModuleProxy::defaults()
00553 {
00554 if( d->rootMode )
00555 callRootModule( "defaults()" );
00556 if( realModule() )
00557 d->kcm->defaults();
00558 }
00559
00560 TQString TDECModuleProxy::quickHelp() const
00561 {
00562
00563 if( !d->rootMode )
00564 return realModule() ? realModule()->quickHelp() : TQString::null;
00565 else
00566 {
00567 TQByteArray data, replyData;
00568 TQCString replyType;
00569
00570 if (kapp->dcopClient()->call(d->dcopName, d->dcopName, "quickHelp()",
00571 data, replyType, replyData))
00572 kdDebug(711) << "Calling DCOP function bool changed() failed." << endl;
00573 else
00574 {
00575 TQDataStream reply(replyData, IO_ReadOnly);
00576 if (replyType == "TQString")
00577 {
00578 TQString result;
00579 reply >> result;
00580 return result;
00581 }
00582 else
00583 kdDebug(711) << "DCOP function changed() returned mumbo jumbo." << endl;
00584 }
00585 return TQString::null;
00586 }
00587 }
00588
00589 const TDEAboutData * TDECModuleProxy::aboutData() const
00590 {
00591 if( !d->rootMode ) {
00592 return realModule() ? realModule()->aboutData() : 0;
00593 }
00594 else {
00595
00596
00597 return 0;
00598 }
00599 }
00600
00601 TQString TDECModuleProxy::handbookDocPath() const
00602 {
00603 if( !d->rootMode ) {
00604 return realModule() ? realModule()->handbookDocPath() : TQString::null;
00605 }
00606 else {
00607
00608
00609 return TQString::null;
00610 }
00611 }
00612
00613 TQString TDECModuleProxy::handbookSection() const
00614 {
00615 if( !d->rootMode ) {
00616 return realModule() ? realModule()->handbookSection() : TQString::null;
00617 }
00618 else {
00619
00620
00621 return TQString::null;
00622 }
00623 }
00624
00625 int TDECModuleProxy::buttons() const
00626 {
00627 return realModule() ? realModule()->buttons() :
00628 TDECModule::Help | TDECModule::Default | TDECModule::Apply ;
00629 }
00630
00631 TQString TDECModuleProxy::rootOnlyMsg() const
00632 {
00633 return realModule() ? realModule()->rootOnlyMsg() : TQString::null;
00634 }
00635
00636 bool TDECModuleProxy::useRootOnlyMsg() const
00637 {
00638 return realModule() ? realModule()->useRootOnlyMsg() : true;
00639 }
00640
00641 TDEInstance * TDECModuleProxy::instance() const
00642 {
00643 return realModule() ? realModule()->instance() : 0;
00644 }
00645
00646 bool TDECModuleProxy::changed() const
00647 {
00648 return d->changed;
00649 }
00650
00651 const TDECModuleInfo& TDECModuleProxy::moduleInfo() const
00652 {
00653 return d->modInfo;
00654 }
00655
00656 bool TDECModuleProxy::rootMode() const
00657 {
00658 return d->rootMode;
00659 }
00660
00661 TQCString TDECModuleProxy::dcopName() const
00662 {
00663 return d->dcopName;
00664 }
00665
00666 void TDECModuleProxy::emitQuickHelpChanged()
00667 {
00668 emit quickHelpChanged();
00669 }
00670
00671
00672 #include "tdecmoduleproxy.moc"
00673
00674