00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <kiconloader.h>
00022
#include <kglobal.h>
00023
#include <kstandarddirs.h>
00024
#include <klocale.h>
00025
#include <kdebug.h>
00026
#include <ksortablevaluelist.h>
00027
#include "kservicefactory.h"
00028
#include "kservicegroupfactory.h"
00029
#include "kservicegroup.h"
00030
#include "kservice.h"
00031
#include "ksycoca.h"
00032
00033
class KServiceGroup::Private
00034 {
00035
public:
00036 Private() { m_bNoDisplay =
false; m_bShowEmptyMenu =
false;m_bShowInlineHeader=
false;m_bInlineAlias=
false; m_bAllowInline =
false;m_inlineValue = 4;}
00037
bool m_bNoDisplay;
00038
bool m_bShowEmptyMenu;
00039
bool m_bShowInlineHeader;
00040
bool m_bInlineAlias;
00041
bool m_bAllowInline;
00042
int m_inlineValue;
00043
QStringList suppressGenericNames;
00044
QString directoryEntryPath;
00045
QStringList sortOrder;
00046 };
00047
00048 KServiceGroup::KServiceGroup(
const QString & name )
00049 :
KSycocaEntry(name), m_childCount(-1)
00050 {
00051 d =
new KServiceGroup::Private;
00052 m_bDeleted =
false;
00053 }
00054
00055 KServiceGroup::KServiceGroup(
const QString &configFile,
const QString & _relpath )
00056 :
KSycocaEntry(_relpath), m_childCount(-1)
00057 {
00058 d =
new KServiceGroup::Private;
00059 m_bDeleted =
false;
00060
00061
QString cfg = configFile;
00062
if (cfg.isEmpty())
00063 cfg = _relpath+
".directory";
00064
00065 d->directoryEntryPath = cfg;
00066
00067
KConfig config( cfg,
true,
false,
"apps" );
00068
00069 config.
setDesktopGroup();
00070
00071 m_strCaption = config.
readEntry(
"Name" );
00072 m_strIcon = config.
readEntry(
"Icon" );
00073 m_strComment = config.
readEntry(
"Comment" );
00074 m_bDeleted = config.
readBoolEntry(
"Hidden",
false );
00075 d->m_bNoDisplay = config.
readBoolEntry(
"NoDisplay",
false );
00076
QStringList tmpList;
00077
if (config.
hasKey(
"OnlyShowIn"))
00078 {
00079
if (!config.
readListEntry(
"OnlyShowIn",
';').contains(
"KDE"))
00080 d->m_bNoDisplay =
true;
00081 }
00082
if (config.
hasKey(
"NotShowIn"))
00083 {
00084
if (config.
readListEntry(
"NotShowIn",
';').contains(
"KDE"))
00085 d->m_bNoDisplay =
true;
00086 }
00087
00088 m_strBaseGroupName = config.
readEntry(
"X-KDE-BaseGroup" );
00089 d->suppressGenericNames = config.
readListEntry(
"X-KDE-SuppressGenericNames" );
00090 d->sortOrder = config.
readListEntry(
"SortOrder");
00091
kdDebug()<<
"cfg :"<<cfg<<
" m_strComment :"<<m_strComment<<
" m_strCaption :"<<m_strCaption<<
" m_strBaseGroupName :"<<m_strBaseGroupName<<
" d->sortOrder : "<<d->sortOrder.join(
";" )<<
endl;
00092
00093
00094
if (m_strCaption.isEmpty())
00095 {
00096 m_strCaption = _relpath;
00097
if (m_strCaption.right(1) ==
"/")
00098 m_strCaption = m_strCaption.left(m_strCaption.length()-1);
00099
int i = m_strCaption.findRev(
'/');
00100
if (i > 0)
00101 m_strCaption = m_strCaption.mid(i+1);
00102 }
00103
if (m_strIcon.isEmpty())
00104 m_strIcon =
"folder";
00105 }
00106
00107 KServiceGroup::KServiceGroup(
QDataStream& _str,
int offset,
bool deep ) :
00108
KSycocaEntry( _str, offset )
00109 {
00110 d =
new KServiceGroup::Private;
00111 m_bDeep = deep;
00112 load( _str );
00113 }
00114
00115 KServiceGroup::~KServiceGroup()
00116 {
00117
delete d;
00118 }
00119
00120 int KServiceGroup::childCount()
00121 {
00122
if (m_childCount == -1)
00123 {
00124 m_childCount = 0;
00125
00126
for( List::ConstIterator it = m_serviceList.begin();
00127 it != m_serviceList.end(); it++)
00128 {
00129
KSycocaEntry *p = (*it);
00130
if (p->
isType(KST_KService))
00131 {
00132
KService *service = static_cast<KService *>(p);
00133
if (!service->
noDisplay())
00134 m_childCount++;
00135 }
00136
else if (p->
isType(KST_KServiceGroup))
00137 {
00138
KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00139 m_childCount += serviceGroup->
childCount();
00140 }
00141 }
00142 }
00143
return m_childCount;
00144 }
00145
00146
00147 bool KServiceGroup::showInlineHeader()
const
00148
{
00149
return d->m_bShowInlineHeader;
00150 }
00151
00152 bool KServiceGroup::showEmptyMenu()
const
00153
{
00154
return d->m_bShowEmptyMenu;
00155 }
00156
00157
bool KServiceGroup::inlineAlias()
const
00158
{
00159
return d->m_bInlineAlias;
00160 }
00161
00162
void KServiceGroup::setInlineAlias(
bool _b)
00163 {
00164 d->m_bInlineAlias = _b;
00165 }
00166
00167
void KServiceGroup::setShowEmptyMenu(
bool _b)
00168 {
00169 d->m_bShowEmptyMenu=_b;
00170 }
00171
00172
void KServiceGroup::setShowInlineHeader(
bool _b)
00173 {
00174 d->m_bShowInlineHeader=_b;
00175 }
00176
00177
int KServiceGroup::inlineValue()
const
00178
{
00179
return d->m_inlineValue;
00180 }
00181
00182
void KServiceGroup::setInlineValue(
int _val)
00183 {
00184 d->m_inlineValue = _val;
00185 }
00186
00187
bool KServiceGroup::allowInline()
const
00188
{
00189
return d->m_bAllowInline;
00190 }
00191
00192
void KServiceGroup::setAllowInline(
bool _b)
00193 {
00194 d->m_bAllowInline = _b;
00195 }
00196
00197 bool KServiceGroup::noDisplay()
const
00198
{
00199
return d->m_bNoDisplay || m_strCaption.startsWith(
".");
00200 }
00201
00202 QStringList KServiceGroup::suppressGenericNames()
const
00203
{
00204
return d->suppressGenericNames;
00205 }
00206
00207
void KServiceGroup::load(
QDataStream& s )
00208 {
00209
QStringList groupList;
00210 Q_INT8 noDisplay;
00211 Q_INT8 _showEmptyMenu;
00212 Q_INT8 inlineHeader;
00213 Q_INT8 _inlineAlias;
00214 Q_INT8 _allowInline;
00215 s >> m_strCaption >> m_strIcon >>
00216 m_strComment >> groupList >> m_strBaseGroupName >> m_childCount >>
00217 noDisplay >> d->suppressGenericNames >> d->directoryEntryPath >>
00218 d->sortOrder >> _showEmptyMenu >> inlineHeader >> _inlineAlias >> _allowInline;
00219
00220 d->m_bNoDisplay = (noDisplay != 0);
00221 d->m_bShowEmptyMenu = ( _showEmptyMenu != 0 );
00222 d->m_bShowInlineHeader = ( inlineHeader != 0 );
00223 d->m_bInlineAlias = ( _inlineAlias != 0 );
00224 d->m_bAllowInline = ( _allowInline != 0 );
00225
00226
if (m_bDeep)
00227 {
00228
for(QStringList::ConstIterator it = groupList.begin();
00229 it != groupList.end(); it++)
00230 {
00231
QString path = *it;
00232
if (path[path.length()-1] ==
'/')
00233 {
00234
KServiceGroup *serviceGroup;
00235 serviceGroup = KServiceGroupFactory::self()->findGroupByDesktopPath(path,
false);
00236
if (serviceGroup)
00237 m_serviceList.append( SPtr(serviceGroup) );
00238 }
00239
else
00240 {
00241
KService *service;
00242 service = KServiceFactory::self()->findServiceByDesktopPath(path);
00243
if (service)
00244 m_serviceList.append( SPtr(service) );
00245 }
00246 }
00247 }
00248 }
00249
00250
void KServiceGroup::addEntry(
KSycocaEntry *entry)
00251 {
00252 m_serviceList.append(entry);
00253 }
00254
00255
void KServiceGroup::save(
QDataStream& s )
00256 {
00257
KSycocaEntry::save( s );
00258
00259
QStringList groupList;
00260
for( List::ConstIterator it = m_serviceList.begin();
00261 it != m_serviceList.end(); it++)
00262 {
00263
KSycocaEntry *p = (*it);
00264
if (p->
isType(KST_KService))
00265 {
00266
KService *service = static_cast<KService *>(p);
00267 groupList.append( service->
desktopEntryPath());
00268 }
00269
else if (p->
isType(KST_KServiceGroup))
00270 {
00271
KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00272 groupList.append( serviceGroup->
relPath());
00273 }
00274
else
00275 {
00276
00277 }
00278 }
00279
00280 (
void)
childCount();
00281
00282 Q_INT8 noDisplay = d->m_bNoDisplay ? 1 : 0;
00283 Q_INT8 _showEmptyMenu = d->m_bShowEmptyMenu ? 1 : 0;
00284 Q_INT8 inlineHeader = d->m_bShowInlineHeader ? 1 : 0;
00285 Q_INT8 _inlineAlias = d->m_bInlineAlias ? 1 : 0;
00286 Q_INT8 _allowInline = d->m_bAllowInline ? 1 : 0;
00287 s << m_strCaption << m_strIcon <<
00288 m_strComment << groupList << m_strBaseGroupName << m_childCount <<
00289 noDisplay << d->suppressGenericNames << d->directoryEntryPath <<
00290 d->sortOrder <<_showEmptyMenu <<inlineHeader<<_inlineAlias<<_allowInline;
00291 }
00292
00293 KServiceGroup::List
00294 KServiceGroup::entries(
bool sort)
00295 {
00296
return entries(sort,
true);
00297 }
00298
00299 KServiceGroup::List
00300 KServiceGroup::entries(
bool sort,
bool excludeNoDisplay)
00301 {
00302
return entries(sort, excludeNoDisplay,
false);
00303 }
00304
00305
static void addItem(KServiceGroup::List &sorted,
const KSycocaEntry::Ptr &p,
bool &addSeparator)
00306 {
00307
if (addSeparator && !sorted.isEmpty())
00308 sorted.append(
new KServiceSeparator());
00309 sorted.append(p);
00310 addSeparator =
false;
00311 }
00312
00313 KServiceGroup::List
00314 KServiceGroup::entries(
bool sort,
bool excludeNoDisplay,
bool allowSeparators,
bool sortByGenericName)
00315 {
00316
KServiceGroup *
group =
this;
00317
00318
00319
00320
00321
00322
if (!m_bDeep) {
00323
00324 group =
00325 KServiceGroupFactory::self()->findGroupByDesktopPath(
relPath(),
true);
00326
00327
if (0 == group)
00328
return List();
00329 }
00330
00331
if (!sort)
00332
return group->
m_serviceList;
00333
00334
00335
00336
00337
KSortableValueList<SPtr,QCString> slist;
00338
KSortableValueList<SPtr,QCString> glist;
00339
for (List::ConstIterator it(group->
m_serviceList.begin()); it != group->
m_serviceList.end(); ++it)
00340 {
00341
KSycocaEntry *p = (*it);
00342
bool noDisplay = p->
isType(KST_KServiceGroup) ?
00343 static_cast<KServiceGroup *>(p)->noDisplay() :
00344 static_cast<KService *>(p)->noDisplay();
00345
if (excludeNoDisplay && noDisplay)
00346
continue;
00347
00348
KSortableValueList<SPtr,QCString> & list = p->
isType(KST_KServiceGroup) ? glist : slist;
00349
QString name;
00350
if (p->
isType(KST_KServiceGroup))
00351 name = static_cast<KServiceGroup *>(p)->caption();
00352
else if (sortByGenericName)
00353 name = static_cast<KService *>(p)->genericName() +
" " + p->
name();
00354
else
00355 name = p->
name() +
" " + static_cast<KService *>(p)->genericName();
00356
00357
00358
QCString key( name.length() * 4 + 1 );
00359
00360
#ifndef USE_SOLARIS
00361
00362 size_t ln = strxfrm( key.data(), name.local8Bit().data(), key.size());
00363
if( ln != size_t( -1 ))
00364 {
00365
if( ln >= key.size())
00366 {
00367 key.resize( ln + 1 );
00368
if( strxfrm( key.data(), name.local8Bit().data(), key.size()) == size_t( -1 ))
00369 key = name.local8Bit();
00370 }
00371 }
00372
else
00373
#endif
00374
{
00375 key = name.local8Bit();
00376 }
00377 list.
insert(key,
SPtr(*it));
00378 }
00379
00380 slist.
sort();
00381 glist.
sort();
00382
00383
if (d->sortOrder.isEmpty())
00384 {
00385 d->sortOrder <<
":M";
00386 d->sortOrder <<
":F";
00387 d->sortOrder <<
":OIH IL[4]";
00388 }
00389
00390
QString rp =
relPath();
00391
if(rp ==
"/") rp = QString::null;
00392
00393
00394
00395
for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it)
00396 {
00397
const QString &item = *it;
00398
if (item.isEmpty())
continue;
00399
if (item[0] ==
'/')
00400 {
00401
QString groupPath = rp + item.mid(1) +
"/";
00402
00403
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2)
00404 {
00405
KServiceGroup *group = (
KServiceGroup *)((
KSycocaEntry *)((*it2).value()));
00406
if (group->
relPath() == groupPath)
00407 {
00408 glist.remove(it2);
00409
break;
00410 }
00411 }
00412 }
00413
else if (item[0] !=
':')
00414 {
00415
00416
00417
00418
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = slist.begin(); it2 != slist.end(); ++it2)
00419 {
00420
KService *service = (
KService *)((
KSycocaEntry *)((*it2).value()));
00421
if (service->
menuId() == item)
00422 {
00423 slist.remove(it2);
00424
break;
00425 }
00426 }
00427 }
00428 }
00429
00430
List sorted;
00431
00432
bool needSeparator =
false;
00433
00434
00435
for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it)
00436 {
00437
const QString &item = *it;
00438
if (item.isEmpty())
continue;
00439
if (item[0] ==
':')
00440 {
00441
00442
if (item ==
":S")
00443 {
00444
if (allowSeparators)
00445 needSeparator =
true;
00446 }
00447
else if ( item.contains(
":O" ) )
00448 {
00449
00450
QString tmp( item );
00451 tmp = tmp.remove(
":O");
00452
QStringList optionAttribute = QStringList::split(
" ",tmp);
00453
if( optionAttribute.count()==0)
00454 optionAttribute.append(tmp);
00455
bool showEmptyMenu =
false;
00456
bool showInline =
false;
00457
bool showInlineHeader =
true;
00458
bool showInlineAlias =
false;
00459
int inlineValue = 4;
00460
00461
for ( QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3 )
00462 {
00463 parseAttribute( *it3, showEmptyMenu, showInline, showInlineHeader, showInlineAlias, inlineValue );
00464 }
00465
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2)
00466 {
00467
KServiceGroup *group = (
KServiceGroup *)((
KSycocaEntry *)(*it2).value());
00468 group->
setShowEmptyMenu( showEmptyMenu );
00469 group->
setAllowInline( showInline );
00470 group->
setShowInlineHeader( showInlineHeader );
00471 group->
setInlineAlias( showInlineAlias );
00472 group->
setInlineValue( inlineValue );
00473 }
00474
00475 }
00476
else if (item ==
":M")
00477 {
00478
00479
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = glist.begin(); it2 != glist.end(); ++it2)
00480 {
00481 addItem(sorted, (*it2).value(), needSeparator);
00482 }
00483 }
00484
else if (item ==
":F")
00485 {
00486
00487
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = slist.begin(); it2 != slist.end(); ++it2)
00488 {
00489 addItem(sorted, (*it2).value(), needSeparator);
00490 }
00491 }
00492
else if (item ==
":A")
00493 {
00494
00495
KSortableValueList<SPtr,QCString>::Iterator it_s = slist.begin();
00496
KSortableValueList<SPtr,QCString>::Iterator it_g = glist.begin();
00497
00498
while(
true)
00499 {
00500
if (it_s == slist.end())
00501 {
00502
if (it_g == glist.end())
00503
break;
00504
00505
00506 addItem(sorted, (*it_g).value(), needSeparator);
00507 it_g++;
00508 }
00509
else if (it_g == glist.end())
00510 {
00511
00512 addItem(sorted, (*it_s).value(), needSeparator);
00513 it_s++;
00514 }
00515
else if ((*it_g).index() < (*it_s).index())
00516 {
00517
00518 addItem(sorted, (*it_g).value(), needSeparator);
00519 it_g++;
00520 }
00521
else
00522 {
00523
00524 addItem(sorted, (*it_s).value(), needSeparator);
00525 it_s++;
00526 }
00527 }
00528 }
00529 }
00530
else if (item[0] ==
'/')
00531 {
00532
QString groupPath = rp + item.mid(1) +
"/";
00533
00534
for (List::ConstIterator it2(group->
m_serviceList.begin()); it2 != group->
m_serviceList.end(); ++it2)
00535 {
00536
if (!(*it2)->isType(KST_KServiceGroup))
00537
continue;
00538
KServiceGroup *group = (
KServiceGroup *)((
KSycocaEntry *)(*it2));
00539
if (group->
relPath() == groupPath)
00540 {
00541
if (!excludeNoDisplay || !group->
noDisplay())
00542 {
00543
const QString &nextItem = *( ++it );
00544
if ( nextItem.startsWith(
":O" ) )
00545 {
00546
QString tmp( nextItem );
00547 tmp = tmp.remove(
":O");
00548
QStringList optionAttribute = QStringList::split(
" ",tmp);
00549
if( optionAttribute.count()==0)
00550 optionAttribute.append(tmp);
00551
bool bShowEmptyMenu =
false;
00552
bool bShowInline =
false;
00553
bool bShowInlineHeader =
false;
00554
bool bShowInlineAlias =
false;
00555
int inlineValue = -1;
00556
00557
for ( QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3 )
00558 {
00559 parseAttribute( *it3 , bShowEmptyMenu, bShowInline, bShowInlineHeader, bShowInlineAlias , inlineValue );
00560 }
00561 group->
setShowEmptyMenu( bShowEmptyMenu );
00562 group->
setAllowInline( bShowInline );
00563 group->
setShowInlineHeader( bShowInlineHeader );
00564 group->
setInlineAlias( bShowInlineAlias );
00565 group->
setInlineValue( inlineValue );
00566
00567 }
00568
else
00569 it--;
00570
00571 addItem(sorted, (group), needSeparator);
00572 }
00573
break;
00574 }
00575 }
00576 }
00577
else
00578 {
00579
for (List::ConstIterator it2(group->
m_serviceList.begin()); it2 != group->
m_serviceList.end(); ++it2)
00580 {
00581
if (!(*it2)->isType(KST_KService))
00582
continue;
00583
KService *service = (
KService *)((
KSycocaEntry *)(*it2));
00584
if (service->
menuId() == item)
00585 {
00586
if (!excludeNoDisplay || !service->
noDisplay())
00587 addItem(sorted, (*it2), needSeparator);
00588
break;
00589 }
00590 }
00591 }
00592 }
00593
00594
return sorted;
00595 }
00596
00597
void KServiceGroup::parseAttribute(
const QString &item ,
bool &showEmptyMenu,
bool &showInline,
bool &showInlineHeader,
bool & showInlineAlias ,
int &inlineValue )
00598 {
00599
if( item ==
"ME")
00600 showEmptyMenu=
true;
00601
else if ( item ==
"NME")
00602 showEmptyMenu=
false;
00603
else if( item ==
"I")
00604 showInline =
true;
00605
else if ( item ==
"NI")
00606 showInline =
false;
00607
else if( item ==
"IH")
00608 showInlineHeader=
true;
00609
else if ( item ==
"NIH")
00610 showInlineHeader =
false;
00611
else if( item ==
"IA")
00612 showInlineAlias =
true;
00613
else if ( item ==
"NIA")
00614 showInlineAlias =
false;
00615
else if( ( item ).contains(
"IL" ))
00616 {
00617
QString tmp( item );
00618 tmp = tmp.remove(
"IL[" );
00619 tmp = tmp.remove(
"]" );
00620
bool ok;
00621
int _inlineValue = tmp.toInt(&ok);
00622
if ( !ok )
00623 _inlineValue = -1;
00624 inlineValue = _inlineValue;
00625 }
00626
else
00627
kdDebug()<<
" not supported !!!!!!!\n";
00628 }
00629
00630
void KServiceGroup::setLayoutInfo(
const QStringList &layout)
00631 {
00632 d->sortOrder = layout;
00633 }
00634
00635
QStringList KServiceGroup::layoutInfo()
const
00636
{
00637
return d->sortOrder;
00638 }
00639
00640 KServiceGroup::Ptr
00641 KServiceGroup::baseGroup(
const QString & _baseGroupName )
00642 {
00643
return KServiceGroupFactory::self()->findBaseGroup(_baseGroupName,
true);
00644 }
00645
00646 KServiceGroup::Ptr
00647 KServiceGroup::root()
00648 {
00649
return KServiceGroupFactory::self()->findGroupByDesktopPath(
"/",
true);
00650 }
00651
00652 KServiceGroup::Ptr
00653 KServiceGroup::group(
const QString &relPath)
00654 {
00655
if (relPath.isEmpty())
return root();
00656
return KServiceGroupFactory::self()->findGroupByDesktopPath(relPath,
true);
00657 }
00658
00659 KServiceGroup::Ptr
00660 KServiceGroup::childGroup(
const QString &parent)
00661 {
00662
return KServiceGroupFactory::self()->findGroupByDesktopPath(
"#parent#"+parent,
true);
00663 }
00664
00665
QString
00666 KServiceGroup::directoryEntryPath()
const
00667
{
00668
return d->directoryEntryPath;
00669 }
00670
00671
00672
void KServiceGroup::virtual_hook(
int id,
void* data )
00673 { KSycocaEntry::virtual_hook(
id, data ); }
00674
00675
00676 KServiceSeparator::KServiceSeparator( )
00677 :
KSycocaEntry("separator")
00678 {
00679 }