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(
"kcmshell %1 --embed-proxy %2 --lang %3").arg(cmd).arg
00367 (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