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; }
00037
bool m_bNoDisplay;
00038
QStringList suppressGenericNames;
00039
QString directoryEntryPath;
00040
QStringList sortOrder;
00041 };
00042
00043 KServiceGroup::KServiceGroup(
const QString & name )
00044 :
KSycocaEntry(name), m_childCount(-1)
00045 {
00046 d =
new KServiceGroup::Private;
00047 m_bDeleted =
false;
00048 }
00049
00050 KServiceGroup::KServiceGroup(
const QString &configFile,
const QString & _relpath )
00051 :
KSycocaEntry(_relpath), m_childCount(-1)
00052 {
00053 d =
new KServiceGroup::Private;
00054 m_bDeleted =
false;
00055
00056
QString cfg = configFile;
00057
if (cfg.
isEmpty())
00058 cfg = _relpath+
".directory";
00059
00060 d->directoryEntryPath = cfg;
00061
00062
KConfig config( cfg,
true,
false,
"apps" );
00063
00064 config.
setDesktopGroup();
00065
00066 m_strCaption = config.
readEntry(
"Name" );
00067 m_strIcon = config.
readEntry(
"Icon" );
00068 m_strComment = config.
readEntry(
"Comment" );
00069 m_bDeleted = config.
readBoolEntry(
"Hidden",
false );
00070 d->m_bNoDisplay = config.
readBoolEntry(
"NoDisplay",
false );
00071
QStringList tmpList;
00072
if (config.
hasKey(
"OnlyShowIn"))
00073 {
00074
if (!config.
readListEntry(
"OnlyShowIn",
';').contains(
"KDE"))
00075 d->m_bNoDisplay =
true;
00076 }
00077
if (config.
hasKey(
"NotShowIn"))
00078 {
00079
if (config.
readListEntry(
"NotShowIn",
';').contains(
"KDE"))
00080 d->m_bNoDisplay =
true;
00081 }
00082
00083 m_strBaseGroupName = config.
readEntry(
"X-KDE-BaseGroup" );
00084 d->suppressGenericNames = config.
readListEntry(
"X-KDE-SuppressGenericNames" );
00085
00086
00087
00088
if (m_strCaption.
isEmpty())
00089 {
00090 m_strCaption = _relpath;
00091
if (m_strCaption.
right(1) ==
"/")
00092 m_strCaption = m_strCaption.
left(m_strCaption.
length()-1);
00093
int i = m_strCaption.
findRev(
'/');
00094
if (i > 0)
00095 m_strCaption = m_strCaption.
mid(i+1);
00096 }
00097
if (m_strIcon.
isEmpty())
00098 m_strIcon =
"folder";
00099 }
00100
00101 KServiceGroup::KServiceGroup(
QDataStream& _str,
int offset,
bool deep ) :
00102
KSycocaEntry( _str, offset )
00103 {
00104 d =
new KServiceGroup::Private;
00105 m_bDeep = deep;
00106 load( _str );
00107 }
00108
00109 KServiceGroup::~KServiceGroup()
00110 {
00111
delete d;
00112 }
00113
00114 int KServiceGroup::childCount()
00115 {
00116
if (m_childCount == -1)
00117 {
00118 m_childCount = 0;
00119
00120
for( List::ConstIterator it = m_serviceList.
begin();
00121 it != m_serviceList.
end(); it++)
00122 {
00123
KSycocaEntry *p = (*it);
00124
if (p->
isType(KST_KService))
00125 {
00126
KService *service = static_cast<KService *>(p);
00127
if (!service->
noDisplay())
00128 m_childCount++;
00129 }
00130
else if (p->
isType(KST_KServiceGroup))
00131 {
00132
KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00133 m_childCount += serviceGroup->
childCount();
00134 }
00135 }
00136 }
00137
return m_childCount;
00138 }
00139
00140
00141 bool KServiceGroup::noDisplay()
const
00142
{
00143
return d->m_bNoDisplay || m_strCaption.
startsWith(
".");
00144 }
00145
00146 QStringList KServiceGroup::suppressGenericNames()
const
00147
{
00148
return d->suppressGenericNames;
00149 }
00150
00151
void KServiceGroup::load(
QDataStream& s )
00152 {
00153
QStringList groupList;
00154 Q_INT8 noDisplay;
00155 s >> m_strCaption >> m_strIcon >>
00156 m_strComment >> groupList >> m_strBaseGroupName >> m_childCount >>
00157 noDisplay >> d->suppressGenericNames >> d->directoryEntryPath >>
00158 d->sortOrder;
00159
00160 d->m_bNoDisplay = (noDisplay != 0);
00161
00162
if (m_bDeep)
00163 {
00164
for(QStringList::ConstIterator it = groupList.begin();
00165 it != groupList.end(); it++)
00166 {
00167
QString path = *it;
00168
if (path[path.
length()-1] ==
'/')
00169 {
00170
KServiceGroup *serviceGroup;
00171 serviceGroup = KServiceGroupFactory::self()->findGroupByDesktopPath(path,
false);
00172
if (serviceGroup)
00173 m_serviceList.append( SPtr(serviceGroup) );
00174 }
00175
else
00176 {
00177
KService *service;
00178 service = KServiceFactory::self()->findServiceByDesktopPath(path);
00179
if (service)
00180 m_serviceList.append( SPtr(service) );
00181 }
00182 }
00183 }
00184 }
00185
00186
void KServiceGroup::addEntry(
KSycocaEntry *entry)
00187 {
00188 m_serviceList.append(entry);
00189 }
00190
00191
void KServiceGroup::save(
QDataStream& s )
00192 {
00193
KSycocaEntry::save( s );
00194
00195
QStringList groupList;
00196
for( List::ConstIterator it = m_serviceList.begin();
00197 it != m_serviceList.end(); it++)
00198 {
00199
KSycocaEntry *p = (*it);
00200
if (p->
isType(KST_KService))
00201 {
00202
KService *service = static_cast<KService *>(p);
00203 groupList.append( service->
desktopEntryPath());
00204 }
00205
else if (p->
isType(KST_KServiceGroup))
00206 {
00207
KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00208 groupList.append( serviceGroup->
relPath());
00209 }
00210
else
00211 {
00212
00213 }
00214 }
00215
00216 (
void)
childCount();
00217
00218 Q_INT8 noDisplay = d->m_bNoDisplay ? 1 : 0;
00219 s << m_strCaption << m_strIcon <<
00220 m_strComment << groupList << m_strBaseGroupName << m_childCount <<
00221 noDisplay << d->suppressGenericNames << d->directoryEntryPath <<
00222 d->sortOrder;
00223 }
00224
00225 KServiceGroup::List
00226 KServiceGroup::entries(
bool sort)
00227 {
00228
return entries(sort,
true);
00229 }
00230
00231 KServiceGroup::List
00232 KServiceGroup::entries(
bool sort,
bool excludeNoDisplay)
00233 {
00234
return entries(sort, excludeNoDisplay,
false);
00235 }
00236
00237
static void addItem(KServiceGroup::List &sorted,
const KSycocaEntry::Ptr &p,
bool &addSeparator)
00238 {
00239
if (addSeparator && !sorted.isEmpty())
00240 sorted.append(
new KServiceSeparator());
00241 sorted.append(p);
00242 addSeparator =
false;
00243 }
00244
00245 KServiceGroup::List
00246 KServiceGroup::entries(
bool sort,
bool excludeNoDisplay,
bool allowSeparators,
bool sortByGenericName)
00247 {
00248
KServiceGroup *
group =
this;
00249
00250
00251
00252
00253
00254
if (!m_bDeep) {
00255
00256 group =
00257 KServiceGroupFactory::self()->findGroupByDesktopPath(
relPath(),
true);
00258
00259
if (0 == group)
00260
return List();
00261 }
00262
00263
if (!sort)
00264
return group->
m_serviceList;
00265
00266
00267
00268
00269
KSortableValueList<SPtr,QCString> slist;
00270
KSortableValueList<SPtr,QCString> glist;
00271
for (List::ConstIterator it(group->
m_serviceList.
begin()); it != group->
m_serviceList.
end(); ++it)
00272 {
00273
KSycocaEntry *p = (*it);
00274
bool noDisplay = p->
isType(KST_KServiceGroup) ?
00275 static_cast<KServiceGroup *>(p)->noDisplay() :
00276 static_cast<KService *>(p)->noDisplay();
00277
if (excludeNoDisplay && noDisplay)
00278
continue;
00279
00280
KSortableValueList<SPtr,QCString> & list = p->
isType(KST_KServiceGroup) ? glist : slist;
00281
QString name;
00282
if (p->
isType(KST_KServiceGroup))
00283 name = static_cast<KServiceGroup *>(p)->caption();
00284
else if (sortByGenericName)
00285 name = static_cast<KService *>(p)->genericName() +
" " + p->
name();
00286
else
00287 name = p->
name() +
" " + static_cast<KService *>(p)->genericName();
00288
00289
QCString key( name.
length() * 4 + 1 );
00290
00291
#ifndef USE_SOLARIS
00292
00293 size_t ln = strxfrm( key.data(), name.
local8Bit().data(), key.size());
00294
if( ln != size_t( -1 ))
00295 {
00296
if( ln >= key.size())
00297 {
00298 key.resize( ln + 1 );
00299
if( strxfrm( key.data(), name.
local8Bit().data(), key.size()) == size_t( -1 ))
00300 key = name.
local8Bit();
00301 }
00302 }
00303
else
00304
#endif
00305
{
00306 key = name.
local8Bit();
00307 }
00308 list.
insert(key,
SPtr(*it));
00309 }
00310
00311 slist.
sort();
00312 glist.
sort();
00313
00314
if (d->sortOrder.isEmpty())
00315 {
00316 d->sortOrder <<
":M";
00317 d->sortOrder <<
":F";
00318 }
00319
00320
QString rp =
relPath();
00321
if(rp ==
"/") rp = QString::null;
00322
00323
00324
00325
for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it)
00326 {
00327
const QString &item = *it;
00328
if (item.
isEmpty())
continue;
00329
if (item[0] ==
'/')
00330 {
00331
QString groupPath = rp + item.
mid(1) +
"/";
00332
00333
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = glist.
begin(); it2 != glist.
end(); ++it2)
00334 {
00335
KServiceGroup *group = (
KServiceGroup *)((
KSycocaEntry *)((*it2).value()));
00336
if (group->
relPath() == groupPath)
00337 {
00338 glist.
remove(it2);
00339
break;
00340 }
00341 }
00342 }
00343
else if (item[0] !=
':')
00344 {
00345
00346
00347
00348
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = slist.
begin(); it2 != slist.
end(); ++it2)
00349 {
00350
KService *service = (
KService *)((
KSycocaEntry *)((*it2).value()));
00351
if (service->
menuId() == item)
00352 {
00353 slist.
remove(it2);
00354
break;
00355 }
00356 }
00357 }
00358 }
00359
00360
List sorted;
00361
00362
bool needSeparator =
false;
00363
00364
00365
for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it)
00366 {
00367
const QString &item = *it;
00368
if (item.
isEmpty())
continue;
00369
if (item[0] ==
':')
00370 {
00371
00372
if (item ==
":S")
00373 {
00374
if (allowSeparators)
00375 needSeparator =
true;
00376 }
00377
else if (item ==
":M")
00378 {
00379
00380
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = glist.
begin(); it2 != glist.
end(); ++it2)
00381 {
00382 addItem(sorted, (*it2).value(), needSeparator);
00383 }
00384 }
00385
else if (item ==
":F")
00386 {
00387
00388
for(
KSortableValueList<SPtr,QCString>::Iterator it2 = slist.
begin(); it2 != slist.
end(); ++it2)
00389 {
00390 addItem(sorted, (*it2).value(), needSeparator);
00391 }
00392 }
00393
else if (item ==
":A")
00394 {
00395
00396
KSortableValueList<SPtr,QCString>::Iterator it_s = slist.
begin();
00397
KSortableValueList<SPtr,QCString>::Iterator it_g = glist.
begin();
00398
00399
while(
true)
00400 {
00401
if (it_s == slist.
end())
00402 {
00403
if (it_g == glist.
end())
00404
break;
00405
00406
00407 addItem(sorted, (*it_g).value(), needSeparator);
00408 it_g++;
00409 }
00410
else if (it_g == glist.
end())
00411 {
00412
00413 addItem(sorted, (*it_s).value(), needSeparator);
00414 it_s++;
00415 }
00416
else if ((*it_g).index() < (*it_s).index())
00417 {
00418
00419 addItem(sorted, (*it_g).value(), needSeparator);
00420 it_g++;
00421 }
00422
else
00423 {
00424
00425 addItem(sorted, (*it_s).value(), needSeparator);
00426 it_s++;
00427 }
00428 }
00429 }
00430 }
00431
else if (item[0] ==
'/')
00432 {
00433
QString groupPath = rp + item.
mid(1) +
"/";
00434
00435
for (List::ConstIterator it2(group->
m_serviceList.
begin()); it2 != group->
m_serviceList.
end(); ++it2)
00436 {
00437
if (!(*it2)->isType(KST_KServiceGroup))
00438
continue;
00439
KServiceGroup *group = (
KServiceGroup *)((
KSycocaEntry *)(*it2));
00440
if (group->
relPath() == groupPath)
00441 {
00442
if (!excludeNoDisplay || !group->
noDisplay())
00443 addItem(sorted, (*it2), needSeparator);
00444
break;
00445 }
00446 }
00447 }
00448
else
00449 {
00450
for (List::ConstIterator it2(group->
m_serviceList.
begin()); it2 != group->
m_serviceList.
end(); ++it2)
00451 {
00452
if (!(*it2)->isType(KST_KService))
00453
continue;
00454
KService *service = (
KService *)((
KSycocaEntry *)(*it2));
00455
if (service->
menuId() == item)
00456 {
00457
if (!excludeNoDisplay || !service->
noDisplay())
00458 addItem(sorted, (*it2), needSeparator);
00459
break;
00460 }
00461 }
00462 }
00463 }
00464
00465
return sorted;
00466 }
00467
00468
void KServiceGroup::setLayoutInfo(
const QStringList &layout)
00469 {
00470 d->sortOrder = layout;
00471 }
00472
00473 KServiceGroup::Ptr
00474 KServiceGroup::baseGroup(
const QString & _baseGroupName )
00475 {
00476
return KServiceGroupFactory::self()->findBaseGroup(_baseGroupName,
true);
00477 }
00478
00479 KServiceGroup::Ptr
00480 KServiceGroup::root()
00481 {
00482
return KServiceGroupFactory::self()->findGroupByDesktopPath(
"/",
true);
00483 }
00484
00485 KServiceGroup::Ptr
00486 KServiceGroup::group(
const QString &relPath)
00487 {
00488
if (relPath.
isEmpty())
return root();
00489
return KServiceGroupFactory::self()->findGroupByDesktopPath(relPath,
true);
00490 }
00491
00492 KServiceGroup::Ptr
00493 KServiceGroup::childGroup(
const QString &parent)
00494 {
00495
return KServiceGroupFactory::self()->findGroupByDesktopPath(
"#parent#"+parent,
true);
00496 }
00497
00498
QString
00499 KServiceGroup::directoryEntryPath()
const
00500
{
00501
return d->directoryEntryPath;
00502 }
00503
00504
00505
void KServiceGroup::virtual_hook(
int id,
void* data )
00506 { KSycocaEntry::virtual_hook(
id, data ); }
00507
00508
00509 KServiceSeparator::KServiceSeparator( )
00510 :
KSycocaEntry("separator")
00511 {
00512 }