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