kio Library API Documentation

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., 59 Temple Place - Suite 330,
00016  *  Boston, MA 02111-1307, USA.
00017  **/
00018 
00019 // $Id: kservicegroup.cpp,v 1.25 2002/11/19 21:07:31 bausi Exp $
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     QString directoryEntryPath;
00038     QStringList sortOrder;
00039   bool m_bNoDisplay;
00040 };
00041 
00042 KServiceGroup::KServiceGroup( const QString & name )
00043  : KSycocaEntry(name), m_childCount(-1)
00044 {
00045   d = new KServiceGroup::Private;
00046   m_bDeleted = false;
00047 }
00048 
00049 KServiceGroup::KServiceGroup( const QString &configFile, const QString & _relpath )
00050  : KSycocaEntry(_relpath), m_childCount(-1)
00051 {
00052   d = new KServiceGroup::Private;
00053   m_bDeleted = false;
00054 
00055   QString cfg = configFile;
00056   if (cfg.isEmpty())
00057      cfg = _relpath+".directory";
00058 
00059   d->directoryEntryPath = cfg;
00060 
00061   KConfig config( cfg, true, false, "apps" );
00062 
00063   config.setDesktopGroup();
00064 
00065   m_strCaption = config.readEntry( "Name" );
00066   m_strIcon = config.readEntry( "Icon" );
00067   m_strComment = config.readEntry( "Comment" );
00068   m_bDeleted = config.readBoolEntry( "Hidden", false );
00069   d->m_bNoDisplay = config.readBoolEntry( "NoDisplay", false );
00070   m_strBaseGroupName = config.readEntry( "X-KDE-BaseGroup" );
00071 
00072   d->sortOrder = config.readListEntry("SortOrder");
00073 
00074   // Fill in defaults.
00075   if (m_strCaption.isEmpty())
00076   {
00077      m_strCaption = _relpath;
00078      if (m_strCaption.right(1) == "/")
00079         m_strCaption = m_strCaption.left(m_strCaption.length()-1);
00080      int i = m_strCaption.findRev('/');
00081      if (i > 0)
00082         m_strCaption = m_strCaption.mid(i+1);
00083   }
00084   if (m_strIcon.isEmpty())
00085      m_strIcon = "folder";
00086 }
00087 
00088 KServiceGroup::KServiceGroup( QDataStream& _str, int offset, bool deep ) :
00089     KSycocaEntry( _str, offset )
00090 {
00091   d = new KServiceGroup::Private;
00092   m_bDeep = deep;
00093   load( _str );
00094 }
00095 
00096 KServiceGroup::~KServiceGroup()
00097 {
00098   delete d;
00099 }
00100 
00101 int KServiceGroup::childCount()
00102 {
00103   if (m_childCount == -1)
00104   {
00105      m_childCount = 0;
00106 
00107      for( List::ConstIterator it = m_serviceList.begin();
00108           it != m_serviceList.end(); it++)
00109      {
00110         KSycocaEntry *p = (*it);
00111         if (p->isType(KST_KService))
00112         {
00113            KService *service = static_cast<KService *>(p);
00114            if (!service->noDisplay())
00115               m_childCount++;
00116         }
00117         else if (p->isType(KST_KServiceGroup))
00118         {
00119            KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00120            m_childCount += serviceGroup->childCount();
00121         }
00122      }
00123   }
00124   return m_childCount;
00125 }
00126 
00127 
00128 bool KServiceGroup::noDisplay() const
00129 {
00130     return d->m_bNoDisplay;
00131 }
00132 
00133 void KServiceGroup::load( QDataStream& s )
00134 {
00135   QStringList groupList;
00136   Q_INT8 noDisplay;
00137   s >> m_strCaption >> m_strIcon >>
00138       m_strComment >> groupList >> m_strBaseGroupName >> m_childCount >>
00139       noDisplay >> d->directoryEntryPath >> d->sortOrder;
00140 
00141   d->m_bNoDisplay = (noDisplay != 0);
00142 
00143   if (m_bDeep)
00144   {
00145      for(QStringList::ConstIterator it = groupList.begin();
00146          it != groupList.end(); it++)
00147      {
00148         QString path = *it;
00149         if (path[path.length()-1] == '/')
00150         {
00151            KServiceGroup *serviceGroup;
00152            serviceGroup = KServiceGroupFactory::self()->findGroupByDesktopPath(path, false);
00153            m_serviceList.append( SPtr(serviceGroup) );
00154         }
00155         else
00156         {
00157            KService *service;
00158            service = KServiceFactory::self()->findServiceByDesktopPath(path);
00159            m_serviceList.append( SPtr(service) );
00160         }
00161      }
00162   }
00163 }
00164 
00165 void KServiceGroup::addEntry( KSycocaEntry *entry)
00166 {
00167   m_serviceList.append(entry);
00168 }
00169 
00170 void KServiceGroup::save( QDataStream& s )
00171 {
00172   KSycocaEntry::save( s );
00173 
00174   QStringList groupList;
00175   for( List::ConstIterator it = m_serviceList.begin();
00176        it != m_serviceList.end(); it++)
00177   {
00178      KSycocaEntry *p = (*it);
00179      if (p->isType(KST_KService))
00180      {
00181         KService *service = static_cast<KService *>(p);
00182         groupList.append( service->desktopEntryPath());
00183      }
00184      else if (p->isType(KST_KServiceGroup))
00185      {
00186         KServiceGroup *serviceGroup = static_cast<KServiceGroup *>(p);
00187         groupList.append( serviceGroup->relPath());
00188      }
00189      else
00190      {
00191         //fprintf(stderr, "KServiceGroup: Unexpected object in list!\n");
00192      }
00193   }
00194 
00195   (void) childCount();
00196 
00197   Q_INT8 noDisplay = d->m_bNoDisplay ? 1 : 0;
00198   s << m_strCaption << m_strIcon <<
00199       m_strComment << groupList << m_strBaseGroupName << m_childCount <<
00200       noDisplay << d->directoryEntryPath << d->sortOrder;
00201 }
00202 
00203 KServiceGroup::List
00204 KServiceGroup::entries(bool sort)
00205 {
00206    return entries(sort, true);
00207 }
00208 
00209 KServiceGroup::List
00210 KServiceGroup::entries(bool sort, bool excludeNoDisplay)
00211 {
00212     KServiceGroup *group = this;
00213 
00214     // If the entries haven't been loaded yet, we have to reload ourselves
00215     // together with the entries. We can't only load the entries afterwards
00216     // since the offsets could have been changed if the database has changed.
00217 
00218     if (!m_bDeep) {
00219 
00220         group =
00221             KServiceGroupFactory::self()->findGroupByDesktopPath(relPath(), true);
00222 
00223         if (0 == group) // No guarantee that we still exist!
00224             return List();
00225     }
00226 
00227     if (!sort)
00228         return group->m_serviceList;
00229 
00230 
00231     // Sort the list alphabetically, according to locale.
00232     // Groups come first, then services.
00233 
00234     KSortableValueList<SPtr,QCString> slist;
00235     KSortableValueList<SPtr,QCString> glist;
00236     for (List::ConstIterator it(group->m_serviceList.begin()); it != group->m_serviceList.end(); ++it)
00237     {
00238         KSycocaEntry *p = (*it);
00239         // Choose the right list
00240         KSortableValueList<SPtr,QCString> & list = p->isType(KST_KServiceGroup) ? glist : slist;
00241         QString name = p->isType(KST_KServiceGroup) ?
00242                                    static_cast<KServiceGroup *>(p)->caption() :
00243                                    p->name();
00244         QCString key( name.length() * 4 + 1 );
00245         // strxfrm() crashes on Solaris
00246 #ifndef USE_SOLARIS
00247         // maybe it'd be better to use wcsxfrm() where available
00248         size_t ln = strxfrm( key.data(), name.local8Bit().data(), key.size());
00249         if( ln != size_t( -1 ))
00250         {
00251             if( ln >= key.size())
00252             { // didn't fit?
00253                 key.resize( ln + 1 );
00254                 if( strxfrm( key.data(), name.local8Bit().data(), key.size()) == size_t( -1 ))
00255                     key = name.local8Bit();
00256             }
00257         }
00258         else
00259 #endif
00260         {
00261             key = name.local8Bit();
00262         }
00263         list.insert(key,SPtr(*it));
00264     }
00265     // Now sort
00266     slist.sort();
00267     glist.sort();
00268 
00269     List lsort;
00270     for(KSortableValueList<SPtr,QCString>::ConstIterator it = glist.begin(); it != glist.end(); ++it)
00271     {
00272         if (excludeNoDisplay)
00273         {
00274            KServiceGroup *serviceGroup = (KServiceGroup *)((KSycocaEntry *)((*it).value()));
00275            if (serviceGroup->noDisplay())
00276               continue;
00277         }
00278         lsort.append((*it).value());
00279     }
00280     for(KSortableValueList<SPtr,QCString>::ConstIterator it = slist.begin(); it != slist.end(); ++it)
00281     {
00282         if (excludeNoDisplay)
00283         {
00284            KService *service = (KService *)((KSycocaEntry *)((*it).value()));
00285            if (service->noDisplay())
00286               continue;
00287         }
00288         lsort.append((*it).value());
00289     }
00290 
00291     // honor the SortOrder Key
00292 
00293     QString rp = relPath();
00294     if(rp == "/") rp = QString::null;
00295 
00296     if (d->sortOrder.isEmpty())
00297         return lsort;
00298 
00299     //kdDebug() << "Honouring sort order " << order.join(",") << endl;
00300 
00301     // Iterate through the sort spec list. If we find an entry that matches one
00302     // in the original list, take it out of the original list and add it to the
00303     // sorted list. Finally, add all entries that are still in the original list
00304     // to the end of the sorted list.
00305 
00306     List sorted;
00307     List orig = lsort;
00308 
00309     for (QStringList::ConstIterator it(d->sortOrder.begin()); it != d->sortOrder.end(); ++it)
00310     {
00311         //kdDebug() << "order has : " << *it << endl;
00312         for (List::Iterator sit(orig.begin()); sit != orig.end(); ++sit)
00313             {
00314                 QString entry = (*sit)->entryPath();
00315                 // Groups have a trailing slash, we need to remove it first
00316                 if ( entry[entry.length()-1] == '/' )
00317                    entry.truncate(entry.length()-1);
00318                 //kdDebug() << "Comparing to : " << entry.mid(entry.findRev('/')+1) << endl;
00319                 if (*it == entry.mid(entry.findRev('/')+1))
00320                     {
00321                         //kdDebug() << "Appending to sorted : " << *it << endl;
00322                         sorted.append(*sit);
00323                         orig.remove(sit);
00324                         break;
00325                     }
00326             }
00327     }
00328 
00329     for (List::Iterator sit(orig.begin()); sit != orig.end(); ++sit)
00330         sorted.append(*sit);
00331 
00332     return sorted;
00333 }
00334 
00335 KServiceGroup::Ptr
00336 KServiceGroup::baseGroup( const QString & _baseGroupName )
00337 {
00338     return KServiceGroupFactory::self()->findBaseGroup(_baseGroupName, true);
00339 }
00340 
00341 KServiceGroup::Ptr
00342 KServiceGroup::root()
00343 {
00344    return KServiceGroupFactory::self()->findGroupByDesktopPath("/", true);
00345 }
00346 
00347 KServiceGroup::Ptr
00348 KServiceGroup::group(const QString &relPath)
00349 {
00350    if (relPath.isEmpty()) return root();
00351    return KServiceGroupFactory::self()->findGroupByDesktopPath(relPath, true);
00352 }
00353 
00354 KServiceGroup::Ptr
00355 KServiceGroup::childGroup(const QString &parent)
00356 {
00357    return KServiceGroupFactory::self()->findGroupByDesktopPath("#parent#"+parent, true);
00358 }
00359 
00360 QString
00361 KServiceGroup::directoryEntryPath() const
00362 {
00363    return d->directoryEntryPath;
00364 }
00365 
00366 void KServiceGroup::virtual_hook( int id, void* data )
00367 { KSycocaEntry::virtual_hook( id, data ); }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Mar 16 18:44:15 2005 by doxygen 1.3.3 written by Dimitri van Heesch, © 1997-2001