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