00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include "ksettings/dialog.h"
00021
00022
00023
#include <kcmultidialog.h>
00024
#include <klocale.h>
00025
#include <kservicegroup.h>
00026
#include <kdebug.h>
00027
#include <ktrader.h>
00028
#include <kplugininfo.h>
00029
#include "ksettings/dispatcher.h"
00030
#include "ksettings/componentsdialog.h"
00031
#include <ksimpleconfig.h>
00032
#include <kstandarddirs.h>
00033
#include <kiconloader.h>
00034
#include <qvbox.h>
00035
#include <qlabel.h>
00036
#include "kcmoduleinfo.h"
00037
00038
namespace KSettings
00039 {
00040
00041
struct GroupInfo
00042 {
00043
QString id;
00044
QString name;
00045
QString comment;
00046
QString icon;
00047
int weight;
00048
QString parentid;
00049
QWidget * page;
00050 };
00051
00052
00053
00054
class PageNode
00055 {
00056
private:
00057
typedef QValueList<PageNode*> List;
00058
enum Type { KCM, Group, Root };
00059
union Value
00060 {
00061
KCModuleInfo * kcm;
00062 GroupInfo * group;
00063 };
00064 Type m_type;
00065 Value m_value;
00066
00067 Dialog * m_dialog;
00068 List m_children;
00069 PageNode * m_parent;
00070
bool m_visible;
00071
bool m_dirty;
00072
00073
protected:
00074 PageNode(
KCModuleInfo * info, PageNode * parent )
00075 : m_type( KCM )
00076 , m_parent( parent )
00077 , m_visible( true )
00078 , m_dirty( true )
00079 {
00080 m_value.kcm = info;
00081 m_dialog = parent->m_dialog;
00082 }
00083
00084 PageNode( GroupInfo & group, PageNode * parent )
00085 : m_type( Group )
00086 , m_parent( parent )
00087 , m_visible( true )
00088 , m_dirty( true )
00089 {
00090 m_value.group =
new GroupInfo( group );
00091 m_value.group->page = 0;
00092 m_dialog = parent->m_dialog;
00093 }
00094
00095
void bubbleSort( List::Iterator begin, List::Iterator end )
00096 {
00097 --
end;
00098
bool finished;
00099 List::Iterator lastswapped = begin;
00100 List::Iterator i;
00101 List::Iterator j;
00102
while( begin !=
end )
00103 {
00104 finished =
true;
00105 i = j =
end;
00106
do {
00107 --j;
00108
if( **i < **j )
00109 {
00110 finished =
false;
00111 qSwap( *i, *j );
00112 lastswapped = j;
00113 }
00114 --i;
00115 }
while( j != begin );
00116
if( finished )
00117
return;
00118 ++lastswapped;
00119 begin = lastswapped;
00120 }
00121 }
00122
00123
public:
00124 PageNode( Dialog * dialog )
00125 : m_type( Root )
00126 , m_dialog( dialog )
00127 , m_parent( 0 )
00128 , m_visible( true )
00129 , m_dirty( true )
00130 {}
00131
00132 ~PageNode()
00133 {
00134
if( KCM == m_type )
00135
delete m_value.kcm;
00136
else if( Group == m_type )
00137
delete m_value.group;
00138 List::Iterator
end = m_children.end();
00139
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00140
delete ( *it );
00141 }
00142
00143
int weight()
const
00144
{
00145
int w = ( KCM == m_type ) ? m_value.kcm->weight()
00146 : m_value.group->weight;
00147
kdDebug( 700 ) <<
k_funcinfo <<
name() <<
" " << w <<
endl;
00148
return w;
00149 }
00150
00151
bool operator<(
const PageNode & rhs )
const
00152
{
00153
return weight() < rhs.weight();
00154 }
00155
00156
bool isVisible()
00157 {
00158
if( m_dirty )
00159 {
00160
if( KCM == m_type )
00161 m_visible = m_dialog->isPluginForKCMEnabled( m_value.kcm );
00162
else
00163 {
00164 m_visible =
false;
00165 List::Iterator
end = m_children.end();
00166
for( List::Iterator it = m_children.begin(); it !=
end;
00167 ++it )
00168
if( ( *it )->isVisible() )
00169 {
00170 m_visible =
true;
00171
break;
00172 }
00173 }
00174 m_dirty =
false;
00175 }
00176
kdDebug( 700 ) <<
k_funcinfo <<
"returns " << m_visible <<
endl;
00177
return m_visible;
00178 }
00179
00180
void makeDirty()
00181 {
00182 m_dirty =
true;
00183 List::Iterator
end = m_children.end();
00184
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00185 ( *it )->makeDirty();
00186 }
00187
00188
QString name()
const
00189
{
00190
if( Root == m_type )
00191
return QString::fromAscii(
"root node" );
00192
return ( KCM == m_type ) ? m_value.kcm->moduleName()
00193 : m_value.group->
name;
00194 }
00195
00196
QStringList parentNames()
const
00197
{
00198
QStringList ret;
00199 PageNode * node = m_parent;
00200
while( node && node->m_type != Root )
00201 {
00202 ret.prepend( node->name() );
00203 node = node->m_parent;
00204 }
00205
return ret;
00206 }
00207
00208
void addToDialog(
KCMultiDialog * dlg )
00209 {
00210
kdDebug( 700 ) <<
k_funcinfo <<
"for " <<
name() <<
endl;
00211
if( ! isVisible() )
00212
return;
00213
00214
if( KCM == m_type )
00215 {
00216 dlg->
addModule( *m_value.kcm, parentNames() );
00217
return;
00218 }
00219
if( Group == m_type && 0 == m_value.group->page )
00220 {
00221
QPixmap icon;
00222
if( ! m_value.group->icon.isNull() )
00223 icon = SmallIcon( m_value.group->icon,
00224 IconSize( KIcon::Small ) );
00225
QVBox * page = dlg->
addVBoxPage( m_value.group->name,
00226 QString::null, icon );
00227
QLabel * comment =
new QLabel( m_value.group->comment, page );
00228 comment->setTextFormat( Qt::RichText );
00229 m_value.group->page = page;
00230 }
00231 List::Iterator
end = m_children.end();
00232
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00233 ( *it )->addToDialog( dlg );
00234 }
00235
00236
void removeFromDialog(
KCMultiDialog * dlg )
00237 {
00238
kdDebug( 700 ) <<
k_funcinfo <<
"for " <<
name() <<
endl;
00239
if( KCM == m_type )
00240
return;
00241
if( Root == m_type )
00242 dlg->
removeAllModules();
00243 List::Iterator
end = m_children.end();
00244
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00245 ( *it )->removeFromDialog( dlg );
00246
if( Group == m_type )
00247 {
00248
delete m_value.group->page;
00249 m_value.group->page = 0;
00250 }
00251 }
00252
00253
void sort()
00254 {
00255
kdDebug( 700 ) <<
k_funcinfo <<
name() <<
endl;
00256 List::Iterator begin = m_children.begin();
00257 List::Iterator
end = m_children.end();
00258 bubbleSort( begin, end );
00259
for( List::Iterator it = begin ; it !=
end; ++it )
00260 ( *it )->sort();
00261 }
00262
00263
bool insert( GroupInfo & group )
00264 {
00265
if( group.parentid.isNull() )
00266 {
00267
if( Root == m_type )
00268 {
00269 m_children.
append(
new PageNode( group,
this ) );
00270
return true;
00271 }
00272
else
00273
kdFatal( 700 ) <<
"wrong PageNode insertion"
00274 <<
kdBacktrace() <<
endl;
00275 }
00276
if( Group == m_type && group.parentid == m_value.group->id )
00277 {
00278 m_children.append(
new PageNode( group,
this ) );
00279
return true;
00280 }
00281 List::Iterator
end = m_children.end();
00282
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00283
if( ( *it )->insert( group ) )
00284
return true;
00285
00286
if( Root == m_type )
00287 {
00288 m_children.
append(
new PageNode( group,
this ) );
00289
return true;
00290 }
00291
return false;
00292 }
00293
00294
bool insert(
KCModuleInfo * info,
const QString & parentid )
00295 {
00296
if( parentid.isNull() )
00297 {
00298
if( Root == m_type )
00299 {
00300 m_children.
append(
new PageNode( info,
this ) );
00301
return true;
00302 }
00303
else
00304
kdFatal( 700 ) <<
"wrong PageNode insertion"
00305 <<
kdBacktrace() <<
endl;
00306 }
00307
if( Group == m_type && parentid == m_value.group->id )
00308 {
00309 m_children.append(
new PageNode( info,
this ) );
00310
return true;
00311 }
00312 List::Iterator
end = m_children.end();
00313
for( List::Iterator it = m_children.begin(); it !=
end; ++it )
00314
if( ( *it )->insert( info, parentid ) )
00315
return true;
00316
00317
if( Root == m_type )
00318 {
00319 m_children.
append(
new PageNode( info,
this ) );
00320
return true;
00321 }
00322
return false;
00323 }
00324
00325
bool needTree()
00326 {
00327 List::ConstIterator
end = m_children.end();
00328
for( List::ConstIterator it = m_children.begin(); it !=
end; ++it )
00329
if( ( *it )->m_children.count() > 0 )
00330
return true;
00331
return false;
00332 }
00333
00334
bool singleChild()
00335 {
00336
return ( m_children.count() == 1 );
00337 }
00338 };
00339
00340
class Dialog::DialogPrivate
00341 {
00342
public:
00343 DialogPrivate( Dialog * parent )
00344 : dlg( 0 )
00345 , pagetree( parent )
00346 {
00347 }
00348
00349
bool staticlistview;
00350
KCMultiDialog * dlg;
00351 PageNode pagetree;
00352
QWidget * parentwidget;
00353
QStringList registeredComponents;
00354
QValueList<KService::Ptr> services;
00355
QMap<QString, KPluginInfo*> plugininfomap;
00356 };
00357
00358 Dialog::Dialog(
QWidget * parent,
const char * name )
00359 :
QObject( parent, name )
00360 , d( new DialogPrivate( this ) )
00361 {
00362 d->parentwidget = parent;
00363 d->staticlistview =
true;
00364 d->services = instanceServices();
00365 }
00366
00367 Dialog::Dialog( ContentInListView content,
00368
QWidget * parent,
const char * name )
00369 :
QObject( parent, name )
00370 , d( new DialogPrivate( this ) )
00371 {
00372 d->parentwidget = parent;
00373 d->staticlistview = ( content ==
Static );
00374 d->services = instanceServices();
00375 }
00376
00377 Dialog::Dialog(
const QStringList & components,
00378
QWidget * parent,
const char * name )
00379 :
QObject( parent, name )
00380 , d( new DialogPrivate( this ) )
00381 {
00382 d->parentwidget = parent;
00383 d->staticlistview =
true;
00384 d->services = instanceServices() + parentComponentsServices( components );
00385 }
00386
00387 Dialog::Dialog(
const QStringList & components,
00388 ContentInListView content,
QWidget * parent,
const char * name )
00389 :
QObject( parent, name )
00390 , d( new DialogPrivate( this ) )
00391 {
00392 d->parentwidget = parent;
00393 d->staticlistview = ( content ==
Static );
00394 d->services = instanceServices() + parentComponentsServices( components );
00395 }
00396
00397 Dialog::~Dialog()
00398 {
00399
delete d;
00400 }
00401
00402 void Dialog::addPluginInfos(
const QValueList<KPluginInfo*> & plugininfos )
00403 {
00404
for(
QValueList<KPluginInfo*>::ConstIterator it = plugininfos.begin();
00405 it != plugininfos.end(); ++it )
00406 {
00407 d->registeredComponents.append( ( *it )->pluginName() );
00408 d->services += ( *it )->kcmServices();
00409 d->plugininfomap[ ( *it )->pluginName() ] = *it;
00410 }
00411 }
00412
00413 void Dialog::show()
00414 {
00415
if( 0 == d->dlg )
00416 createDialogFromServices();
00417 Dispatcher::self()->syncConfiguration();
00418
return d->dlg->show();
00419 }
00420
00421
KCMultiDialog * Dialog::dialog()
00422 {
00423
if( 0 == d->dlg )
00424 createDialogFromServices();
00425
return d->dlg;
00426 }
00427
00428
QValueList<KService::Ptr> Dialog::instanceServices()
const
00429
{
00430
kdDebug( 700 ) <<
k_funcinfo <<
endl;
00431
QString instanceName =
KGlobal::instance()->
instanceName();
00432 d->registeredComponents.append( instanceName );
00433
kdDebug( 700 ) <<
"calling KServiceGroup::childGroup( " << instanceName
00434 <<
" )" <<
endl;
00435
KServiceGroup::Ptr service =
KServiceGroup::childGroup( instanceName );
00436
00437
QValueList<KService::Ptr> ret;
00438
00439
if( service && service->isValid() )
00440 {
00441
kdDebug( 700 ) <<
"call was successfull" <<
endl;
00442
KServiceGroup::List list = service->entries();
00443
for( KServiceGroup::List::ConstIterator it = list.begin();
00444 it != list.end(); ++it )
00445 {
00446
KSycocaEntry * p = *it;
00447
if( p->
isType( KST_KService ) )
00448 {
00449
kdDebug( 700 ) <<
"found service" <<
endl;
00450 ret << static_cast<KService *>( p );
00451 }
00452
else
00453
kdWarning( 700 ) <<
"KServiceGroup::childGroup returned"
00454
" something else than a KService (kinda)" <<
endl;
00455 }
00456 }
00457
00458
return ret;
00459 }
00460
00461
QValueList<KService::Ptr> Dialog::parentComponentsServices(
00462
const QStringList & kcdparents )
const
00463
{
00464 d->registeredComponents += kcdparents;
00465
QString constraint = kcdparents.join(
00466
"' in [X-KDE-ParentComponents]) or ('" );
00467 constraint =
"('" + constraint +
"' in [X-KDE-ParentComponents])";
00468
00469
kdDebug( 700 ) <<
"constraint = " << constraint <<
endl;
00470
return KTrader::self()->query(
"KCModule", constraint );
00471 }
00472
00473
bool Dialog::isPluginForKCMEnabled(
KCModuleInfo * moduleinfo )
const
00474
{
00475
00476
00477
bool enabled =
true;
00478
kdDebug( 700 ) <<
"check whether the " << moduleinfo->
moduleName()
00479 <<
" KCM should be shown" <<
endl;
00480
00481
QStringList parentComponents = moduleinfo->
service()->property(
00482
"X-KDE-ParentComponents" ).toStringList();
00483
for( QStringList::ConstIterator pcit = parentComponents.begin();
00484 pcit != parentComponents.end(); ++pcit )
00485 {
00486
00487
if( d->registeredComponents.find( *pcit ) ==
00488 d->registeredComponents.end() )
00489
continue;
00490
00491
00492
if( ! d->plugininfomap.contains( *pcit ) )
00493 {
00494
00495 enabled =
true;
00496
00497
break;
00498 }
00499
00500
KPluginInfo * pinfo = d->plugininfomap[ *pcit ];
00501 pinfo->
load();
00502 enabled = pinfo->
isPluginEnabled();
00503
kdDebug( 700 ) <<
"parent " << *pcit <<
" is "
00504 << ( enabled ?
"enabled" :
"disabled" ) <<
endl;
00505
00506
if( enabled )
00507
break;
00508 }
00509
return enabled;
00510 }
00511
00512
void Dialog::parseGroupFile(
const QString & filename )
00513 {
00514
KSimpleConfig file( filename );
00515
QStringList groups = file.groupList();
00516
for( QStringList::ConstIterator it = groups.begin(); it != groups.end();
00517 ++it )
00518 {
00519 GroupInfo group;
00520
QString id = *it;
00521 file.setGroup(
id.utf8() );
00522 group.id =
id;
00523 group.name = file.readEntry(
"Name" );
00524 group.comment = file.readEntry(
"Comment" );
00525 group.weight = file.readNumEntry(
"Weight", 100 );
00526 group.parentid = file.readEntry(
"Parent" );
00527 group.icon = file.readEntry(
"Icon" );
00528 d->pagetree.insert( group );
00529 }
00530 }
00531
00532
void Dialog::createDialogFromServices()
00533 {
00534
00535
QString setdlgpath =
locate(
"appdata",
00536 KGlobal::instance()->instanceName() +
".setdlg" );
00537
QStringList setdlgaddon =
KGlobal::dirs()->
findAllResources(
"appdata",
00538
"ksettingsdialog/*.setdlg" );
00539
if( ! setdlgpath.isNull() )
00540 parseGroupFile( setdlgpath );
00541
if( setdlgaddon.size() > 0 )
00542
for( QStringList::ConstIterator it = setdlgaddon.begin();
00543 it != setdlgaddon.end(); ++it )
00544 parseGroupFile( *it );
00545
00546
00547
for(
QValueList<KService::Ptr>::ConstIterator it = d->services.begin();
00548 it != d->services.end(); ++it )
00549 {
00550
00551
KCModuleInfo * info =
new KCModuleInfo( *it );
00552
QString parentid;
00553
QVariant tmp = info->
service()->property(
"X-KDE-CfgDlgHierarchy",
00554 QVariant::String );
00555
if( tmp.isValid() )
00556 parentid = tmp.toString();
00557 d->pagetree.insert( info, parentid );
00558 }
00559
00560
00561
00562 d->pagetree.sort();
00563
00564
int dialogface =
KJanusWidget::IconList;
00565
if( d->pagetree.needTree() )
00566 dialogface =
KJanusWidget::TreeList;
00567
else if( d->pagetree.singleChild() )
00568 dialogface =
KJanusWidget::Plain;
00569
00570
kdDebug( 700 ) <<
"creating KCMultiDialog" <<
endl;
00571 d->dlg =
new KCMultiDialog( dialogface, i18n(
"Configure" ),
00572 d->parentwidget );
00573
00574
if( dialogface ==
KJanusWidget::TreeList )
00575 d->dlg->setShowIconsInTreeList(
true );
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
if( ! d->staticlistview )
00590 d->dlg->addButtonBelowList( i18n(
"Configure..." ),
this,
00591 SLOT( configureTree() ) );
00592
00593 connect( d->dlg, SIGNAL( okClicked() ), Dispatcher::self(),
00594 SLOT( syncConfiguration() ) );
00595 connect( d->dlg, SIGNAL( applyClicked() ), Dispatcher::self(),
00596 SLOT( syncConfiguration() ) );
00597 connect( d->dlg, SIGNAL( configCommitted(
const QCString & ) ),
00598 Dispatcher::self(), SLOT( reparseConfiguration(
const QCString & ) ) );
00599
00600 d->pagetree.addToDialog( d->dlg );
00601
00602
if( dialogface ==
KJanusWidget::TreeList )
00603 d->dlg->unfoldTreeList(
true );
00604 }
00605
00606
void Dialog::configureTree()
00607 {
00608
kdDebug( 700 ) <<
k_funcinfo <<
endl;
00609 ComponentsDialog * subdlg =
new ComponentsDialog( d->dlg );
00610 subdlg->setPluginInfos( d->plugininfomap );
00611 subdlg->show();
00612 connect( subdlg, SIGNAL( okClicked() ),
this, SLOT( updateTreeList() ) );
00613 connect( subdlg, SIGNAL( applyClicked() ),
this, SLOT( updateTreeList() ) );
00614 connect( subdlg, SIGNAL( okClicked() ),
this,
00615 SIGNAL(
pluginSelectionChanged() ) );
00616 connect( subdlg, SIGNAL( applyClicked() ),
this,
00617 SIGNAL(
pluginSelectionChanged() ) );
00618 connect( subdlg, SIGNAL( finished() ), subdlg, SLOT( delayedDestruct() ) );
00619 }
00620
00621
void Dialog::updateTreeList()
00622 {
00623
kdDebug( 700 ) <<
k_funcinfo <<
endl;
00624
00625 d->pagetree.makeDirty();
00626
00627
00628
00629
00630
00631 d->pagetree.removeFromDialog( d->dlg );
00632 d->pagetree.addToDialog( d->dlg );
00633
00634
if( d->pagetree.needTree() )
00635 d->dlg->unfoldTreeList(
true );
00636 }
00637
00638 }
00639
00640
#include "dialog.moc"
00641
00642