/*
Copyright ( c ) 1999 Matthias Hoelzer - Kluepfel < hoelzer @ kde . org >
Copyright ( c ) 2000 Matthias Elter < elter @ kde . org >
Copyright ( c ) 2004 Frans Englich < frans . englich @ telia . com >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
# include <iostream>
# include <tqcstring.h>
# include <tqfile.h>
# include <dcopclient.h>
# include <qxembed.h>
# include <kaboutdata.h>
# include <kapplication.h>
# include <kcmdlineargs.h>
# include <kcmoduleinfo.h>
# include <kcmoduleloader.h>
# include <kcmoduleproxy.h>
# include <kcmultidialog.h>
# include <kdebug.h>
# include <kdialogbase.h>
# include <kiconloader.h>
# include <klocale.h>
# include <kservice.h>
# include <kservicegroup.h>
# include <kstartupinfo.h>
# include <twin.h>
# include <kglobal.h>
# include "main.h"
# include "main.moc"
using namespace std ;
KService : : List m_modules ;
static KCmdLineOptions options [ ] =
{
{ " list " , I18N_NOOP ( " List all possible modules " ) , 0 } ,
{ " +module " , I18N_NOOP ( " Configuration module to open " ) , 0 } ,
{ " lang <language> " , I18N_NOOP ( " Specify a particular language " ) , 0 } ,
{ " embed <id> " , I18N_NOOP ( " Embeds the module with buttons in window with id <id> " ) , 0 } ,
{ " embed-proxy <id> " , I18N_NOOP ( " Embeds the module without buttons in window with id <id> " ) , 0 } ,
{ " silent " , I18N_NOOP ( " Do not display main window " ) , 0 } ,
KCmdLineLastOption
} ;
static void listModules ( const TQString & baseGroup )
{
KServiceGroup : : Ptr group = KServiceGroup : : group ( baseGroup ) ;
if ( ! group | | ! group - > isValid ( ) )
return ;
KServiceGroup : : List list = group - > entries ( true , true ) ;
for ( KServiceGroup : : List : : ConstIterator it = list . begin ( ) ;
it ! = list . end ( ) ; it + + )
{
KSycocaEntry * p = ( * it ) ;
if ( p - > isType ( KST_KService ) )
{
KService * s = static_cast < KService * > ( p ) ;
if ( ! kapp - > authorizeControlModule ( s - > menuId ( ) ) )
continue ;
m_modules . append ( s ) ;
}
else if ( p - > isType ( KST_KServiceGroup ) )
listModules ( p - > entryPath ( ) ) ;
}
}
static KService : : Ptr locateModule ( const TQCString & module )
{
TQString path = TQFile : : decodeName ( module ) ;
if ( ! path . endsWith ( " .desktop " ) )
path + = " .desktop " ;
KService : : Ptr service = KService : : serviceByStorageId ( path ) ;
if ( ! service )
{
kdWarning ( 780 ) < < " Could not find module ' " < < module < < " '. " < < endl ;
return 0 ;
}
// avoid finding random non-TDE applications
if ( module . left ( 4 ) ! = " kde- " & & service - > library ( ) . isEmpty ( ) )
return locateModule ( " kde- " + module ) ;
if ( ! KCModuleLoader : : testModule ( module ) )
{
kdDebug ( 780 ) < < " According to \" " < < module < < " \" 's test function, it should Not be loaded. " < < endl ;
return 0 ;
}
return service ;
}
bool KCMShell : : isRunning ( )
{
if ( dcopClient ( ) - > appId ( ) = = m_dcopName )
return false ; // We are the one and only.
kdDebug ( 780 ) < < " kcmshell with modules ' " < <
m_dcopName < < " ' is already running. " < < endl ;
dcopClient ( ) - > attach ( ) ; // Reregister as anonymous
dcopClient ( ) - > setNotifications ( true ) ;
TQByteArray data ;
TQDataStream str ( data , IO_WriteOnly ) ;
str < < kapp - > startupId ( ) ;
TQCString replyType ;
TQByteArray replyData ;
if ( ! dcopClient ( ) - > call ( m_dcopName , " dialog " , " activate(TQCString) " ,
data , replyType , replyData ) )
{
kdDebug ( 780 ) < < " Calling DCOP function dialog::activate() failed. " < < endl ;
return false ; // Error, we have to do it ourselves.
}
return true ;
}
KCMShellMultiDialog : : KCMShellMultiDialog ( int dialogFace , const TQString & caption ,
TQWidget * parent , const char * name , bool modal )
: KCMultiDialog ( dialogFace , caption , parent , name , modal ) ,
DCOPObject ( " dialog " )
{
}
void KCMShellMultiDialog : : activate ( TQCString asn_id )
{
kdDebug ( 780 ) < < k_funcinfo < < endl ;
KStartupInfo : : setNewStartupId ( this , asn_id ) ;
}
void KCMShell : : setDCOPName ( const TQCString & dcopName , bool rootMode )
{
m_dcopName = " kcmshell_ " ;
if ( rootMode )
m_dcopName + = " rootMode_ " ;
m_dcopName + = dcopName ;
dcopClient ( ) - > registerAs ( m_dcopName , false ) ;
}
void KCMShell : : waitForExit ( )
{
kdDebug ( 780 ) < < k_funcinfo < < endl ;
connect ( dcopClient ( ) , TQT_SIGNAL ( applicationRemoved ( const TQCString & ) ) ,
TQT_SLOT ( appExit ( const TQCString & ) ) ) ;
exec ( ) ;
}
void KCMShell : : appExit ( const TQCString & appId )
{
kdDebug ( 780 ) < < k_funcinfo < < endl ;
if ( appId = = m_dcopName )
{
kdDebug ( 780 ) < < " ' " < < appId < < " ' closed, dereferencing. " < < endl ;
deref ( ) ;
}
}
static void setIcon ( TQWidget * w , const TQString & iconName )
{
TQPixmap icon = DesktopIcon ( iconName ) ;
TQPixmap miniIcon = SmallIcon ( iconName ) ;
w - > setIcon ( icon ) ; //standard X11
# if defined Q_WS_X11 && ! defined K_WS_QTONLY
KWin : : setIcons ( w - > winId ( ) , icon , miniIcon ) ;
# endif
}
extern " C " KDE_EXPORT int kdemain ( int _argc , char * _argv [ ] )
{
KAboutData aboutData ( " kcmshell " , I18N_NOOP ( " TDE Control Module " ) ,
0 ,
I18N_NOOP ( " A tool to start single TDE control modules " ) ,
KAboutData : : License_GPL ,
I18N_NOOP ( " (c) 1999-2004, The KDE Developers " ) ) ;
aboutData . addAuthor ( " Frans Englich " , I18N_NOOP ( " Maintainer " ) , " frans.englich@kde.org " ) ;
aboutData . addAuthor ( " Daniel Molkentin " , 0 , " molkentin@kde.org " ) ;
aboutData . addAuthor ( " Matthias Hoelzer-Kluepfel " , 0 , " hoelzer@kde.org " ) ;
aboutData . addAuthor ( " Matthias Elter " , 0 , " elter@kde.org " ) ;
aboutData . addAuthor ( " Matthias Ettrich " , 0 , " ettrich@kde.org " ) ;
aboutData . addAuthor ( " Waldo Bastian " , 0 , " bastian@kde.org " ) ;
KGlobal : : locale ( ) - > setMainCatalogue ( " kcmshell " ) ;
TDECmdLineArgs : : init ( _argc , _argv , & aboutData ) ;
TDECmdLineArgs : : addCmdLineOptions ( options ) ; // Add our own options.
KCMShell app ;
const TDECmdLineArgs * args = TDECmdLineArgs : : parsedArgs ( ) ;
const TQCString lang = args - > getOption ( " lang " ) ;
if ( ! lang . isNull ( ) )
KGlobal : : locale ( ) - > setLanguage ( lang ) ;
if ( args - > isSet ( " list " ) )
{
cout < < static_cast < const char * > ( i18n ( " The following modules are available: " ) . local8Bit ( ) ) < < endl ;
listModules ( " Settings/ " ) ;
int maxLen = 0 ;
for ( KService : : List : : ConstIterator it = m_modules . begin ( ) ; it ! = m_modules . end ( ) ; + + it )
{
int len = ( * it ) - > desktopEntryName ( ) . length ( ) ;
if ( len > maxLen )
maxLen = len ;
}
for ( KService : : List : : ConstIterator it = m_modules . begin ( ) ; it ! = m_modules . end ( ) ; + + it )
{
TQString entry ( " %1 - %2 " ) ;
entry = entry . arg ( ( * it ) - > desktopEntryName ( ) . leftJustify ( maxLen , ' ' ) )
. arg ( ! ( * it ) - > comment ( ) . isEmpty ( ) ? ( * it ) - > comment ( )
: i18n ( " No description available " ) ) ;
cout < < static_cast < const char * > ( entry . local8Bit ( ) ) < < endl ;
}
return 0 ;
}
if ( args - > count ( ) < 1 )
{
args - > usage ( ) ;
return - 1 ;
}
TQCString dcopName ;
KService : : List modules ;
for ( int i = 0 ; i < args - > count ( ) ; i + + )
{
KService : : Ptr service = locateModule ( args - > arg ( i ) ) ;
if ( service )
{
modules . append ( service ) ;
if ( ! dcopName . isEmpty ( ) )
dcopName + = " _ " ;
dcopName + = args - > arg ( i ) ;
}
}
/* Check if this particular module combination is already running, but
* allow the same module to run when embedding ( root mode ) */
app . setDCOPName ( dcopName ,
( args - > isSet ( " embed-proxy " ) | | args - > isSet ( " embed " ) ) ) ;
if ( app . isRunning ( ) )
{
app . waitForExit ( ) ;
return 0 ;
}
//KDialogBase::DialogType dtype = KDialogBase::Plain; // FIXME
KDialogBase : : DialogType dtype = KDialogBase : : IconList ; // Work around a bug whereby several kcontrol modules (such as displayconfig) use an incorrect size when loaded with kcmshell in the Plain mode
// This bug is possibly related to kcmultidialog.cpp:266 [( new TQHBoxLayout( page ) )->setAutoAdd( true );]
// In fact, this method of display may be preferable to the Plain mode from a UX perspective,
// as the icon shows the user what the active kcontrol module is called.
if ( modules . count ( ) < 1 )
return 0 ;
else if ( modules . count ( ) > 1 )
dtype = KDialogBase : : IconList ;
bool idValid ;
int id ;
if ( args - > isSet ( " embed-proxy " ) )
{
id = args - > getOption ( " embed-proxy " ) . toInt ( & idValid ) ;
if ( idValid )
{
KCModuleProxy * module = new KCModuleProxy ( modules . first ( ) - > desktopEntryName ( ) ) ;
module - > realModule ( ) ;
QXEmbed : : embedClientIntoWindow ( module , id ) ;
app . exec ( ) ;
delete module ;
}
else
kdDebug ( 780 ) < < " Supplied id ' " < < id < < " ' is not valid. " < < endl ;
return 0 ;
}
KCMShellMultiDialog * dlg = new KCMShellMultiDialog ( dtype ,
i18n ( " Configure - %1 " ) . arg ( kapp - > caption ( ) ) , 0 , " " , true ) ;
for ( KService : : List : : ConstIterator it = modules . begin ( ) ; it ! = modules . end ( ) ; + + it )
dlg - > addModule ( KCModuleInfo ( * it ) ) ;
if ( args - > isSet ( " embed " ) )
{
id = args - > getOption ( " embed " ) . toInt ( & idValid ) ;
if ( idValid )
{
QXEmbed : : embedClientIntoWindow ( dlg , id ) ;
dlg - > exec ( ) ;
delete dlg ;
}
else
kdDebug ( 780 ) < < " Supplied id ' " < < id < < " ' is not valid. " < < endl ;
}
else
{
if ( kapp - > iconName ( ) ! = kapp - > name ( ) )
setIcon ( dlg , kapp - > iconName ( ) ) ;
else if ( modules . count ( ) = = 1 )
setIcon ( dlg , KCModuleInfo ( modules . first ( ) ) . icon ( ) ) ;
dlg - > exec ( ) ;
delete dlg ;
}
return 0 ;
}
// vim: sw=4 et sts=4