kservicegroup.cpp

00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00003  *
00004  *  This library is free software; you can redistribute it and/or
00005  *  modify it under the terms of the GNU Library General Public
00006  *  License version 2 as published by the Free Software Foundation;
00007  *
00008  *  This library is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011  *  Library General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU Library General Public License
00014  *  along with this library; see the file COPYING.LIB.  If not, write to
00015  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  *  Boston, MA 02110-1301, USA.
00017  **/
00018 
00019 #include <kiconloader.h>
00020 #include <kglobal.h>
00021 #include <kstandarddirs.h>
00022 #include <klocale.h>
00023 #include <kdebug.h>
00024 #include <ksortablevaluelist.h>
00025 #include "kservicefactory.h"
00026 #include "kservicegroupfactory.h"
00027 #include "kservicegroup.h"
00028 #include "kservice.h"
00029 #include "ksycoca.h"
00030 
00031 class KServiceGroup::Private
00032 {
00033 public:
00034     Private() { m_bNoDisplay = false; m_bShowEmptyMenu = false;m_bShowInlineHeader=false;m_bInlineAlias=false; m_bAllowInline = false;m_inlineValue = 4;}
00035   bool m_bNoDisplay;
00036     bool m_bShowEmptyMenu;
00037     bool m_bShowInlineHeader;
00038     bool m_bInlineAlias;
00039     bool m_bAllowInline;
00040     int m_inlineValue;
00041     QStringList suppressGenericNames;
00042     QString directoryEntryPath;
00043     QStringList sortOrder;
00044 };
00045 
00046 KServiceGroup::KServiceGroup( const QString & name )
00047  : KSycocaEntry(name), m_childCount(-1)
00048 {
00049   d = new KServiceGroup::Private;
00050   m_bDeleted = false;
00051   m_bDeep = false;
00052 }
00053 
00054 KServiceGroup::KServiceGroup( const QString &configFile, const QString & _relpath )
00055  : KSycocaEntry(_relpath), m_childCount(-1)
00056 {
00057   d = new KServiceGroup::Private;
00058   m_bDeleted = false;
00059   m_bDeep = 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      QStringList onlyShowInList = config.readListEntry("OnlyShowIn", ';');
00080      if (! (onlyShowInList.contains("KDE") || onlyShowInList.contains("KDE3")))
00081         d->m_bNoDisplay = true;
00082   }
00083   if (config.hasKey("NotShowIn"))
00084   {
00085      QStringList notShowInList = config.readListEntry("NotShowIn", ';');
00086      if (notShowInList.contains("KDE") || notShowInList.contains("KDE3"))
00087         d->m_bNoDisplay = true;
00088   }
00089 
00090   m_strBaseGroupName = config.readEntry( "X-KDE-BaseGroup" );
00091   d->suppressGenericNames = config.readListEntry( "X-KDE-SuppressGenericNames" );
00092   d->sortOrder = config.readListEntry("SortOrder");
00093 
00094   // Fill in defaults.
00095   if (m_strCaption.isEmpty())
00096   {
00097      m_strCaption = _relpath;
00098      if (m_strCaption.right(1) == "/")
00099         m_strCaption = m_strCaption.left(m_strCaption.length()-1);
00100      int i = m_strCaption.findRev('/');
00101      if (i > 0)
00102         m_strCaption = m_strCaption.mid(i+1);
00103   }
00104   if (m_strIcon.isEmpty())
00105      m_strIcon = "folder";
00106 }
00107 
00108 KServiceGroup::KServiceGroup( QDataStream& _str, int offset, bool deep ) :
00109     KSycocaEntry( _str, offset )
00110 {
00111   d = new KServiceGroup::Private;
00112   m_bDeep = deep;
00113   load( _str );
00114 }
00115 
00116 KServiceGroup::~KServiceGroup()
00117 {
00118   delete d;
00119 }
00120 
00121 int KServiceGroup::childCount()
00122 {
00123   if (m_childCount == -1)
00124   {
00125      m_childCount = 0;
00126 
00127      for( List::ConstIterator it = m_serviceList.begin();
00128           it != m_serviceList.end(); it++)
00129      {
00130         KSycocaEntry *p = (*it);
00131         if (p->isType(KST_KService))
00132         {
00133            KService *service = static_cast<KService *>(p);
00134            if (!service->noDisplay())
00135               m_childCount++;
00136         }
00137         else if (p->isType(KST_KServiceGroup))
00138         {
00139            KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00140            m_childCount += serviceGroup->childCount();
00141         }
00142      }
00143   }
00144   return m_childCount;
00145 }
00146 
00147 
00148 bool KServiceGroup::showInlineHeader() const
00149 {
00150     return d->m_bShowInlineHeader;
00151 }
00152 
00153 bool KServiceGroup::showEmptyMenu() const
00154 {
00155     return d->m_bShowEmptyMenu;
00156 }
00157 
00158 bool KServiceGroup::inlineAlias() const
00159 {
00160     return d->m_bInlineAlias;
00161 }
00162 
00163 void KServiceGroup::setInlineAlias(bool _b)
00164 {
00165     d->m_bInlineAlias = _b;
00166 }
00167 
00168 void KServiceGroup::setShowEmptyMenu(bool _b)
00169 {
00170     d->m_bShowEmptyMenu=_b;
00171 }
00172 
00173 void KServiceGroup::setShowInlineHeader(bool _b)
00174 {
00175     d->m_bShowInlineHeader=_b;
00176 }
00177 
00178 int KServiceGroup::inlineValue() const
00179 {
00180     return d->m_inlineValue;
00181 }
00182 
00183 void KServiceGroup::setInlineValue(int _val)
00184 {
00185     d->m_inlineValue = _val;
00186 }
00187 
00188 bool KServiceGroup::allowInline() const
00189 {
00190     return d->m_bAllowInline;
00191 }
00192 
00193 void KServiceGroup::setAllowInline(bool _b)
00194 {
00195     d->m_bAllowInline = _b;
00196 }
00197 
00198 bool KServiceGroup::noDisplay() const
00199 {
00200   return d->m_bNoDisplay || m_strCaption.startsWith(".");
00201 }
00202 
00203 QStringList KServiceGroup::suppressGenericNames() const
00204 {
00205   return d->suppressGenericNames;
00206 }
00207 
00208 void KServiceGroup::load( QDataStream& s )
00209 {
00210   QStringList groupList;
00211   Q_INT8 noDisplay;
00212   Q_INT8 _showEmptyMenu;
00213   Q_INT8 inlineHeader;
00214   Q_INT8 _inlineAlias;
00215   Q_INT8 _allowInline;
00216   s >> m_strCaption >> m_strIcon >>
00217       m_strComment >> groupList >> m_strBaseGroupName >> m_childCount >>
00218       noDisplay >> d->suppressGenericNames >> d->directoryEntryPath >>
00219       d->sortOrder >> _showEmptyMenu >> inlineHeader >> _inlineAlias >> _allowInline;
00220 
00221   d->m_bNoDisplay = (noDisplay != 0);
00222   d->m_bShowEmptyMenu = ( _showEmptyMenu != 0 );
00223   d->m_bShowInlineHeader = ( inlineHeader != 0 );
00224   d->m_bInlineAlias = ( _inlineAlias != 0 );
00225   d->m_bAllowInline = ( _allowInline != 0 );
00226 
00227   if (m_bDeep)
00228   {
00229      for(QStringList::ConstIterator it = groupList.begin();
00230          it != groupList.end(); it++)
00231      {
00232         QString path = *it;
00233         if (path[path.length()-1] == '/')
00234         {
00235            KServiceGroup *serviceGroup;
00236            serviceGroup = KServiceGroupFactory::self()->findGroupByDesktopPath(path, false);
00237            if (serviceGroup)
00238               m_serviceList.append( SPtr(serviceGroup) );
00239         }
00240         else
00241         {
00242            KService *service;
00243            service = KServiceFactory::self()->findServiceByDesktopPath(path);
00244            if (service)
00245               m_serviceList.append( SPtr(service) );
00246         }
00247      }
00248   }
00249 }
00250 
00251 void KServiceGroup::addEntry( KSycocaEntry *entry)
00252 {
00253   m_serviceList.append(entry);
00254 }
00255 
00256 void KServiceGroup::save( QDataStream& s )
00257 {
00258   KSycocaEntry::save( s );
00259 
00260   QStringList groupList;
00261   for( List::ConstIterator it = m_serviceList.begin();
00262        it != m_serviceList.end(); it++)
00263   {
00264      KSycocaEntry *p = (*it);
00265      if (p->isType(KST_KService))
00266      {
00267         KService *service = static_cast<KService *>(p);
00268         groupList.append( service->desktopEntryPath());
00269      }
00270      else if (p->isType(KST_KServiceGroup))
00271      {
00272         KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00273         groupList.append( serviceGroup->relPath());
00274      }
00275      else
00276      {
00277         //fprintf(stderr, "KServiceGroup: Unexpected object in list!\n");
00278      }
00279   }
00280 
00281   (void) childCount();
00282 
00283   Q_INT8 noDisplay = d->m_bNoDisplay ? 1 : 0;
00284   Q_INT8 _showEmptyMenu = d->m_bShowEmptyMenu ? 1 : 0;
00285   Q_INT8 inlineHeader = d->m_bShowInlineHeader ? 1 : 0;
00286   Q_INT8 _inlineAlias = d->m_bInlineAlias ? 1 : 0;
00287   Q_INT8 _allowInline = d->m_bAllowInline ? 1 : 0;
00288   s << m_strCaption << m_strIcon <<
00289       m_strComment << groupList << m_strBaseGroupName << m_childCount <<
00290       noDisplay << d->suppressGenericNames << d->directoryEntryPath <<
00291       d->sortOrder <<_showEmptyMenu <<inlineHeader<<_inlineAlias<<_allowInline;
00292 }
00293 
00294 KServiceGroup::List
00295 KServiceGroup::entries(bool sort)
00296 {
00297    return entries(sort, true);
00298 }
00299 
00300 KServiceGroup::List
00301 KServiceGroup::entries(bool sort, bool excludeNoDisplay)
00302 {
00303    return entries(sort, excludeNoDisplay, false);
00304 }
00305 
00306 static void addItem(KServiceGroup::List &sorted, const KSycocaEntry::Ptr &p, bool &addSeparator)
00307 {
00308    if (addSeparator && !sorted.isEmpty())
00309       sorted.append(new KServiceSeparator());
00310    sorted.append(p);
00311    addSeparator = false;
00312 }
00313 
00314 KServiceGroup::List
00315 KServiceGroup::entries(bool sort, bool excludeNoDisplay, bool allowSeparators, bool sortByGenericName)
00316 {
00317     KServiceGroup *group = this;
00318 
00319     // If the entries haven't been loaded yet, we have to reload ourselves
00320     // together with the entries. We can't only load the entries afterwards
00321     // since the offsets could have been changed if the database has changed.
00322 
00323     if (!m_bDeep) {
00324 
00325         group =
00326             KServiceGroupFactory::self()->findGroupByDesktopPath(relPath(), true);
00327 
00328         if (0 == group) // No guarantee that we still exist!
00329             return List();
00330     }
00331 
00332     if (!sort)
00333         return group->m_serviceList;
00334 
00335     // Sort the list alphabetically, according to locale.
00336     // Groups come first, then services.
00337 
00338     KSortableValueList<SPtr,QCString> slist;
00339     KSortableValueList<SPtr,QCString> glist;
00340     for (List::ConstIterator it(group->m_serviceList.begin()); it != group->m_serviceList.end(); ++it)
00341     {
00342         KSycocaEntry *p = (*it);
00343     bool noDisplay = p->isType(KST_KServiceGroup) ?
00344                                    static_cast<KServiceGroup *>(p)->noDisplay() :
00345                                    static_cast<KService *>(p)->noDisplay();
00346         if (excludeNoDisplay && noDisplay)
00347            continue;
00348         // Choose the right list
00349         KSortableValueList<SPtr,QCString> & list = p->isType(KST_KServiceGroup) ? glist : slist;
00350         QString name;
00351         if (p->isType(KST_KServiceGroup))
00352           name = static_cast<KServiceGroup *>(p)->caption();
00353         else if (sortByGenericName)
00354           name = static_cast<KService *>(p)->genericName() + " " + p->name();
00355         else
00356           name = p->name() + " " + static_cast<KService *>(p)->genericName();
00357 
00358         QCString key( name.length() * 4 + 1 );
00359         // strxfrm() crashes on Solaris
00360 #ifndef USE_SOLARIS
00361         // maybe it'd be better to use wcsxfrm() where available
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             { // didn't fit?
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     // Now sort
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]"; //just inline header
00388     }
00389 
00390     QString rp = relPath();
00391     if(rp == "/") rp = QString::null;
00392 
00393     // Iterate through the sort spec list.
00394     // If an entry gets mentioned explicitly, we remove it from the sorted list
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            // Remove entry from sorted list of services.
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            // Remove entry from sorted list of services.
00416            // TODO: Remove item from sortOrder-list if not found
00417            // TODO: This prevents duplicates
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     // Iterate through the sort spec list.
00434     // Add the entries to the list according to the sort spec.
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           // Special condition...
00442           if (item == ":S")
00443           {
00444              if (allowSeparators)
00445                 needSeparator = true;
00446           }
00447           else if ( item.contains( ":O" ) )
00448           {
00449               //todo parse attribute:
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 = false;
00458               bool showInlineAlias = false;
00459               int inlineValue = -1;
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             // Add sorted list of sub-menus
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             // Add sorted list of services
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             // Add sorted lists of services and submenus
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; // Done
00504 
00505                   // Insert remaining sub-menu
00506                   addItem(sorted, (*it_g).value(), needSeparator);
00507                   it_g++;
00508                }
00509                else if (it_g == glist.end())
00510                {
00511                   // Insert remaining service
00512                   addItem(sorted, (*it_s).value(), needSeparator);
00513                   it_s++;
00514                }
00515                else if ((*it_g).index() < (*it_s).index())
00516                {
00517                   // Insert sub-menu first
00518                   addItem(sorted, (*it_g).value(), needSeparator);
00519                   it_g++;
00520                }
00521                else
00522                {
00523                   // Insert service first
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                             for ( QStringList::Iterator it3 = optionAttribute.begin(); it3 != optionAttribute.end(); ++it3 )
00557                             {
00558                                 parseAttribute( *it3 , bShowEmptyMenu, bShowInline, bShowInlineHeader, bShowInlineAlias , inlineValue );
00559                                 group->setShowEmptyMenu( bShowEmptyMenu );
00560                                 group->setAllowInline( bShowInline );
00561                                 group->setShowInlineHeader( bShowInlineHeader );
00562                                 group->setInlineAlias( bShowInlineAlias );
00563                                 group->setInlineValue( inlineValue );
00564                             }
00565                         }
00566                         else
00567                             it--;
00568 
00569                         addItem(sorted, (group), needSeparator);
00570                     }
00571                     break;
00572                 }
00573             }
00574         }
00575         else
00576         {
00577             for (List::ConstIterator it2(group->m_serviceList.begin()); it2 != group->m_serviceList.end(); ++it2)
00578             {
00579                 if (!(*it2)->isType(KST_KService))
00580                     continue;
00581                 KService *service = (KService *)((KSycocaEntry *)(*it2));
00582                 if (service->menuId() == item)
00583                 {
00584                     if (!excludeNoDisplay || !service->noDisplay())
00585                         addItem(sorted, (*it2), needSeparator);
00586                     break;
00587                 }
00588             }
00589         }
00590     }
00591 
00592     return sorted;
00593 }
00594 
00595 void KServiceGroup::parseAttribute( const QString &item ,  bool &showEmptyMenu, bool &showInline, bool &showInlineHeader, bool & showInlineAlias , int &inlineValue )
00596 {
00597     if( item == "ME") //menu empty
00598         showEmptyMenu=true;
00599     else if ( item == "NME") //not menu empty
00600         showEmptyMenu=false;
00601     else if( item == "I") //inline menu !
00602         showInline = true;
00603     else if ( item == "NI") //not inline menu!
00604         showInline = false;
00605     else if( item == "IH") //inline  header!
00606         showInlineHeader= true;
00607     else if ( item == "NIH") //not inline  header!
00608         showInlineHeader = false;
00609     else if( item == "IA") //inline alias!
00610         showInlineAlias = true;
00611     else if (  item == "NIA") //not inline alias!
00612         showInlineAlias = false;
00613     else if( ( item ).contains( "IL" )) //inline limite!
00614     {
00615         QString tmp( item );
00616         tmp = tmp.remove( "IL[" );
00617         tmp = tmp.remove( "]" );
00618         bool ok;
00619         int _inlineValue = tmp.toInt(&ok);
00620         if ( !ok ) //error
00621             _inlineValue = -1;
00622         inlineValue =  _inlineValue;
00623     }
00624     else
00625         kdDebug()<<" This attribute is not supported :"<<item<<endl;
00626 }
00627 
00628 void KServiceGroup::setLayoutInfo(const QStringList &layout)
00629 {
00630     d->sortOrder = layout;
00631 }
00632 
00633 QStringList KServiceGroup::layoutInfo() const
00634 {
00635     return d->sortOrder;
00636 }
00637 
00638 KServiceGroup::Ptr
00639 KServiceGroup::baseGroup( const QString & _baseGroupName )
00640 {
00641     return KServiceGroupFactory::self()->findBaseGroup(_baseGroupName, true);
00642 }
00643 
00644 KServiceGroup::Ptr
00645 KServiceGroup::root()
00646 {
00647    return KServiceGroupFactory::self()->findGroupByDesktopPath("/", true);
00648 }
00649 
00650 KServiceGroup::Ptr
00651 KServiceGroup::group(const QString &relPath)
00652 {
00653    if (relPath.isEmpty()) return root();
00654    return KServiceGroupFactory::self()->findGroupByDesktopPath(relPath, true);
00655 }
00656 
00657 KServiceGroup::Ptr
00658 KServiceGroup::childGroup(const QString &parent)
00659 {
00660    return KServiceGroupFactory::self()->findGroupByDesktopPath("#parent#"+parent, true);
00661 }
00662 
00663 QString
00664 KServiceGroup::directoryEntryPath() const
00665 {
00666    return d->directoryEntryPath;
00667 }
00668 
00669 
00670 void KServiceGroup::virtual_hook( int id, void* data )
00671 { KSycocaEntry::virtual_hook( id, data ); }
00672 
00673 
00674 KServiceSeparator::KServiceSeparator( )
00675  : KSycocaEntry("separator")
00676 {
00677 }
KDE Home | KDE Accessibility Home | Description of Access Keys