• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeutils
 

tdeutils

tdecmoduleproxy.cpp
00001 /*  This file is part of the KDE project
00002     Copyright (C) 2004 Frans Englich <frans.englich@telia.com>
00003     Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License version 2 as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
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             //, view( 0 )
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; // Delete before embedWidget!
00084             delete embedWidget; // Delete before embedFrame!
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; /* Contains TQScrollView view, and root stuff */
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  TODO:
00117 
00118  - How TDECModuleProxy behaves wrt memory leaks and behavior, when exiting
00119     from root mode is not tested, because no code make use of it. It needs 
00120     work, if it should be used.
00121 
00122  - Should write a document which outlines test cases, to avoid 
00123     regressions. This class is a hazard.
00124 
00125  - Two Layout problems in runAsRoot:
00126     * lblBusy doesn't show
00127     * d->kcm/d->rootInfo doesn't get it right when the user 
00128         presses cancel in the tdesu dialog
00129 
00130  - Resizing horizontally is contrained; minimum size is set somewhere. 
00131     It appears to be somehow derived from the module's size.
00132 
00133  - Prettify: set icon in KCMultiDialog.
00134 
00135  - Perhaps it's possible to link against tdesu such that 
00136     the dialog is in process?
00137 
00138  */
00139 /***************************************************************/
00140 TDECModule * TDECModuleProxy::realModule() const
00141 {
00142 
00143     /*
00144      * Note, don't call any function that calls realModule() since
00145      * that leads to an infinite loop.
00146      */
00147 
00148     kdDebug(711) << k_funcinfo << endl;
00149 
00150     /* Already loaded */
00151     if( d->kcm )
00152         return d->kcm;
00153 
00154     /* /We/ have no kcm, but tdecmshell running with root prevs does.. */
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     { /* We got the name we requested, because no one was before us, 
00180        * or, it was an random application which had picked that name */
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 && /* If the message was not yet created */
00199                 d->kcm->useRootOnlyMsg() /* and the module requests the message */ &&
00200                 moduleInfo().needsRootPrivileges() /* and the module wants root access */ && 
00201                 !KUser().isSuperUser() ) /* and we are not currently root */
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         /* Re-register as anonymous */
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         /* Figure out the name of where the module is already loaded */
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         /* Violence: Get rid of KCMError & CO, so that 
00276          * realModule() attempts to reload the module */
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     /* We have no kcm, if we're in root mode */
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     /* The DCOP registration is now gone, and it will occur again when tdecmshell soon 
00333      * registers. Here's a race condition in other words, but how likely is that?
00334      *
00335      * - It's a user initiated action, which means the user have to do weird stuff, very
00336      *   quick.
00337      * - If the user _do_ manage to fsck up, the code will recover gracefully, see realModule().
00338      *
00339      * So no worry. At the end of this function, communication with 
00340      * the DCOP object is established.
00341      */
00342 
00343     /* Prepare the process to run the tdecmshell */
00344     TQString cmd = moduleInfo().service()->exec().stripWhiteSpace();
00345     if (cmd.left(5) == "tdesu")
00346     {
00347         cmd = TQString(cmd.remove(0,5)).stripWhiteSpace();
00348 
00349         /* Remove all tdesu switches */
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     /* Run the process */
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     /* Clean up in case of failure */
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     /* Such that the "ordinary" module loads again */
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     /* This is all we do for now; all the heavy work is 
00509      * done in realModule(). It's called when the module
00510      * _actually_ is needed, in for example showEvent().
00511      * The module is loaded "on demand" -- lazy loading.
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     /* Note, we don't use d->dcopClient here, because it's used for 
00545      * the loaded module(and it's not "us" when this function is called) */
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     /* This needs fixing, perhaps cache a TDEAboutData copy
00596      * while in root mode? */
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     /* This needs fixing, perhaps cache a handbookSection() copy
00608      * while in root mode? */
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     /* This needs fixing, perhaps cache a handbookSection() copy
00620      * while in root mode? */
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 // vim: sw=4 ts=4 noet

tdeutils

Skip menu "tdeutils"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeutils

Skip menu "tdeutils"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeutils by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.