# kio Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:03 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003