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