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