25 #include "kservice_p.h"
27 #include <sys/types.h>
39 #include <ksimpleconfig.h>
40 #include <kapplication.h>
42 #include <kdesktopfile.h>
44 #include <kiconloader.h>
46 #include <kconfigbase.h>
47 #include <kstandarddirs.h>
48 #include <dcopclient.h>
50 #include "kservicefactory.h"
51 #include "kservicetypefactory.h"
52 #include "kservicetype.h"
53 #include "kuserprofile.h"
56 class KService::KServicePrivate
64 : KSycocaEntry( TQString::null)
66 d =
new KServicePrivate;
69 m_strType =
"Application";
74 m_bAllowAsDefault =
true;
75 m_initialPreference = 10;
80 : KSycocaEntry( _fullpath)
82 KDesktopFile config( _fullpath );
88 : KSycocaEntry( config->fileName())
96 d =
new KServicePrivate;
99 bool absPath = !TQDir::isRelativePath(entryPath());
100 bool kde4application = config->fileName().contains(
"/share/applications/kde4/");
101 TQString kde4applicationprefix;
102 if (kde4application) {
104 kde4applicationprefix = config->fileName();
105 int pos = kde4applicationprefix.find(
"/share/applications/kde4/");
106 kde4applicationprefix.truncate(pos-1);
109 config->setDesktopGroup();
111 TQMap<TQString, TQString> entryMap = config->entryMap(config->group());
113 entryMap.remove(
"Encoding");
114 entryMap.remove(
"Version");
116 m_bDeleted = config->readBoolEntry(
"Hidden",
false );
117 entryMap.remove(
"Hidden");
125 m_strName = config->readName();
126 entryMap.remove(
"Name");
127 if ( m_strName.isEmpty() )
129 if (config->readEntry(
"Exec" ).isEmpty())
137 m_strName = entryPath();
138 int i = m_strName.findRev(
'/');
139 m_strName = m_strName.mid(i+1);
140 i = m_strName.findRev(
'.');
142 m_strName = m_strName.left(i);
145 m_strType = config->readType();
146 entryMap.remove(
"Type");
147 if ( m_strType.isEmpty() )
154 m_strType =
"Application";
155 }
else if ( m_strType !=
"Application" && m_strType !=
"Service" )
157 kdWarning(7012) <<
"The desktop entry file " << entryPath()
158 <<
" has Type=" << m_strType
159 <<
" instead of \"Application\" or \"Service\"" << endl;
165 if (!config->tryExec()) {
172 TQString resource = config->resource();
174 if ( (m_strType ==
"Application") &&
175 (!resource.isEmpty()) &&
176 (resource !=
"apps") &&
179 kdWarning(7012) <<
"The desktop entry file " << entryPath()
180 <<
" has Type=" << m_strType <<
" but is located under \"" << resource
181 <<
"\" instead of \"apps\"" << endl;
186 if ( (m_strType ==
"Service") &&
187 (!resource.isEmpty()) &&
188 (resource !=
"services") &&
191 kdWarning(7012) <<
"The desktop entry file " << entryPath()
192 <<
" has Type=" << m_strType <<
" but is located under \"" << resource
193 <<
"\" instead of \"services\"" << endl;
198 TQString
name = entryPath();
199 int pos = name.findRev(
'/');
201 name = name.mid(pos+1);
202 pos = name.find(
'.');
204 name = name.left(pos);
206 m_strExec = config->readPathEntry(
"Exec" );
207 if (kde4application && !m_strExec.startsWith(
"/")) {
208 m_strExec =
"KDEHOME=$HOME/" KDE4_DEFAULT_HOME
" KDEDIRS=" + kde4applicationprefix +
"/ XDG_DATA_DIRS=" + kde4applicationprefix +
"/share XDG_CONFIG_DIRS=/etc/xdg/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:$PATH "+m_strExec;
209 }
else if (config->readBoolEntry(
"X-KDE-SubstituteUID")) {
210 int space = m_strExec.find(
" ");
212 m_strExec = KStandardDirs::findExe(m_strExec);
214 const TQString command = m_strExec.left(space);
215 m_strExec.replace(command,KStandardDirs::findExe(command));
219 entryMap.remove(
"Exec");
221 m_strIcon = config->readEntry(
"Icon",
"unknown" );
222 if (kde4application) {
223 if (TQFile::exists(kde4applicationprefix +
"/share/icons/oxygen/22x22/apps/" + m_strIcon +
".png")) {
224 m_strIcon = kde4applicationprefix +
"/share/icons/oxygen/22x22/apps/" + m_strIcon +
".png";
225 }
else if (TQFile::exists(kde4applicationprefix +
"/share/icons/hicolor/22x22/apps/" + m_strIcon +
".png")) {
226 m_strIcon = kde4applicationprefix +
"/share/icons/hicolor/22x22/apps/" + m_strIcon +
".png";
229 entryMap.remove(
"Icon");
230 m_bTerminal = (config->readBoolEntry(
"Terminal" ));
231 entryMap.remove(
"Terminal");
232 m_strTerminalOptions = config->readEntry(
"TerminalOptions" );
233 entryMap.remove(
"TerminalOptions");
234 m_strPath = config->readPath();
235 entryMap.remove(
"Path");
236 m_strComment = config->readComment();
237 entryMap.remove(
"Comment");
238 m_strGenName = config->readGenericName();
239 if (kde4application) {
240 m_strGenName +=
" [KDE4]";
242 entryMap.remove(
"GenericName");
244 if (!untranslatedGenericName.isEmpty())
245 entryMap.insert(
"UntranslatedGenericName", untranslatedGenericName);
247 m_lstKeywords = config->readListEntry(
"Keywords");
248 entryMap.remove(
"Keywords");
249 d->categories = config->readListEntry(
"Categories",
';');
250 entryMap.remove(
"Categories");
251 m_strLibrary = config->readEntry(
"X-KDE-Library" );
252 entryMap.remove(
"X-KDE-Library");
253 m_strInit = config->readEntry(
"X-KDE-Init" );
254 entryMap.remove(
"X-KDE-Init");
256 m_lstServiceTypes = config->readListEntry(
"ServiceTypes" );
257 entryMap.remove(
"ServiceTypes");
259 if (!kde4application)
260 m_lstServiceTypes += config->readListEntry(
"MimeType",
';' );
261 entryMap.remove(
"MimeType");
263 if ( m_strType ==
"Application" && !m_lstServiceTypes.contains(
"Application") )
265 m_lstServiceTypes +=
"Application";
267 TQString dcopServiceType = config->readEntry(
"X-DCOP-ServiceType").lower();
268 entryMap.remove(
"X-DCOP-ServiceType");
269 if (dcopServiceType ==
"unique")
270 m_DCOPServiceType = DCOP_Unique;
271 else if (dcopServiceType ==
"multi")
272 m_DCOPServiceType = DCOP_Multi;
273 else if (dcopServiceType ==
"wait")
274 m_DCOPServiceType = DCOP_Wait;
276 m_DCOPServiceType = DCOP_None;
278 m_strDesktopEntryName = name.lower();
280 m_strDesktopEntryName =
"kde4-" + m_strDesktopEntryName;
282 m_bAllowAsDefault = config->readBoolEntry(
"AllowDefault",
true );
283 entryMap.remove(
"AllowDefault");
285 m_initialPreference = config->readNumEntry(
"X-KDE-InitialPreference", 1 );
286 entryMap.remove(
"X-KDE-InitialPreference");
287 if ( m_initialPreference == 1 )
288 m_initialPreference = config->readNumEntry(
"InitialPreference", 1 );
289 entryMap.remove(
"InitialPreference");
295 TQMap<TQString,TQString>::ConstIterator it = entryMap.begin();
296 for( ; it != entryMap.end();++it)
299 TQString key = it.key();
300 if (kde4application && key==
"OnlyShowIn" && it.data()==
"KDE;")
302 m_mapProps.insert( key, TQVariant( it.data()));
308 d =
new KServicePrivate;
312 KService::~KService()
318 TQPixmap
KService::pixmap( KIcon::Group _group,
int _force_size,
int _state, TQString * _path )
const
320 KIconLoader *iconLoader=KGlobal::iconLoader();
321 if (!iconLoader->extraDesktopThemesAdded())
323 TQPixmap
pixmap=iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path,
true );
324 if (!pixmap.isNull() )
return pixmap;
326 iconLoader->addExtraDesktopThemes();
329 return iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path );
332 void KService::load( TQDataStream& s )
337 TQ_INT8 def, term, dummy1, dummy2;
338 TQ_INT8 dst, initpref;
339 TQString dummyStr1, dummyStr2;
340 int dummyI1, dummyI2;
347 s >> m_strType >> m_strName >> m_strExec >> m_strIcon
348 >> term >> m_strTerminalOptions
349 >> m_strPath >> m_strComment >> m_lstServiceTypes >> def >> m_mapProps
350 >> m_strLibrary >> dummyI1 >> dummyI2
352 >> m_strDesktopEntryName
353 >> dummy1 >> dummyStr1 >> initpref >> dummyStr2 >> dummy2
354 >> m_lstKeywords >> m_strInit >> dummyUI32 >> m_strGenName
355 >> d->categories >> d->menuId;
357 m_bAllowAsDefault = def;
360 m_initialPreference = initpref;
365 void KService::save( TQDataStream& s )
367 KSycocaEntry::save( s );
368 TQ_INT8 def = m_bAllowAsDefault, initpref = m_initialPreference;
369 TQ_INT8 term = m_bTerminal;
370 TQ_INT8 dst = (TQ_INT8) m_DCOPServiceType;
371 TQ_INT8 dummy1 = 0, dummy2 = 0;
372 TQString dummyStr1, dummyStr2;
373 int dummyI1 = 0, dummyI2 = 0;
374 TQ_UINT32 dummyUI32 = 0;
380 s << m_strType << m_strName << m_strExec << m_strIcon
381 << term << m_strTerminalOptions
382 << m_strPath << m_strComment << m_lstServiceTypes << def << m_mapProps
383 << m_strLibrary << dummyI1 << dummyI2
385 << m_strDesktopEntryName
386 << dummy1 << dummyStr1 << initpref << dummyStr2 << dummy2
387 << m_lstKeywords << m_strInit << dummyUI32 << m_strGenName
388 << d->categories << d->menuId;
393 if (!m_bValid)
return false;
404 TQStringList::ConstIterator it = m_lstServiceTypes.begin();
405 for( ; it != m_lstServiceTypes.end(); ++it )
407 (*it).toInt(&isNumber);
412 if ( ptr && ptr->inherits( _servicetype ) )
418 if ( mimePtr && mimePtr->is( *it ) )
426 if (!m_bValid)
return 0;
431 TQStringList::ConstIterator it = m_lstServiceTypes.begin();
432 for( ; it != m_lstServiceTypes.end(); ++it )
434 (*it).toInt(&isNumber);
439 if ( !ptr || !ptr->inherits( mimeType ) )
442 int initalPreference = m_initialPreference;
444 if (it != m_lstServiceTypes.end())
446 int i = (*it).toInt(&isNumber);
448 initalPreference = i;
450 return initalPreference;
458 it = m_lstServiceTypes.begin();
459 for( ; it != m_lstServiceTypes.end(); ++it )
461 (*it).toInt(&isNumber);
468 if ( !mimePtr || !mimePtr->is( *it ) )
471 int initalPreference = m_initialPreference;
473 if (it != m_lstServiceTypes.end())
475 int i = (*it).toInt(&isNumber);
477 initalPreference = i;
479 return initalPreference;
484 class KServiceReadProperty :
public KConfigBase
487 KServiceReadProperty(
const TQString &_key,
const TQCString &_value)
488 : key(_key), value(_value) { }
490 bool internalHasGroup(
const TQCString &)
const {
return false; }
492 TQStringList groupList()
const {
return TQStringList(); }
494 TQMap<TQString,TQString> entryMap(
const TQString &group)
const
495 { Q_UNUSED(group);
return TQMap<TQString,TQString>(); }
497 void reparseConfiguration() { }
499 KEntryMap internalEntryMap(
const TQString &pGroup)
const
500 { Q_UNUSED(pGroup);
return KEntryMap(); }
502 KEntryMap internalEntryMap()
const {
return KEntryMap(); }
504 void putData(
const KEntryKey &_key,
const KEntry& _data,
bool _checkGroup)
505 { Q_UNUSED(_key); Q_UNUSED(_data); Q_UNUSED(_checkGroup); }
507 KEntry lookupData(
const KEntryKey &_key)
const
508 { Q_UNUSED(_key); KEntry entry; entry.mValue = value;
return entry; }
516 return property( _name, TQVariant::Invalid);
522 static TQVariant makeStringVariant(
const TQString&
string )
526 return string.isNull() ? TQVariant() : TQVariant( string );
531 if ( _name ==
"Type" )
532 return TQVariant( m_strType );
533 else if ( _name ==
"Name" )
534 return TQVariant( m_strName );
535 else if ( _name ==
"Exec" )
536 return makeStringVariant( m_strExec );
537 else if ( _name ==
"Icon" )
538 return makeStringVariant( m_strIcon );
539 else if ( _name ==
"Terminal" )
540 return TQVariant( static_cast<int>(m_bTerminal) );
541 else if ( _name ==
"TerminalOptions" )
542 return makeStringVariant( m_strTerminalOptions );
543 else if ( _name ==
"Path" )
544 return makeStringVariant( m_strPath );
545 else if ( _name ==
"Comment" )
546 return makeStringVariant( m_strComment );
547 else if ( _name ==
"GenericName" )
548 return makeStringVariant( m_strGenName );
549 else if ( _name ==
"ServiceTypes" )
550 return TQVariant( m_lstServiceTypes );
551 else if ( _name ==
"AllowAsDefault" )
552 return TQVariant( static_cast<int>(m_bAllowAsDefault) );
553 else if ( _name ==
"InitialPreference" )
554 return TQVariant( m_initialPreference );
555 else if ( _name ==
"Library" )
556 return makeStringVariant( m_strLibrary );
557 else if ( _name ==
"DesktopEntryPath" )
558 return TQVariant( entryPath() );
559 else if ( _name ==
"DesktopEntryName")
560 return TQVariant( m_strDesktopEntryName );
561 else if ( _name ==
"Categories")
562 return TQVariant( d->categories );
563 else if ( _name ==
"Keywords")
564 return TQVariant( m_lstKeywords );
568 if (t == TQVariant::Invalid)
572 t = KServiceTypeFactory::self()->findPropertyTypeByName(_name);
573 if (t == TQVariant::Invalid)
575 kdDebug(7012) <<
"Request for unknown property '" << _name <<
"'\n";
582 TQMap<TQString,TQVariant>::ConstIterator it = m_mapProps.find( _name );
583 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
591 case TQVariant::String:
593 case TQVariant::Bool:
596 TQString aValue = it.data().toString();
598 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
603 val = aValue.toInt( &bOK );
607 if (t == TQVariant::Bool)
609 return TQVariant((
bool)val, 1);
611 return TQVariant(val);
615 KServiceReadProperty ksrp(_name, it.data().toString().utf8());
616 return ksrp.readPropertyEntry(_name, t);
624 TQMap<TQString,TQVariant>::ConstIterator it = m_mapProps.begin();
625 for( ; it != m_mapProps.end(); ++it )
626 res.append( it.key() );
628 res.append(
"Type" );
629 res.append(
"Name" );
630 res.append(
"Comment" );
631 res.append(
"GenericName" );
632 res.append(
"Icon" );
633 res.append(
"Exec" );
634 res.append(
"Terminal" );
635 res.append(
"TerminalOptions" );
636 res.append(
"Path" );
637 res.append(
"ServiceTypes" );
638 res.append(
"AllowAsDefault" );
639 res.append(
"InitialPreference" );
640 res.append(
"Library" );
641 res.append(
"DesktopEntryPath" );
642 res.append(
"DesktopEntryName" );
643 res.append(
"Keywords" );
644 res.append(
"Categories" );
651 return KServiceFactory::self()->allServices();
656 KService * s = KServiceFactory::self()->findServiceByName( _name );
657 return KService::Ptr( s );
662 KService * s = KServiceFactory::self()->findServiceByDesktopPath( _name );
663 return KService::Ptr( s );
668 KService * s = KServiceFactory::self()->findServiceByDesktopName( _name.lower() );
669 if (!s && !_name.startsWith(
"kde-"))
670 s = KServiceFactory::self()->findServiceByDesktopName(
"kde-"+_name.lower() );
671 return KService::Ptr( s );
676 KService * s = KServiceFactory::self()->findServiceByMenuId( _name );
677 return KService::Ptr( s );
690 if (!TQDir::isRelativePath(_storageId) && TQFile::exists(_storageId))
693 TQString tmp = _storageId;
694 tmp = tmp.mid(tmp.findRev(
'/')+1);
696 if (tmp.endsWith(
".desktop"))
697 tmp.truncate(tmp.length()-8);
699 if (tmp.endsWith(
".kdelnk"))
700 tmp.truncate(tmp.length()-7);
709 return KServiceFactory::self()->allInitServices();
713 TQVariant v =
property(
"X-KDE-SubstituteUID", TQVariant::Bool);
714 return v.isValid() && v.toBool();
720 TQVariant v =
property(
"X-KDE-Username", TQVariant::String);
721 user = v.isValid() ? v.toString() : TQString::null;
723 user = ::getenv(
"ADMIN_ACCOUNT");
730 TQMap<TQString,TQVariant>::ConstIterator it = m_mapProps.find(
"NoDisplay" );
731 if ( (it != m_mapProps.end()) && (it.data().isValid()))
733 TQString aValue = it.data().toString().lower();
734 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
738 it = m_mapProps.find(
"OnlyShowIn" );
739 if ( (it != m_mapProps.end()) && (it.data().isValid()))
741 TQString aValue = it.data().toString();
742 TQStringList aList = TQStringList::split(
';', aValue);
743 if ((!aList.contains(
"TDE")) && (!aList.contains(
"KDE")))
747 it = m_mapProps.find(
"NotShowIn" );
748 if ( (it != m_mapProps.end()) && (it.data().isValid()))
750 TQString aValue = it.data().toString();
751 TQStringList aList = TQStringList::split(
';', aValue);
752 if ((aList.contains(
"TDE")) || (aList.contains(
"KDE")))
756 if (!kapp->authorizeControlModule(d->menuId))
763 TQVariant v =
property(
"UntranslatedGenericName", TQVariant::String);
764 return v.isValid() ? v.toString() : TQString::null;
768 TQMap<TQString,TQVariant>::ConstIterator it = m_mapProps.find(
"X-SuSE-Unimportant" );
769 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
774 TQString aValue = it.data().toString();
775 if (aValue ==
"true" || aValue ==
"on" || aValue ==
"yes")
782 TQMap<TQString,TQVariant>::ConstIterator it = m_mapProps.find(
"X-KDE-ParentApp" );
783 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
785 return TQString::null;
788 return it.data().toString();
793 if ( m_strExec.find(
"%F" ) != -1 || m_strExec.find(
"%U" ) != -1 ||
794 m_strExec.find(
"%N" ) != -1 || m_strExec.find(
"%D" ) != -1 )
802 return d->categories;
810 void KService::setMenuId(
const TQString &menuId)
817 if (!d->menuId.isEmpty())
828 return ::locateLocal(
"xdgdata-apps", d->menuId);
832 TQString *menuId,
const TQStringList *reservedMenuIds)
834 TQString base = suggestedName;
836 base.prepend(
"kde-");
839 for(
int i = 1;
true; i++)
842 result = base +
".desktop";
844 result = base + TQString(
"-%1.desktop").arg(i);
846 if (reservedMenuIds && reservedMenuIds->contains(result))
856 if (!locate(
"xdgdata-apps", result).isEmpty())
861 TQString file = result.mid(4);
862 if (!locate(
"apps",
".hidden/"+file).isEmpty())
873 return ::locateLocal(
"xdgdata-apps", result);
877 TQString file = result.mid(4);
878 return ::locateLocal(
"apps",
".hidden/"+file);
883 void KService::virtual_hook(
int id,
void* data )
884 { KSycocaEntry::virtual_hook(
id, data ); }
889 KServiceProgressDialog dlg(parent,
"ksycoca_progress",
890 i18n(
"Updating System Configuration"),
891 i18n(
"Updating system configuration."));
894 DCOPClient *client = kapp->dcopClient();
896 int result = client->callAsync(
"kded",
"kbuildsycoca",
"recreate()",
897 data, TQT_TQOBJECT(&dlg), TQT_SLOT(slotFinished()));
905 KServiceProgressDialog::KServiceProgressDialog(TQWidget *parent,
const char *name,
906 const TQString &caption,
const TQString &text)
907 : KProgressDialog(parent, name, caption, text, true)
909 connect(&m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotProgress()));
910 progressBar()->setTotalSteps(20);
912 m_timer.start(m_timeStep);
917 KServiceProgressDialog::slotProgress()
919 int p = progressBar()->progress();
922 progressBar()->reset();
923 progressBar()->setProgress(1);
924 m_timeStep = m_timeStep * 2;
925 m_timer.start(m_timeStep);
929 progressBar()->setProgress(p+1);
934 KServiceProgressDialog::slotFinished()
936 progressBar()->setProgress(20);
938 TQTimer::singleShot(1000,
this, TQT_SLOT(close()));
941 #include "kservice_p.moc"