• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kded
 

kded

  • kded
tdebuildsycoca.cpp
1/* This file is part of the KDE libraries
2 * Copyright (C) 1999 David Faure <faure@kde.org>
3 * Copyright (C) 2002-2003 Waldo Bastian <bastian@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License version 2 as published by the Free Software Foundation;
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 **/
19
20#include <tqdir.h>
21#include <tqeventloop.h>
22#include <config.h>
23
24#include "tdebuildsycoca.h"
25#include "kresourcelist.h"
26#include "vfolder_menu.h"
27
28#include <kservice.h>
29#include <kmimetype.h>
30#include <kbuildservicetypefactory.h>
31#include <kbuildservicefactory.h>
32#include <kbuildservicegroupfactory.h>
33#include <kbuildimageiofactory.h>
34#include <kbuildprotocolinfofactory.h>
35#include <kctimefactory.h>
36#include <kdatastream.h>
37
38#include <tqdatastream.h>
39#include <tqfile.h>
40#include <tqtimer.h>
41
42#include <assert.h>
43#include <tdeapplication.h>
44#include <dcopclient.h>
45#include <tdeglobal.h>
46#include <kdebug.h>
47#include <kdirwatch.h>
48#include <tdestandarddirs.h>
49#include <ksavefile.h>
50#include <tdelocale.h>
51#include <tdeaboutdata.h>
52#include <tdecmdlineargs.h>
53#include <tdecrash.h>
54
55#ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
56 // GUI version of tdebuildsycoca, so-called "tdebuildsycocaw".
57# include <tqlabel.h>
58# include <tdemessagebox.h>
59 bool silent;
60 bool showprogress;
61#endif
62
63#include <stdlib.h>
64#include <unistd.h>
65#include <time.h>
66#include <memory>
67
68typedef TQDict<KSycocaEntry> KBSEntryDict;
69typedef TQValueList<KSycocaEntry::List> KSycocaEntryListList;
70
71static TQ_UINT32 newTimestamp = 0;
72
73static KBuildServiceFactory *g_bsf = 0;
74static KBuildServiceGroupFactory *g_bsgf = 0;
75static KSycocaFactory *g_factory = 0;
76static KCTimeInfo *g_ctimeInfo = 0;
77static TQDict<TQ_UINT32> *g_ctimeDict = 0;
78static const char *g_resource = 0;
79static KBSEntryDict *g_entryDict = 0;
80static KBSEntryDict *g_serviceGroupEntryDict = 0;
81static KSycocaEntryListList *g_allEntries = 0;
82static TQStringList *g_changeList = 0;
83static TQStringList *g_allResourceDirs = 0;
84static bool g_changed = false;
85static KSycocaEntry::List g_tempStorage;
86static VFolderMenu *g_vfolder = 0;
87
88static const char *cSycocaPath = 0;
89
90static bool bGlobalDatabase = false;
91static bool bMenuTest = false;
92
93void crashHandler(int)
94{
95 // If we crash while reading sycoca, we delete the database
96 // in an attempt to recover.
97 if (cSycocaPath)
98 unlink(cSycocaPath);
99}
100
101static TQString sycocaPath()
102{
103 TQString path;
104
105 if (bGlobalDatabase)
106 {
107 path = TDEGlobal::dirs()->saveLocation("services")+"tdesycoca";
108 }
109 else
110 {
111 TQCString tdesycoca_env = getenv("TDESYCOCA");
112 if (tdesycoca_env.isEmpty())
113 path = TDEGlobal::dirs()->saveLocation("cache")+"tdesycoca";
114 else
115 path = TQFile::decodeName(tdesycoca_env);
116 }
117
118 return path;
119}
120
121static TQString oldSycocaPath()
122{
123 TQCString tdesycoca_env = getenv("TDESYCOCA");
124 if (tdesycoca_env.isEmpty())
125 return TDEGlobal::dirs()->saveLocation("tmp")+"tdesycoca";
126
127 return TQString::null;
128}
129
130KBuildSycoca::KBuildSycoca()
131 : KSycoca( true )
132{
133}
134
135KBuildSycoca::~KBuildSycoca()
136{
137
138}
139
140void KBuildSycoca::processGnomeVfs()
141{
142 TQString file = locate("app-reg", "gnome-vfs.applications");
143 if (file.isEmpty())
144 {
145// kdDebug(7021) << "gnome-vfs.applications not found." << endl;
146 return;
147 }
148
149 TQString app;
150
151 char line[1024*64];
152
153 FILE *f = fopen(TQFile::encodeName(file), "r");
154 while (!feof(f))
155 {
156 if (!fgets(line, sizeof(line)-1, f))
157 {
158 break;
159 }
160
161 if (line[0] != '\t')
162 {
163 app = TQString::fromLatin1(line);
164 app.truncate(app.length()-1);
165 }
166 else if (strncmp(line+1, "mime_types=", 11) == 0)
167 {
168 TQString mimetypes = TQString::fromLatin1(line+12);
169 mimetypes.truncate(mimetypes.length()-1);
170 mimetypes.replace(TQRegExp("\\*"), "all");
171 KService *s = g_bsf->findServiceByName(app);
172 if (!s)
173 continue;
174
175 TQStringList &serviceTypes = s->accessServiceTypes();
176 if (serviceTypes.count() <= 1)
177 {
178 serviceTypes += TQStringList::split(',', mimetypes);
179// kdDebug(7021) << "Adding gnome mimetypes for '" << app << "'.\n";
180// kdDebug(7021) << "ServiceTypes=" << s->serviceTypes().join(":") << endl;
181 }
182 }
183 }
184 fclose( f );
185}
186
187KSycocaEntry *KBuildSycoca::createEntry(const TQString &file, bool addToFactory)
188{
189 TQ_UINT32 timeStamp = g_ctimeInfo->ctime(file);
190 if (!timeStamp)
191 {
192 timeStamp = TDEGlobal::dirs()->calcResourceHash( g_resource, file, true);
193 }
194 KSycocaEntry* entry = 0;
195 if (g_allEntries)
196 {
197 assert(g_ctimeDict);
198 TQ_UINT32 *timeP = (*g_ctimeDict)[file];
199 TQ_UINT32 oldTimestamp = timeP ? *timeP : 0;
200
201 if (timeStamp && (timeStamp == oldTimestamp))
202 {
203 // Re-use old entry
204 if (g_factory == g_bsgf) // Strip .directory from service-group entries
205 {
206 entry = g_entryDict->find(file.left(file.length()-10));
207 }
208 else if (g_factory == g_bsf)
209 {
210 entry = g_entryDict->find(file);
211 }
212 else
213 {
214 entry = g_entryDict->find(file);
215 }
216 // remove from g_ctimeDict; if g_ctimeDict is not empty
217 // after all files have been processed, it means
218 // some files were removed since last time
219 g_ctimeDict->remove( file );
220 }
221 else if (oldTimestamp)
222 {
223 g_changed = true;
224 kdDebug(7021) << "modified: " << file << endl;
225 }
226 else
227 {
228 g_changed = true;
229 kdDebug(7021) << "new: " << file << endl;
230 }
231 }
232 g_ctimeInfo->addCTime(file, timeStamp );
233 if (!entry)
234 {
235 // Create a new entry
236 entry = g_factory->createEntry( file, g_resource );
237 }
238 if ( entry && entry->isValid() )
239 {
240 if (addToFactory)
241 g_factory->addEntry( entry, g_resource );
242 else
243 g_tempStorage.append(entry);
244 return entry;
245 }
246 return 0;
247}
248
249void KBuildSycoca::slotCreateEntry(const TQString &file, KService **service)
250{
251 KSycocaEntry *entry = createEntry(file, false);
252 *service = dynamic_cast<KService *>(entry);
253}
254
255// returns false if the database is up to date
256bool KBuildSycoca::build()
257{
258 typedef TQPtrList<KBSEntryDict> KBSEntryDictList;
259 KBSEntryDictList *entryDictList = 0;
260 KBSEntryDict *serviceEntryDict = 0;
261
262 entryDictList = new KBSEntryDictList();
263 // Convert for each factory the entryList to a Dict.
264 int i = 0;
265 // For each factory
266 for (KSycocaFactory *factory = m_lstFactories->first();
267 factory;
268 factory = m_lstFactories->next() )
269 {
270 KBSEntryDict *entryDict = new KBSEntryDict();
271 if (g_allEntries)
272 {
273 KSycocaEntry::List list = (*g_allEntries)[i++];
274 for( KSycocaEntry::List::Iterator it = list.begin();
275 it != list.end();
276 ++it)
277 {
278 entryDict->insert( (*it)->entryPath(), static_cast<KSycocaEntry *>(*it));
279 }
280 }
281 if (factory == g_bsf)
282 serviceEntryDict = entryDict;
283 else if (factory == g_bsgf)
284 g_serviceGroupEntryDict = entryDict;
285 entryDictList->append(entryDict);
286 }
287
288 TQStringList allResources;
289 // For each factory
290 for (KSycocaFactory *factory = m_lstFactories->first();
291 factory;
292 factory = m_lstFactories->next() )
293 {
294 // For each resource the factory deals with
295 const KSycocaResourceList *list = factory->resourceList();
296 if (!list) continue;
297
298 for( KSycocaResourceList::ConstIterator it1 = list->begin();
299 it1 != list->end();
300 ++it1 )
301 {
302 KSycocaResource res = (*it1);
303 if (!allResources.contains(res.resource))
304 allResources.append(res.resource);
305 }
306 }
307
308 g_ctimeInfo = new KCTimeInfo(); // This is a build factory too, don't delete!!
309 bool uptodate = true;
310 // For all resources
311 for( TQStringList::ConstIterator it1 = allResources.begin();
312 it1 != allResources.end();
313 ++it1 )
314 {
315 g_changed = false;
316 g_resource = (*it1).ascii();
317
318 TQStringList relFiles;
319
320 (void) TDEGlobal::dirs()->findAllResources( g_resource,
321 TQString::null,
322 true, // Recursive!
323 true, // uniq
324 relFiles);
325
326
327 // Now find all factories that use this resource....
328 // For each factory
329 g_entryDict = entryDictList->first();
330 for (g_factory = m_lstFactories->first();
331 g_factory;
332 g_factory = m_lstFactories->next(),
333 g_entryDict = entryDictList->next() )
334 {
335 // For each resource the factory deals with
336 const KSycocaResourceList *list = g_factory->resourceList();
337 if (!list) continue;
338
339 for( KSycocaResourceList::ConstIterator it2 = list->begin();
340 it2 != list->end();
341 ++it2 )
342 {
343 KSycocaResource res = (*it2);
344 if (res.resource != (*it1)) continue;
345
346 // For each file in the resource
347 for( TQStringList::ConstIterator it3 = relFiles.begin();
348 it3 != relFiles.end();
349 ++it3 )
350 {
351 // Check if file matches filter
352 if ((*it3).endsWith(res.extension))
353 createEntry(*it3, true);
354 }
355 }
356 if ((g_factory == g_bsf) && (strcmp(g_resource, "services") == 0))
357 processGnomeVfs();
358 }
359 if (g_changed || !g_allEntries)
360 {
361 uptodate = false;
362 g_changeList->append(g_resource);
363 }
364 }
365
366 bool result = !uptodate || !g_ctimeDict->isEmpty();
367
368 if (result || bMenuTest)
369 {
370 g_resource = "apps";
371 g_factory = g_bsf;
372 g_entryDict = serviceEntryDict;
373 g_changed = false;
374
375 g_vfolder = new VFolderMenu;
376 if (!m_trackId.isEmpty())
377 g_vfolder->setTrackId(m_trackId);
378
379 connect(g_vfolder, TQ_SIGNAL(newService(const TQString &, KService **)),
380 this, TQ_SLOT(slotCreateEntry(const TQString &, KService **)));
381
382 VFolderMenu::SubMenu *kdeMenu = g_vfolder->parseMenu("tde-applications.menu", true);
383
384 KServiceGroup *entry = g_bsgf->addNew("/", kdeMenu->directoryFile, 0, false);
385 entry->setLayoutInfo(kdeMenu->layoutList);
386 createMenu(TQString::null, TQString::null, kdeMenu);
387
388 KServiceGroup::Ptr g(entry);
389
390 (void) existingResourceDirs();
391 *g_allResourceDirs += g_vfolder->allDirectories();
392
393 disconnect(g_vfolder, TQ_SIGNAL(newService(const TQString &, KService **)),
394 this, TQ_SLOT(slotCreateEntry(const TQString &, KService **)));
395
396 if (g_changed || !g_allEntries)
397 {
398 uptodate = false;
399 g_changeList->append(g_resource);
400 }
401 if (bMenuTest)
402 return false;
403 }
404
405 return result;
406}
407
408void KBuildSycoca::createMenu(TQString caption, TQString name, VFolderMenu::SubMenu *menu)
409{
410 for(VFolderMenu::SubMenu *subMenu = menu->subMenus.first(); subMenu; subMenu = menu->subMenus.next())
411 {
412 TQString subName = name+subMenu->name+"/";
413
414 TQString directoryFile = subMenu->directoryFile;
415 if (directoryFile.isEmpty())
416 directoryFile = subName+".directory";
417 TQ_UINT32 timeStamp = g_ctimeInfo->ctime(directoryFile);
418 if (!timeStamp)
419 {
420 timeStamp = TDEGlobal::dirs()->calcResourceHash( g_resource, directoryFile, true);
421 }
422
423 KServiceGroup* entry = 0;
424 if (g_allEntries)
425 {
426 TQ_UINT32 *timeP = (*g_ctimeDict)[directoryFile];
427 TQ_UINT32 oldTimestamp = timeP ? *timeP : 0;
428
429 if (timeStamp && (timeStamp == oldTimestamp))
430 {
431 entry = dynamic_cast<KServiceGroup *> (g_serviceGroupEntryDict->find(subName));
432 if (entry && (entry->directoryEntryPath() != directoryFile))
433 entry = 0; // Can't reuse this one!
434 }
435 }
436 g_ctimeInfo->addCTime(directoryFile, timeStamp);
437
438 entry = g_bsgf->addNew(subName, subMenu->directoryFile, entry, subMenu->isDeleted);
439 entry->setLayoutInfo(subMenu->layoutList);
440 if (! (bMenuTest && entry->noDisplay()) )
441 createMenu(caption + entry->caption() + "/", subName, subMenu);
442 }
443 if (caption.isEmpty())
444 caption += "/";
445 if (name.isEmpty())
446 name += "/";
447 for(TQDictIterator<KService> it(menu->items); it.current(); ++it)
448 {
449 if (bMenuTest)
450 {
451 if (!menu->isDeleted && !it.current()->noDisplay())
452 printf("%s\t%s\t%s\n", caption.local8Bit().data(), it.current()->menuId().local8Bit().data(), locate("apps", it.current()->desktopEntryPath()).local8Bit().data());
453 }
454 else
455 {
456 g_bsf->addEntry( it.current(), g_resource );
457 g_bsgf->addNewEntryTo(name, it.current());
458 }
459 }
460}
461
462bool KBuildSycoca::recreate()
463{
464 TQString path(sycocaPath());
465#ifdef TQ_WS_WIN
466 printf("tdebuildsycoca: path='%s'\n", (const char*)path);
467#endif
468
469 // KSaveFile first writes to a temp file.
470 // Upon close() it moves the stuff to the right place.
471 std::unique_ptr<KSaveFile> database( new KSaveFile(path) );
472 if (database->status() == EACCES && TQFile::exists(path))
473 {
474 TQFile::remove( path );
475 database.reset( new KSaveFile(path) ); // try again
476 }
477 if (database->status() != 0)
478 {
479 fprintf(stderr, "[tdebuildsycoca] ERROR creating database '%s'! %s\n", path.local8Bit().data(),strerror(database->status()));
480#ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
481 // GUI version of tdebuildsycoca, so-called "tdebuildsycocaw".
482 if (!silent)
483 KMessageBox::error(0, i18n("Error creating database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca"));
484#endif
485 return false;
486 }
487
488 m_str = database->dataStream();
489
490 kdDebug(7021) << "Recreating tdesycoca file (" << path << ", version " << KSycoca::version() << ")" << endl;
491
492 // It is very important to build the servicetype one first
493 // Both are registered in KSycoca, no need to keep the pointers
494 KSycocaFactory *stf = new KBuildServiceTypeFactory;
495 g_bsgf = new KBuildServiceGroupFactory();
496 g_bsf = new KBuildServiceFactory(stf, g_bsgf);
497 (void) new KBuildImageIOFactory();
498 (void) new KBuildProtocolInfoFactory();
499
500 if( build()) // Parse dirs
501 {
502 save(); // Save database
503 if (m_str->device()->status())
504 database->abort(); // Error
505 m_str = 0L;
506 if (!database->close())
507 {
508 fprintf(stderr, "[tdebuildsycoca] ERROR writing database '%s'!\n", database->name().local8Bit().data());
509 fprintf(stderr, "[tdebuildsycoca] Disk full?\n");
510#ifdef KBUILDSYCOCA_GUI
511 if (!silent)
512 KMessageBox::error(0, i18n("[tdebuildsycoca] Error writing database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca"));
513#endif
514 return false;
515 }
516 }
517 else
518 {
519 m_str = 0L;
520 database->abort();
521 if (bMenuTest)
522 return true;
523 kdDebug(7021) << "Database is up to date" << endl;
524 }
525
526 if (!bGlobalDatabase)
527 {
528 // update the timestamp file
529 TQString stamppath = path + "stamp";
530 TQFile tdesycocastamp(stamppath);
531 tdesycocastamp.open( IO_WriteOnly );
532 TQDataStream str( &tdesycocastamp );
533 str << newTimestamp;
534 str << existingResourceDirs();
535 if (g_vfolder)
536 str << g_vfolder->allDirectories(); // Extra resource dirs
537 }
538 return true;
539}
540
541void KBuildSycoca::save()
542{
543 // Write header (#pass 1)
544 m_str->device()->at(0);
545
546 (*m_str) << (TQ_INT32) KSycoca::version();
547 KSycocaFactory * servicetypeFactory = 0L;
548 KSycocaFactory * serviceFactory = 0L;
549 for(KSycocaFactory *factory = m_lstFactories->first();
550 factory;
551 factory = m_lstFactories->next())
552 {
553 TQ_INT32 aId;
554 TQ_INT32 aOffset;
555 aId = factory->factoryId();
556 if ( aId == KST_KServiceTypeFactory )
557 servicetypeFactory = factory;
558 else if ( aId == KST_KServiceFactory )
559 serviceFactory = factory;
560 aOffset = factory->offset();
561 (*m_str) << aId;
562 (*m_str) << aOffset;
563 }
564 (*m_str) << (TQ_INT32) 0; // No more factories.
565 // Write TDEDIRS
566 (*m_str) << TDEGlobal::dirs()->kfsstnd_prefixes();
567 (*m_str) << newTimestamp;
568 (*m_str) << TDEGlobal::locale()->language();
569 (*m_str) << TDEGlobal::dirs()->calcResourceHash("services", "update_tdesycoca", true);
570 (*m_str) << (*g_allResourceDirs);
571
572 // Write factory data....
573 for(KSycocaFactory *factory = m_lstFactories->first();
574 factory;
575 factory = m_lstFactories->next())
576 {
577 factory->save(*m_str);
578 if (m_str->device()->status())
579 return; // error
580 }
581
582 int endOfData = m_str->device()->at();
583
584 // Write header (#pass 2)
585 m_str->device()->at(0);
586
587 (*m_str) << (TQ_INT32) KSycoca::version();
588 for(KSycocaFactory *factory = m_lstFactories->first();
589 factory;
590 factory = m_lstFactories->next())
591 {
592 TQ_INT32 aId;
593 TQ_INT32 aOffset;
594 aId = factory->factoryId();
595 aOffset = factory->offset();
596 (*m_str) << aId;
597 (*m_str) << aOffset;
598 }
599 (*m_str) << (TQ_INT32) 0; // No more factories.
600
601 // Jump to end of database
602 m_str->device()->at(endOfData);
603}
604
605bool KBuildSycoca::checkDirTimestamps( const TQString& dirname, const TQDateTime& stamp, bool top )
606{
607 if( top )
608 {
609 TQFileInfo inf( dirname );
610 if( inf.lastModified() > stamp )
611 {
612 kdDebug( 7021 ) << "timestamp changed:" << dirname << endl;
613 return false;
614 }
615 }
616 TQDir dir( dirname );
617 const TQFileInfoList *list = dir.entryInfoList( TQDir::DefaultFilter, TQDir::Unsorted );
618 if (!list)
619 return true;
620
621 for( TQFileInfoListIterator it( *list );
622 it.current() != NULL;
623 ++it )
624 {
625 TQFileInfo* fi = it.current();
626 if( fi->fileName() == "." || fi->fileName() == ".." )
627 continue;
628 if( fi->lastModified() > stamp )
629 {
630 kdDebug( 7201 ) << "timestamp changed:" << fi->filePath() << endl;
631 return false;
632 }
633 if( fi->isDir() && !checkDirTimestamps( fi->filePath(), stamp, false ))
634 return false;
635 }
636 return true;
637}
638
639// check times of last modification of all files on which tdesycoca depens,
640// and also their directories
641// if all of them all older than the timestamp in file tdesycocastamp, this
642// means that there's no need to rebuild tdesycoca
643bool KBuildSycoca::checkTimestamps( TQ_UINT32 timestamp, const TQStringList &dirs )
644{
645 kdDebug( 7021 ) << "checking file timestamps" << endl;
646 TQDateTime stamp;
647 stamp.setTime_t( timestamp );
648 for( TQStringList::ConstIterator it = dirs.begin();
649 it != dirs.end();
650 ++it )
651 {
652 if( !checkDirTimestamps( *it, stamp, true ))
653 return false;
654 }
655 kdDebug( 7021 ) << "timestamps check ok" << endl;
656 return true;
657}
658
659TQStringList KBuildSycoca::existingResourceDirs()
660{
661 static TQStringList* dirs = NULL;
662 if( dirs != NULL )
663 return *dirs;
664 dirs = new TQStringList;
665 g_allResourceDirs = new TQStringList;
666 // these are all resources cached by tdesycoca
667 TQStringList resources;
668 resources += KBuildServiceTypeFactory::resourceTypes();
669 resources += KBuildServiceGroupFactory::resourceTypes();
670 resources += KBuildServiceFactory::resourceTypes();
671 resources += KBuildImageIOFactory::resourceTypes();
672 resources += KBuildProtocolInfoFactory::resourceTypes();
673 while( !resources.empty())
674 {
675 TQString res = resources.front();
676 *dirs += TDEGlobal::dirs()->resourceDirs( res.latin1());
677 resources.remove( res ); // remove this 'res' and all its duplicates
678 }
679
680 *g_allResourceDirs = *dirs;
681
682 for( TQStringList::Iterator it = dirs->begin();
683 it != dirs->end(); )
684 {
685 TQFileInfo inf( *it );
686 if( !inf.exists() || !inf.isReadable() )
687 it = dirs->remove( it );
688 else
689 ++it;
690 }
691 return *dirs;
692}
693
694static TDECmdLineOptions options[] = {
695 { "nosignal", I18N_NOOP("Do not signal applications to update"), 0 },
696 { "noincremental", I18N_NOOP("Disable incremental update, re-read everything"), 0 },
697 { "checkstamps", I18N_NOOP("Check file timestamps"), 0 },
698 { "nocheckfiles", I18N_NOOP("Disable checking files (dangerous)"), 0 },
699 { "global", I18N_NOOP("Create global database"), 0 },
700 { "menutest", I18N_NOOP("Perform menu generation test run only"), 0 },
701 { "track <menu-id>", I18N_NOOP("Track menu id for debug purposes"), 0 },
702#ifdef KBUILDSYCOCA_GUI
703 { "silent", I18N_NOOP("Silent - work without windows and stderr"), 0 },
704 { "showprogress", I18N_NOOP("Show progress information (even if 'silent' mode is on)"), 0 },
705#endif
706 TDECmdLineLastOption
707};
708
709static const char appName[] = "tdebuildsycoca";
710static const char appVersion[] = "1.1";
711
712class WaitForSignal : public TQObject
713{
714public:
715 ~WaitForSignal() { tdeApp->eventLoop()->exitLoop(); }
716};
717
718extern "C" TDE_EXPORT int kdemain(int argc, char **argv)
719{
720 TDELocale::setMainCatalogue("tdelibs");
721 TDEAboutData d(appName, I18N_NOOP("KBuildSycoca"), appVersion,
722 I18N_NOOP("Rebuilds the system configuration cache."),
723 TDEAboutData::License_GPL, "(c) 1999-2002 KDE Developers");
724 d.addAuthor("David Faure", I18N_NOOP("Author"), "faure@kde.org");
725 d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org");
726
727 TDECmdLineArgs::init(argc, argv, &d);
728 TDECmdLineArgs::addCmdLineOptions(options);
729 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
730 bGlobalDatabase = args->isSet("global");
731 bMenuTest = args->isSet("menutest");
732
733 if (bGlobalDatabase)
734 {
735 setenv("TDEHOME", "-", 1);
736 setenv("TDEROOTHOME", "-", 1);
737 }
738
739 TDEApplication::disableAutoDcopRegistration();
740#ifdef KBUILDSYCOCA_GUI
741 TDEApplication k;
742#else
743 TDEApplication k(false, false);
744#endif
745 k.disableSessionManagement();
746
747#ifdef KBUILDSYCOCA_GUI
748 silent = args->isSet("silent");
749 showprogress = args->isSet("showprogress");
750 TQLabel progress( TQString("<p><br><nobr> %1 </nobr><br>").arg( i18n("Reloading TDE configuration, please wait...") ), 0, "", TQt::WType_Dialog | TQt::WStyle_DialogBorder | TQt::WStyle_Customize| TQt::WStyle_Title );
751 TQString capt = i18n("TDE Configuration Manager");
752 if (!silent) {
753 if (KMessageBox::No == KMessageBox::questionYesNo(0, i18n("Do you want to reload TDE configuration?"), capt, i18n("Reload"), i18n("Do Not Reload")))
754 return 0;
755 }
756 if (!silent || showprogress) {
757 progress.setCaption( capt );
758 progress.show();
759 }
760#endif
761
762 TDECrash::setCrashHandler(TDECrash::defaultCrashHandler);
763 TDECrash::setEmergencySaveFunction(crashHandler);
764 TDECrash::setApplicationName(TQString(appName));
765
766 // this program is in tdelibs so it uses tdelibs as catalog
767 TDELocale::setMainCatalogue("tdelibs");
768 // force generating of TDELocale object. if not, the database will get
769 // be translated
770 TDEGlobal::locale();
771 TDEGlobal::dirs()->addResourceType("app-reg", "share/application-registry" );
772
773 DCOPClient *dcopClient = new DCOPClient();
774
775 while(true)
776 {
777 TQCString registeredName = dcopClient->registerAs(appName, false);
778 if (registeredName.isEmpty())
779 {
780 fprintf(stderr, "[tdebuildsycoca] Warning: %s is unable to register with DCOP.\n", appName);
781 break;
782 }
783 else if (registeredName == appName)
784 {
785 break; // Go
786 }
787 fprintf(stderr, "[tdebuildsycoca] Waiting for already running %s to finish.\n", appName);
788
789 dcopClient->setNotifications( true );
790 while (dcopClient->isApplicationRegistered(appName))
791 {
792 WaitForSignal *obj = new WaitForSignal;
793 obj->connect(dcopClient, TQ_SIGNAL(applicationRemoved(const TQCString &)),
794 TQ_SLOT(deleteLater()));
795 tdeApp->eventLoop()->enterLoop();
796 }
797 dcopClient->setNotifications( false );
798 }
799 fprintf(stderr, "[tdebuildsycoca] %s running...\n", appName);
800
801 bool checkfiles = bGlobalDatabase || args->isSet("checkfiles");
802
803 bool incremental = !bGlobalDatabase && args->isSet("incremental") && checkfiles;
804 if (incremental || !checkfiles)
805 {
806 KSycoca::self()->disableAutoRebuild(); // Prevent deadlock
807 TQString current_language = TDEGlobal::locale()->language();
808 TQString tdesycoca_language = KSycoca::self()->language();
809 TQ_UINT32 current_update_sig = TDEGlobal::dirs()->calcResourceHash("services", "update_tdesycoca", true);
810 TQ_UINT32 tdesycoca_update_sig = KSycoca::self()->updateSignature();
811
812 if ((current_update_sig != tdesycoca_update_sig) ||
813 (current_language != tdesycoca_language) ||
814 (KSycoca::self()->timeStamp() == 0))
815 {
816 incremental = false;
817 checkfiles = true;
818 delete KSycoca::self();
819 }
820 }
821
822 g_changeList = new TQStringList;
823
824 bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles;
825 TQ_UINT32 filestamp = 0;
826 TQStringList oldresourcedirs;
827 if( checkstamps && incremental )
828 {
829 TQString path = sycocaPath()+"stamp";
830 TQCString qPath = TQFile::encodeName(path);
831 cSycocaPath = qPath.data(); // Delete timestamps on crash
832 TQFile tdesycocastamp(path);
833 if( tdesycocastamp.open( IO_ReadOnly ))
834 {
835 TQDataStream str( &tdesycocastamp );
836 if (!str.atEnd())
837 str >> filestamp;
838 if (!str.atEnd())
839 {
840 str >> oldresourcedirs;
841 if( oldresourcedirs != KBuildSycoca::existingResourceDirs())
842 checkstamps = false;
843 }
844 else
845 {
846 checkstamps = false;
847 }
848 if (!str.atEnd())
849 {
850 TQStringList extraResourceDirs;
851 str >> extraResourceDirs;
852 oldresourcedirs += extraResourceDirs;
853 }
854 }
855 else
856 {
857 checkstamps = false;
858 }
859 cSycocaPath = 0;
860 }
861
862 newTimestamp = (TQ_UINT32) time(0);
863
864 if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, oldresourcedirs )))
865 {
866 TQCString qSycocaPath = TQFile::encodeName(sycocaPath());
867 cSycocaPath = qSycocaPath.data();
868
869 g_allEntries = 0;
870 g_ctimeDict = 0;
871 if (incremental)
872 {
873 tqWarning("[tdebuildsycoca] Reusing existing tdesycoca.");
874 KSycoca *oldSycoca = KSycoca::self();
875 KSycocaFactoryList *factories = new KSycocaFactoryList;
876 g_allEntries = new KSycocaEntryListList;
877 g_ctimeDict = new TQDict<TQ_UINT32>(523);
878
879 // Must be in same order as in KBuildSycoca::recreate()!
880 factories->append( new KServiceTypeFactory );
881 factories->append( new KServiceGroupFactory );
882 factories->append( new KServiceFactory );
883 factories->append( new KImageIOFactory );
884 factories->append( new KProtocolInfoFactory );
885
886 // For each factory
887 for (KSycocaFactory *factory = factories->first();
888 factory;
889 factory = factories->next() )
890 {
891 KSycocaEntry::List list;
892 list = factory->allEntries();
893 g_allEntries->append( list );
894 }
895 delete factories; factories = 0;
896 KCTimeInfo *ctimeInfo = new KCTimeInfo;
897 ctimeInfo->fillCTimeDict(*g_ctimeDict);
898 delete oldSycoca;
899 }
900 cSycocaPath = 0;
901
902 KBuildSycoca *sycoca= new KBuildSycoca; // Build data base
903 if (args->isSet("track"))
904 sycoca->setTrackId(TQString::fromLocal8Bit(args->getOption("track")));
905 if (!sycoca->recreate()) {
906#ifdef KBUILDSYCOCA_GUI
907 if (!silent || showprogress)
908 progress.close();
909#endif
910 return -1;
911 }
912
913 if (bGlobalDatabase)
914 {
915 // These directories may have been created with 0700 permission
916 // better delete them if they are empty
917 TQString applnkDir = TDEGlobal::dirs()->saveLocation("apps", TQString::null, false);
918 ::rmdir(TQFile::encodeName(applnkDir));
919 TQString servicetypesDir = TDEGlobal::dirs()->saveLocation("servicetypes", TQString::null, false);
920 ::rmdir(TQFile::encodeName(servicetypesDir));
921 }
922 }
923
924 if (!bGlobalDatabase)
925 {
926 // Recreate compatibility symlink
927 TQString oldPath = oldSycocaPath();
928 if (!oldPath.isEmpty())
929 {
930 KTempFile tmp;
931 if (tmp.status() == 0)
932 {
933 TQString tmpFile = tmp.name();
934 tmp.unlink();
935 symlink(TQFile::encodeName(sycocaPath()), TQFile::encodeName(tmpFile));
936 rename(TQFile::encodeName(tmpFile), TQFile::encodeName(oldPath));
937 }
938 }
939 }
940
941 if (args->isSet("signal"))
942 {
943 // Notify ALL applications that have a tdesycoca object, using a broadcast
944 TQByteArray data;
945 TQDataStream stream(data, IO_WriteOnly);
946 stream << *g_changeList;
947 dcopClient->send( "*", "tdesycoca", "notifyDatabaseChanged(TQStringList)", data );
948 }
949
950#ifdef KBUILDSYCOCA_GUI
951 if (!silent) {
952 progress.close();
953 KMessageBox::information(0, i18n("[tdebuildsycoca] Configuration information reloaded successfully."), capt);
954 }
955#endif
956 return 0;
957}
958
959#include "tdebuildsycoca.moc"
KBuildImageIOFactory
Service group factory for building tdesycoca.
Definition: kbuildimageiofactory.h:30
KBuildImageIOFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildimageiofactory.cpp:41
KBuildProtocolInfoFactory
Protocol Info factory for building tdesycoca.
Definition: kbuildprotocolinfofactory.h:31
KBuildProtocolInfoFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildprotocolinfofactory.cpp:40
KBuildServiceFactory
Service factory for building tdesycoca.
Definition: kbuildservicefactory.h:36
KBuildServiceFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicefactory.cpp:50
KBuildServiceFactory::addEntry
void addEntry(KSycocaEntry *newEntry, const char *resource)
Add a new entry.
Definition: kbuildservicefactory.cpp:228
KBuildServiceGroupFactory
Service group factory for building tdesycoca.
Definition: kbuildservicegroupfactory.h:31
KBuildServiceGroupFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicegroupfactory.cpp:40
KBuildServiceGroupFactory::addNew
KServiceGroup * addNew(const TQString &menuName, const TQString &file, KServiceGroup *entry, bool isDeleted)
Add new menu menuName defined by file When entry is non-null it is re-used, otherwise a new group is ...
Definition: kbuildservicegroupfactory.cpp:75
KBuildServiceGroupFactory::addNewEntryTo
void addNewEntryTo(const TQString &menuName, KService *newEntry)
Adds the entry newEntry to the menu menuName.
Definition: kbuildservicegroupfactory.cpp:59
KBuildServiceTypeFactory
Service-type factory for building tdesycoca.
Definition: kbuildservicetypefactory.h:31
KBuildServiceTypeFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicetypefactory.cpp:47
KCTimeInfo
Service group factory for building tdesycoca.
Definition: kctimefactory.h:30

kded

Skip menu "kded"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kded

Skip menu "kded"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kded by doxygen 1.9.4
This website is maintained by Timothy Pearson.