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