kio Library API Documentation

kservice.cpp

00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 - 2001 Waldo Bastian <bastian@kde.org>
00003  *  Copyright (C) 1999        David Faure   <faure@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  *  Boston, MA 02111-1307, USA.
00018  **/
00019 
00020 // $Id: kservice.cpp,v 1.157 2004/09/21 14:39:29 waba Exp $
00021 
00022 #include <config.h>
00023 
00024 #include "kservice.h"
00025 #include "kservice_p.h"
00026 
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 
00030 #include <stddef.h>
00031 #include <unistd.h>
00032 #include <stdlib.h>
00033 
00034 #include <qstring.h>
00035 #include <qfile.h>
00036 #include <qdir.h>
00037 #include <qtl.h>
00038 #include <qfile.h>
00039 
00040 #include <ksimpleconfig.h>
00041 #include <kstddirs.h>
00042 #include <kapplication.h>
00043 #include <kdebug.h>
00044 #include <kdesktopfile.h>
00045 #include <kglobal.h>
00046 #include <kiconloader.h>
00047 #include <klocale.h>
00048 #include <kconfigbase.h>
00049 #include <kstandarddirs.h>
00050 #include <dcopclient.h>
00051 
00052 #include "kservicefactory.h"
00053 #include "kservicetypefactory.h"
00054 #include "kservicetype.h"
00055 #include "kuserprofile.h"
00056 #include "ksycoca.h"
00057 
00058 class KService::KServicePrivate
00059 {
00060 public:
00061   QStringList categories;
00062   QString menuId;
00063 };
00064 
00065 KService::KService( const QString & _name, const QString &_exec, const QString &_icon)
00066  : KSycocaEntry( QString::null)
00067 {
00068   d = new KServicePrivate;
00069   m_bValid = true;
00070   m_bDeleted = false;
00071   m_strType = "Application";
00072   m_strName = _name;
00073   m_strExec = _exec;
00074   m_strIcon = _icon;
00075   m_bTerminal = false;
00076   m_bAllowAsDefault = true;
00077   m_initialPreference = 10;
00078 }
00079 
00080 
00081 KService::KService( const QString & _fullpath )
00082  : KSycocaEntry( _fullpath)
00083 {
00084   KDesktopFile config( _fullpath );
00085 
00086   init(&config);
00087 }
00088 
00089 KService::KService( KDesktopFile *config )
00090  : KSycocaEntry( config->fileName())
00091 {
00092   init(config);
00093 }
00094 
00095 void
00096 KService::init( KDesktopFile *config )
00097 {
00098   d = new KServicePrivate;
00099   m_bValid = true;
00100 
00101   bool absPath = !QDir::isRelativePath(entryPath());
00102 
00103   config->setDesktopGroup();
00104 
00105   QMap<QString, QString> entryMap = config->entryMap(config->group());
00106 
00107   entryMap.remove("Encoding"); // reserved as part of Desktop Entry Standard
00108   entryMap.remove("Version");  // reserved as part of Desktop Entry Standard
00109 
00110   m_bDeleted = config->readBoolEntry( "Hidden", false );
00111   entryMap.remove("Hidden");
00112   if (m_bDeleted)
00113   {
00114     m_bValid = false;
00115     return;
00116   } else if(!absPath) {
00117     QStringList list=KGlobal::dirs()->findAllResources(QFile::encodeName(config->resource()), entryPath());
00118     bool ok=false;
00119     for(QStringList::ConstIterator it=list.fromLast(); !ok && it!=list.end(); it--) {
00120       if(!access(QFile::encodeName(*it), R_OK))
00121         ok=true;
00122     }
00123     if(!ok) {
00124       m_bValid = false;
00125       return;
00126     }
00127   }
00128 
00129   m_strName = config->readEntry( "Name" );
00130   entryMap.remove("Name");
00131   if ( m_strName.isEmpty() )
00132   {
00133     if (config->readEntry( "Exec" ).isEmpty())
00134     {
00135       m_bValid = false;
00136       return;
00137     }
00138     // Try to make up a name.
00139     m_strName = entryPath();
00140     int i = m_strName.findRev('/');
00141     m_strName = m_strName.mid(i+1);
00142     i = m_strName.findRev('.');
00143     if (i != -1)
00144        m_strName = m_strName.left(i);
00145   }
00146 
00147   m_strType = config->readEntry( "Type" );
00148   entryMap.remove("Type");
00149   if ( m_strType.isEmpty() )
00150   {
00151     /*kdWarning(7012) << "The desktop entry file " << entryPath()
00152                     << " has no Type=... entry."
00153                     << " It should be \"Application\" or \"Service\"" << endl;
00154     m_bValid = false;
00155     return;*/
00156     m_strType = "Application";
00157   } else if ( m_strType != "Application" && m_strType != "Service" )
00158   {
00159     kdWarning(7012) << "The desktop entry file " << entryPath()
00160                     << " has Type=" << m_strType
00161                     << " instead of \"Application\" or \"Service\"" << endl;
00162     m_bValid = false;
00163     return;
00164   }
00165 
00166   // In case Try Exec is set, check if the application is available
00167   if (!config->tryExec()) {
00168       m_bDeleted = true;
00169       m_bValid = false;
00170       return;
00171   }
00172 
00173   QString resource = config->resource();
00174 
00175   if ( (m_strType == "Application") &&
00176        (!resource.isEmpty()) &&
00177        (resource != "apps") &&
00178        !absPath)
00179   {
00180     kdWarning(7012) << "The desktop entry file " << entryPath()
00181            << " has Type=" << m_strType << " but is located under \"" << resource
00182            << "\" instead of \"apps\"" << endl;
00183     m_bValid = false;
00184     return;
00185   }
00186 
00187   if ( (m_strType == "Service") &&
00188        (!resource.isEmpty()) &&
00189        (resource != "services") &&
00190        !absPath)
00191   {
00192     kdWarning(7012) << "The desktop entry file " << entryPath()
00193            << " has Type=" << m_strType << " but is located under \"" << resource
00194            << "\" instead of \"services\"" << endl;
00195     m_bValid = false;
00196     return;
00197   }
00198 
00199   QString name = entryPath();
00200   int pos = name.findRev('/');
00201   if (pos != -1)
00202      name = name.mid(pos+1);
00203   pos = name.find('.');
00204   if (pos != -1)
00205      name = name.left(pos);
00206 
00207   m_strExec = config->readPathEntry( "Exec" );
00208   entryMap.remove("Exec");
00209 
00210   m_strIcon = config->readEntry( "Icon", "unknown" );
00211   entryMap.remove("Icon");
00212   m_bTerminal = (config->readBoolEntry( "Terminal" )); // should be a property IMHO
00213   entryMap.remove("Terminal");
00214   m_strTerminalOptions = config->readEntry( "TerminalOptions" ); // should be a property IMHO
00215   entryMap.remove("TerminalOptions");
00216   m_strPath = config->readPathEntry( "Path" );
00217   entryMap.remove("Path");
00218   m_strComment = config->readEntry( "Comment" );
00219   entryMap.remove("Comment");
00220   m_strGenName = config->readEntry( "GenericName" );
00221   entryMap.remove("GenericName");
00222   QString untranslatedGenericName = config->readEntryUntranslated( "GenericName" );
00223   entryMap.insert("UntranslatedGenericName", untranslatedGenericName);
00224 
00225   m_lstKeywords = config->readListEntry("Keywords");
00226   entryMap.remove("Keywords");
00227   d->categories = config->readListEntry("Categories", ';');
00228   entryMap.remove("Categories");
00229   m_strLibrary = config->readEntry( "X-KDE-Library" );
00230   entryMap.remove("X-KDE-Library");
00231   m_strInit = config->readEntry("X-KDE-Init" );
00232   entryMap.remove("X-KDE-Init");
00233 
00234   m_lstServiceTypes = config->readListEntry( "ServiceTypes" );
00235   entryMap.remove("ServiceTypes");
00236   // For compatibility with KDE 1.x
00237   m_lstServiceTypes += config->readListEntry( "MimeType", ';' );
00238   entryMap.remove("MimeType");
00239 
00240   if ( m_strType == "Application" && !m_lstServiceTypes.contains("Application") )
00241     // Applications implement the service type "Application" ;-)
00242     m_lstServiceTypes += "Application";
00243 
00244   QString dcopServiceType = config->readEntry("X-DCOP-ServiceType").lower();
00245   entryMap.remove("X-DCOP-ServiceType");
00246   if (dcopServiceType == "unique")
00247      m_DCOPServiceType = DCOP_Unique;
00248   else if (dcopServiceType == "multi")
00249      m_DCOPServiceType = DCOP_Multi;
00250   else if (dcopServiceType == "wait")
00251      m_DCOPServiceType = DCOP_Wait;
00252   else
00253      m_DCOPServiceType = DCOP_None;
00254 
00255   m_strDesktopEntryName = name.lower();
00256 
00257   m_bAllowAsDefault = config->readBoolEntry( "AllowDefault", true );
00258   entryMap.remove("AllowDefault");
00259 
00260   m_initialPreference = config->readNumEntry( "InitialPreference", 1 );
00261   entryMap.remove("InitialPreference");
00262 
00263   // Store all additional entries in the property map.
00264   // A QMap<QString,QString> would be easier for this but we can't
00265   // brake BC, so we have to store it in m_mapProps.
00266 //  qWarning("Path = %s", entryPath().latin1());
00267   QMap<QString,QString>::ConstIterator it = entryMap.begin();
00268   for( ; it != entryMap.end();++it)
00269   {
00270 //     qWarning("   Key = %s Data = %s", it.key().latin1(), it.data().latin1());
00271      m_mapProps.insert( it.key(), QVariant( it.data()));
00272   }
00273 }
00274 
00275 KService::KService( QDataStream& _str, int offset ) : KSycocaEntry( _str, offset )
00276 {
00277   d = new KServicePrivate;
00278   load( _str );
00279 }
00280 
00281 KService::~KService()
00282 {
00283   //debug("KService::~KService()");
00284   delete d;
00285 }
00286 
00287 QPixmap KService::pixmap( KIcon::Group _group, int _force_size, int _state, QString * _path ) const
00288 {
00289   KIconLoader *iconLoader=KGlobal::iconLoader();
00290   if (!iconLoader->extraDesktopThemesAdded())
00291   {
00292       QPixmap pixmap=iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path, true );
00293       if (!pixmap.isNull() ) return pixmap;
00294 
00295       iconLoader->addExtraDesktopThemes();
00296   }
00297 
00298   return iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path );
00299 }
00300 
00301 void KService::load( QDataStream& s )
00302 {
00303   // dummies are here because of fields that were removed, to keep bin compat.
00304   // Feel free to re-use, but fields for Applications only (not generic services)
00305   // should rather be added to application.desktop
00306   Q_INT8 def, term, dummy1, dummy2;
00307   Q_INT8 dst, initpref;
00308   QString dummyStr1, dummyStr2;
00309   int dummyI1, dummyI2;
00310   Q_UINT32 dummyUI32;
00311 
00312   // WARNING: IN KDE 3.x THIS NEEDS TO REMAIN COMPATIBLE WITH KDE 2.x!
00313   // !! This data structure should remain binary compatible at all times !!
00314   // You may add new fields at the end. Make sure to update the version
00315   // number in ksycoca.h
00316   s >> m_strType >> m_strName >> m_strExec >> m_strIcon
00317     >> term >> m_strTerminalOptions
00318     >> m_strPath >> m_strComment >> m_lstServiceTypes >> def >> m_mapProps
00319     >> m_strLibrary >> dummyI1 >> dummyI2
00320     >> dst
00321     >> m_strDesktopEntryName
00322     >> dummy1 >> dummyStr1 >> initpref >> dummyStr2 >> dummy2
00323     >> m_lstKeywords >> m_strInit >> dummyUI32 >> m_strGenName
00324     >> d->categories >> d->menuId;
00325 
00326   m_bAllowAsDefault = def;
00327   m_bTerminal = term;
00328   m_DCOPServiceType = (DCOPServiceType_t) dst;
00329   m_initialPreference = initpref;
00330 
00331   m_bValid = true;
00332 }
00333 
00334 void KService::save( QDataStream& s )
00335 {
00336   KSycocaEntry::save( s );
00337   Q_INT8 def = m_bAllowAsDefault, initpref = m_initialPreference;
00338   Q_INT8 term = m_bTerminal;
00339   Q_INT8 dst = (Q_INT8) m_DCOPServiceType;
00340   Q_INT8 dummy1 = 0, dummy2 = 0; // see ::load
00341   QString dummyStr1, dummyStr2;
00342   int dummyI1 = 0, dummyI2 = 0;
00343   Q_UINT32 dummyUI32 = 0;
00344 
00345   // WARNING: IN KDE 3.x THIS NEEDS TO REMAIN COMPATIBLE WITH KDE 2.x!
00346   // !! This data structure should remain binary compatible at all times !!
00347   // You may add new fields at the end. Make sure to update the version
00348   // number in ksycoca.h
00349   s << m_strType << m_strName << m_strExec << m_strIcon
00350     << term << m_strTerminalOptions
00351     << m_strPath << m_strComment << m_lstServiceTypes << def << m_mapProps
00352     << m_strLibrary << dummyI1 << dummyI2
00353     << dst
00354     << m_strDesktopEntryName
00355     << dummy1 << dummyStr1 << initpref << dummyStr2 << dummy2
00356     << m_lstKeywords << m_strInit << dummyUI32 << m_strGenName
00357     << d->categories << d->menuId;
00358 }
00359 
00360 bool KService::hasServiceType( const QString& _servicetype ) const
00361 {
00362   if (!m_bValid) return false; // safety test
00363 
00364   //kdDebug(7012) << "Testing " << m_strDesktopEntryName << " for " << _servicetype << endl;
00365 
00366   KMimeType::Ptr mimePtr = KMimeType::mimeType( _servicetype );
00367   if ( mimePtr && mimePtr == KMimeType::defaultMimeTypePtr() )
00368       mimePtr = 0;
00369 
00370   bool isNumber;
00371   // For each service type we are associated with, if it doesn't
00372   // match then we try its parent service types.
00373   QStringList::ConstIterator it = m_lstServiceTypes.begin();
00374   for( ; it != m_lstServiceTypes.end(); ++it )
00375   {
00376       (*it).toInt(&isNumber);
00377       if (isNumber)
00378          continue;
00379       //kdDebug(7012) << "    has " << (*it) << endl;
00380       KServiceType::Ptr ptr = KServiceType::serviceType( *it );
00381       if ( ptr && ptr->inherits( _servicetype ) )
00382           return true;
00383 
00384       // The mimetype inheritance ("is also") works the other way.
00385       // e.g. if we're looking for a handler for mimePtr==smb-workgroup
00386       // then a handler for inode/directory is ok.
00387       if ( mimePtr && mimePtr->is( *it ) )
00388           return true;
00389   }
00390   return false;
00391 }
00392 
00393 int KService::initialPreferenceForMimeType( const QString& mimeType ) const
00394 {
00395   if (!m_bValid) return 0; // safety test
00396 
00397   bool isNumber;
00398 
00399   // For each service type we are associated with
00400   QStringList::ConstIterator it = m_lstServiceTypes.begin();
00401   for( ; it != m_lstServiceTypes.end(); ++it )
00402   {
00403       (*it).toInt(&isNumber);
00404       if (isNumber)
00405          continue;
00406       //kdDebug(7012) << "    has " << (*it) << endl;
00407       KServiceType::Ptr ptr = KServiceType::serviceType( *it );
00408       if ( !ptr || !ptr->inherits( mimeType ) )
00409           continue;
00410 
00411       int initalPreference = m_initialPreference;
00412       ++it;
00413       if (it != m_lstServiceTypes.end())
00414       {
00415          int i = (*it).toInt(&isNumber);
00416          if (isNumber)
00417             initalPreference = i;
00418       }
00419       return initalPreference;
00420   }
00421 
00422   KMimeType::Ptr mimePtr = KMimeType::mimeType( mimeType );
00423   if ( mimePtr && mimePtr == KMimeType::defaultMimeTypePtr() )
00424       mimePtr = 0;
00425 
00426   // Try its parent service types.
00427   it = m_lstServiceTypes.begin();
00428   for( ; it != m_lstServiceTypes.end(); ++it )
00429   {
00430       (*it).toInt(&isNumber);
00431       if (isNumber)
00432          continue;
00433 
00434       // The mimetype inheritance ("is also") works the other way.
00435       // e.g. if we're looking for a handler for mimePtr==smb-workgroup
00436       // then a handler for inode/directory is ok.
00437       if ( !mimePtr || !mimePtr->is( *it ) )
00438           continue;
00439 
00440       int initalPreference = m_initialPreference;
00441       ++it;
00442       if (it != m_lstServiceTypes.end())
00443       {
00444          int i = (*it).toInt(&isNumber);
00445          if (isNumber)
00446             initalPreference = i;
00447       }
00448       return initalPreference;
00449   }
00450   return 0;
00451 }
00452 
00453 class KServiceReadProperty : public KConfigBase
00454 {
00455 public:
00456    KServiceReadProperty(const QString &_key, const QCString &_value)
00457     : key(_key), value(_value) { }
00458 
00459    bool internalHasGroup(const QCString &) const { /*qDebug("hasGroup(const QCString &)");*/ return false; }
00460 
00461    QStringList groupList() const { return QStringList(); }
00462 
00463    QMap<QString,QString> entryMap(const QString &) const
00464       { return QMap<QString,QString>(); }
00465 
00466    void reparseConfiguration() { }
00467 
00468    KEntryMap internalEntryMap( const QString &) const { return KEntryMap(); }
00469 
00470    KEntryMap internalEntryMap() const { return KEntryMap(); }
00471 
00472    void putData(const KEntryKey &, const KEntry&, bool) { }
00473 
00474    KEntry lookupData(const KEntryKey &) const
00475    { KEntry entry; entry.mValue = value; return entry; }
00476 protected:
00477    QString key;
00478    QCString value;
00479 };
00480 
00481 QVariant KService::property( const QString& _name) const
00482 {
00483    return property( _name, QVariant::Invalid);
00484 }
00485 
00486 // Return a string QVariant if string isn't null, and invalid variant otherwise
00487 // (the variant must be invalid if the field isn't in the .desktop file)
00488 // This allows trader queries like "exist Library" to work.
00489 static QVariant makeStringVariant( const QString& string )
00490 {
00491     // Using isEmpty here would be wrong.
00492     // Empty is "specified but empty", null is "not specified" (in the .desktop file)
00493     return string.isNull() ? QVariant() : QVariant( string );
00494 }
00495 
00496 QVariant KService::property( const QString& _name, QVariant::Type t ) const
00497 {
00498   if ( _name == "Type" )
00499     return QVariant( m_strType ); // can't be null
00500   else if ( _name == "Name" )
00501     return QVariant( m_strName ); // can't be null
00502   else if ( _name == "Exec" )
00503     return makeStringVariant( m_strExec );
00504   else if ( _name == "Icon" )
00505     return makeStringVariant( m_strIcon );
00506   else if ( _name == "Terminal" )
00507     return QVariant( static_cast<int>(m_bTerminal) );
00508   else if ( _name == "TerminalOptions" )
00509     return makeStringVariant( m_strTerminalOptions );
00510   else if ( _name == "Path" )
00511     return makeStringVariant( m_strPath );
00512   else if ( _name == "Comment" )
00513     return makeStringVariant( m_strComment );
00514   else if ( _name == "GenericName" )
00515     return makeStringVariant( m_strGenName );
00516   else if ( _name == "ServiceTypes" )
00517     return QVariant( m_lstServiceTypes );
00518   else if ( _name == "AllowAsDefault" )
00519     return QVariant( static_cast<int>(m_bAllowAsDefault) );
00520   else if ( _name == "InitialPreference" )
00521     return QVariant( m_initialPreference );
00522   else if ( _name == "Library" )
00523     return makeStringVariant( m_strLibrary );
00524   else if ( _name == "DesktopEntryPath" ) // can't be null
00525     return QVariant( entryPath() );
00526   else if ( _name == "DesktopEntryName")
00527     return QVariant( m_strDesktopEntryName ); // can't be null
00528   else if ( _name == "Categories")
00529     return QVariant( d->categories );
00530   else if ( _name == "Keywords")
00531     return QVariant( m_lstKeywords );
00532 
00533   // Ok we need to convert the property from a QString to its real type.
00534   // Maybe the caller helped us.
00535   if (t == QVariant::Invalid)
00536   {
00537     // No luck, let's ask KServiceTypeFactory what the type of this property
00538     // is supposed to be.
00539     t = KServiceTypeFactory::self()->findPropertyTypeByName(_name);
00540     if (t == QVariant::Invalid)
00541     {
00542       kdDebug(7012) << "Request for unknown property '" << _name << "'\n";
00543       return QVariant(); // Unknown property: Invalid variant.
00544     }
00545   }
00546 
00547   // Then we use a homebuild class based on KConfigBase to convert the QString.
00548   // For some often used property types we do the conversion ourselves.
00549   QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( _name );
00550   if ( (it == m_mapProps.end()) || (!it.data().isValid()))
00551   {
00552      //kdDebug(7012) << "Property not found " << _name << endl;
00553      return QVariant(); // No property set.
00554   }
00555 
00556   switch(t)
00557   {
00558     case QVariant::String:
00559         return it.data();
00560     case QVariant::Bool:
00561     case QVariant::Int:
00562         {
00563            QString aValue = it.data().toString();
00564            int val = 0;
00565            if (aValue == "true" || aValue == "on" || aValue == "yes")
00566               val = 1;
00567            else
00568            {
00569               bool bOK;
00570               val = aValue.toInt( &bOK );
00571               if( !bOK )
00572                  val = 0;
00573            }
00574            if (t == QVariant::Bool)
00575            {
00576                return QVariant((bool)val, 1);
00577            }
00578            return QVariant(val);
00579         }
00580     default:
00581         // All others
00582         KServiceReadProperty ksrp(_name, it.data().toString().utf8());
00583         return ksrp.readPropertyEntry(_name, t);
00584   }
00585 }
00586 
00587 QStringList KService::propertyNames() const
00588 {
00589   QStringList res;
00590 
00591   QMap<QString,QVariant>::ConstIterator it = m_mapProps.begin();
00592   for( ; it != m_mapProps.end(); ++it )
00593     res.append( it.key() );
00594 
00595   res.append( "Type" );
00596   res.append( "Name" );
00597   res.append( "Comment" );
00598   res.append( "GenericName" );
00599   res.append( "Icon" );
00600   res.append( "Exec" );
00601   res.append( "Terminal" );
00602   res.append( "TerminalOptions" );
00603   res.append( "Path" );
00604   res.append( "ServiceTypes" );
00605   res.append( "AllowAsDefault" );
00606   res.append( "InitialPreference" );
00607   res.append( "Library" );
00608   res.append( "DesktopEntryPath" );
00609   res.append( "DesktopEntryName" );
00610   res.append( "Keywords" );
00611   res.append( "Categories" );
00612 
00613   return res;
00614 }
00615 
00616 KService::List KService::allServices()
00617 {
00618   return KServiceFactory::self()->allServices();
00619 }
00620 
00621 KService::Ptr KService::serviceByName( const QString& _name )
00622 {
00623   KService * s = KServiceFactory::self()->findServiceByName( _name );
00624   return KService::Ptr( s );
00625 }
00626 
00627 KService::Ptr KService::serviceByDesktopPath( const QString& _name )
00628 {
00629   KService * s = KServiceFactory::self()->findServiceByDesktopPath( _name );
00630   return KService::Ptr( s );
00631 }
00632 
00633 KService::Ptr KService::serviceByDesktopName( const QString& _name )
00634 {
00635   KService * s = KServiceFactory::self()->findServiceByDesktopName( _name.lower() );
00636   if (!s && !_name.startsWith("kde-"))
00637      s = KServiceFactory::self()->findServiceByDesktopName( "kde-"+_name.lower() );
00638   return KService::Ptr( s );
00639 }
00640 
00641 KService::Ptr KService::serviceByMenuId( const QString& _name )
00642 {
00643   KService * s = KServiceFactory::self()->findServiceByMenuId( _name );
00644   return KService::Ptr( s );
00645 }
00646 
00647 KService::Ptr KService::serviceByStorageId( const QString& _storageId )
00648 {
00649   KService::Ptr service = KService::serviceByMenuId( _storageId );
00650   if (service)
00651      return service;
00652 
00653   service = KService::serviceByDesktopPath(_storageId);
00654   if (service)
00655      return service;
00656 
00657   if (!QDir::isRelativePath(_storageId) && QFile::exists(_storageId))
00658      return new KService(_storageId);
00659 
00660   QString tmp = _storageId;
00661   tmp = tmp.mid(tmp.findRev('/')+1); // Strip dir
00662 
00663   if (tmp.endsWith(".desktop"))
00664      tmp.truncate(tmp.length()-8);
00665 
00666   if (tmp.endsWith(".kdelnk"))
00667      tmp.truncate(tmp.length()-7);
00668 
00669   service = KService::serviceByDesktopName(tmp);
00670 
00671   return service;
00672 }
00673 
00674 KService::List KService::allInitServices()
00675 {
00676   return KServiceFactory::self()->allInitServices();
00677 }
00678 
00679 bool KService::substituteUid() const {
00680   QVariant v = property("X-KDE-SubstituteUID", QVariant::Bool);
00681   return v.isValid() && v.toBool();
00682 }
00683 
00684 QString KService::username() const {
00685   // See also KDesktopFile::tryExec()
00686   QString user;
00687   QVariant v = property("X-KDE-Username", QVariant::String);
00688   user = v.isValid() ? v.toString() : QString::null;
00689   if (user.isEmpty())
00690      user = ::getenv("ADMIN_ACCOUNT");
00691   if (user.isEmpty())
00692      user = "root";
00693   return user;
00694 }
00695 
00696 bool KService::noDisplay() const {
00697   QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "NoDisplay" );
00698   if ( (it != m_mapProps.end()) && (it.data().isValid()))
00699   {
00700      QString aValue = it.data().toString().lower();
00701      if (aValue == "true" || aValue == "on" || aValue == "yes")
00702         return true;
00703   }
00704 
00705   it = m_mapProps.find( "OnlyShowIn" );
00706   if ( (it != m_mapProps.end()) && (it.data().isValid()))
00707   {
00708      QString aValue = it.data().toString();
00709      QStringList aList = QStringList::split(';', aValue);
00710      if (!aList.contains("KDE"))
00711         return true;
00712   }
00713 
00714   it = m_mapProps.find( "NotShowIn" );
00715   if ( (it != m_mapProps.end()) && (it.data().isValid()))
00716   {
00717      QString aValue = it.data().toString();
00718      QStringList aList = QStringList::split(';', aValue);
00719      if (aList.contains("KDE"))
00720         return true;
00721   }
00722   
00723   if (!kapp->authorizeControlModule(d->menuId))
00724      return true;
00725   
00726   return false;
00727 }
00728 
00729 QString KService::untranslatedGenericName() const {
00730   QVariant v = property("UntranslatedGenericName", QVariant::String);
00731   return v.isValid() ? v.toString() : QString::null;
00732 }
00733 
00734 QString KService::parentApp() const {
00735   QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "X-KDE-ParentApp" );
00736   if ( (it == m_mapProps.end()) || (!it.data().isValid()))
00737   {
00738      return QString::null;
00739   }
00740 
00741   return it.data().toString();
00742 }
00743 
00744 bool KService::allowMultipleFiles() const {
00745   // Can we pass multiple files on the command line or do we have to start the application for every single file ?
00746   if ( m_strExec.find( "%F" ) != -1 || m_strExec.find( "%U" ) != -1 ||
00747        m_strExec.find( "%N" ) != -1 || m_strExec.find( "%D" ) != -1 )
00748     return true;
00749   else
00750     return false;
00751 }
00752 
00753 QStringList KService::categories() const
00754 {
00755   return d->categories;
00756 }
00757 
00758 QString KService::menuId() const
00759 {
00760   return d->menuId;
00761 }
00762 
00763 void KService::setMenuId(const QString &menuId)
00764 {
00765   d->menuId = menuId;
00766 }
00767 
00768 QString KService::storageId() const
00769 {
00770   if (!d->menuId.isEmpty())
00771      return d->menuId;
00772   return entryPath();
00773 }
00774 
00775 QString KService::locateLocal()
00776 {
00777   if (d->menuId.isEmpty() || desktopEntryPath().startsWith(".hidden") ||
00778       (QDir::isRelativePath(desktopEntryPath()) && d->categories.isEmpty()))
00779      return KDesktopFile::locateLocal(desktopEntryPath());
00780 
00781   return ::locateLocal("xdgdata-apps", d->menuId);
00782 }
00783 
00784 QString KService::newServicePath(bool showInMenu, const QString &suggestedName,
00785                                 QString *menuId, const QStringList *reservedMenuIds)
00786 {
00787    QString base = suggestedName;
00788    if (!showInMenu)
00789      base.prepend("kde-");
00790 
00791    QString result;
00792    for(int i = 1; true; i++)
00793    {
00794       if (i == 1)
00795          result = base + ".desktop";
00796       else
00797          result = base + QString("-%1.desktop").arg(i);
00798 
00799       if (reservedMenuIds && reservedMenuIds->contains(result))
00800          continue;
00801 
00802       // Lookup service by menu-id
00803       KService::Ptr s = serviceByMenuId(result);
00804       if (s)
00805          continue;
00806 
00807       if (showInMenu)
00808       {
00809          if (!locate("xdgdata-apps", result).isEmpty())
00810             continue;
00811       }
00812       else
00813       {
00814          QString file = result.mid(4); // Strip "kde-"
00815          if (!locate("apps", ".hidden/"+file).isEmpty())
00816             continue;
00817       }
00818 
00819       break;
00820    }
00821    if (menuId)
00822       *menuId = result;
00823 
00824    if (showInMenu)
00825    {
00826        return ::locateLocal("xdgdata-apps", result);
00827    }
00828    else
00829    {
00830        QString file = result.mid(4); // Strip "kde-"
00831        return ::locateLocal("apps", ".hidden/"+file);
00832    }
00833 }
00834 
00835 
00836 void KService::virtual_hook( int id, void* data )
00837 { KSycocaEntry::virtual_hook( id, data ); }
00838 
00839 
00840 void KService::rebuildKSycoca(QWidget *parent)
00841 {
00842   KServiceProgressDialog dlg(parent, "ksycoca_progress",
00843                       i18n("Updating System Configuration"),
00844                       i18n("Updating system configuration."));
00845 
00846   QByteArray data;
00847   DCOPClient *client = kapp->dcopClient();
00848 
00849   int result = client->callAsync("kded", "kbuildsycoca", "recreate()",
00850                data, &dlg, SLOT(slotFinished()));
00851 
00852   if (result)
00853   {
00854      dlg.exec();
00855   }
00856 }
00857 
00858 KServiceProgressDialog::KServiceProgressDialog(QWidget *parent, const char *name,
00859                           const QString &caption, const QString &text)
00860  : KProgressDialog(parent, name, caption, text, true)
00861 {
00862   connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotProgress()));
00863   progressBar()->setTotalSteps(20);
00864   m_timeStep = 700;
00865   m_timer.start(m_timeStep);
00866   setAutoClose(false);
00867 }
00868 
00869 void
00870 KServiceProgressDialog::slotProgress()
00871 {
00872   int p = progressBar()->progress();
00873   if (p == 18)
00874   {
00875      progressBar()->reset();
00876      progressBar()->setProgress(1);
00877      m_timeStep = m_timeStep * 2;
00878      m_timer.start(m_timeStep);
00879   }
00880   else
00881   {
00882      progressBar()->setProgress(p+1);
00883   }
00884 }
00885 
00886 void
00887 KServiceProgressDialog::slotFinished()
00888 {
00889   progressBar()->setProgress(20);
00890   m_timer.stop();
00891   QTimer::singleShot(1000, this, SLOT(close()));
00892 }
00893 
00894 #include "kservice_p.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 28 01:36:58 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003