25 #include <dcopclient.h>
26 #include <tdeaboutdata.h>
27 #include <tdeaction.h>
28 #include <tdeactionclasses.h>
29 #include <tdeactioncollection.h>
30 #include <tdeapplication.h>
31 #include <tdeconfig.h>
32 #include <tdeconfigdialog.h>
33 #include <tdefiledialog.h>
34 #include <tdeglobalsettings.h>
35 #include <tdehtmldefaults.h>
36 #include <kinstance.h>
37 #include <tdemainwindow.h>
38 #include <tdemessagebox.h>
39 #include <knotifyclient.h>
40 #include <knotifydialog.h>
41 #include <tdepopupmenu.h>
43 #include <kstandarddirs.h>
44 #include <kstdaction.h>
45 #include <tdetempfile.h>
47 #include <tdeio/netaccess.h>
48 #include <tdeparts/browserinterface.h>
49 #include <tdeparts/genericfactory.h>
50 #include <tdeparts/partmanager.h>
53 #include <tqobjectlist.h>
54 #include <tqstringlist.h>
56 #include <tqwidgetlist.h>
57 #include <tqucomextra_p.h>
60 #include <sys/types.h>
66 #include "aboutdata.h"
67 #include "actionmanagerimpl.h"
68 #include "akregator_part.h"
69 #include "akregator_view.h"
70 #include "akregatorconfig.h"
71 #include "articlefilter.h"
72 #include "articleinterceptor.h"
73 #include "configdialog.h"
74 #include "fetchqueue.h"
78 #include "kcursorsaver.h"
79 #include "notificationmanager.h"
80 #include "pageviewer.h"
82 #include "pluginmanager.h"
84 #include "storagefactory.h"
85 #include "storagefactorydummyimpl.h"
86 #include "storagefactoryregistry.h"
87 #include "speechclient.h"
94 typedef KParts::GenericFactory<Part> AkregatorFactory;
95 K_EXPORT_COMPONENT_FACTORY( libakregatorpart, AkregatorFactory )
97 BrowserExtension::BrowserExtension(Part *p,
const char *name)
98 : KParts::BrowserExtension( p, name )
103 void BrowserExtension::saveSettings()
105 m_part->saveSettings();
108 class Part::ApplyFiltersInterceptor :
public ArticleInterceptor
111 virtual ~ApplyFiltersInterceptor() {}
113 virtual void processArticle(Article& article)
115 Filters::ArticleFilterList list = Kernel::self()->articleFilterList();
116 for (Filters::ArticleFilterList::ConstIterator it = list.begin(); it != list.end(); ++it)
117 (*it).applyTo(article);
122 TQObject *parent,
const char *name,
const TQStringList& )
123 : DCOPObject(
"AkregatorIface")
124 , MyBasePart(parent, name)
125 , m_standardListLoaded(false)
126 , m_shuttingDown(false)
129 , m_backedUpList(false)
133 setInstance( AkregatorFactory::instance() );
136 KNotifyClient::startDaemon();
138 m_standardFeedList = TDEGlobal::dirs()->saveLocation(
"data",
"akregator/data") +
"/feeds.opml";
140 m_tagSetPath = TDEGlobal::dirs()->saveLocation(
"data",
"akregator/data") +
"/tagset.xml";
142 Backend::StorageFactoryDummyImpl* dummyFactory =
new Backend::StorageFactoryDummyImpl();
143 Backend::StorageFactoryRegistry::self()->registerFactory(dummyFactory, dummyFactory->key());
147 Backend::StorageFactory* factory = Backend::StorageFactoryRegistry::self()->getFactory(Settings::archiveBackend());
149 TQStringList storageParams;
151 storageParams.append(TQString(
"taggingEnabled=%1").arg(Settings::showTaggingGUI() ?
"true" :
"false"));
155 if (factory->allowsMultipleWriteAccess())
157 m_storage = factory->createStorage(storageParams);
161 if (tryToLock(factory->name()))
162 m_storage = factory->createStorage(storageParams);
164 m_storage = dummyFactory->createStorage(storageParams);
171 m_storage = Backend::StorageFactoryRegistry::self()->getFactory(
"dummy")->createStorage(storageParams);
173 KMessageBox::error(parentWidget, i18n(
"Unable to load storage backend plugin \"%1\". No feeds are archived.").arg(Settings::archiveBackend()), i18n(
"Plugin error") );
176 Filters::ArticleFilterList list;
177 list.readConfig(Settings::self()->config());
178 Kernel::self()->setArticleFilterList(list);
180 m_applyFiltersInterceptor =
new ApplyFiltersInterceptor();
181 ArticleInterceptorManager::self()->addInterceptor(m_applyFiltersInterceptor);
183 m_storage->
open(
true);
184 Kernel::self()->setStorage(m_storage);
185 Backend::Storage::setInstance(m_storage);
187 loadTagSet(m_tagSetPath);
190 ActionManager::setInstance(m_actionManager);
192 m_view =
new Akregator::View(
this, parentWidget, m_actionManager,
"akregator_view");
193 m_actionManager->initView(m_view);
194 m_actionManager->setTagSet(Kernel::self()->tagSet());
196 m_extension =
new BrowserExtension(
this,
"ak_extension");
198 connect(m_view, TQ_SIGNAL(setWindowCaption(
const TQString&)),
this, TQ_SIGNAL(setWindowCaption(
const TQString&)));
199 connect(m_view, TQ_SIGNAL(setStatusBarText(
const TQString&)),
this, TQ_SIGNAL(setStatusBarText(
const TQString&)));
200 connect(m_view, TQ_SIGNAL(setProgress(
int)), m_extension, TQ_SIGNAL(loadingProgress(
int)));
201 connect(m_view, TQ_SIGNAL(signalCanceled(
const TQString&)),
this, TQ_SIGNAL(canceled(
const TQString&)));
202 connect(m_view, TQ_SIGNAL(signalStarted(TDEIO::Job*)),
this, TQ_SIGNAL(started(TDEIO::Job*)));
203 connect(m_view, TQ_SIGNAL(signalCompleted()),
this, TQ_SIGNAL(completed()));
209 TrayIcon::setInstance(trayIcon);
210 m_actionManager->initTrayIcon(trayIcon);
212 connect(trayIcon, TQ_SIGNAL(showPart()),
this, TQ_SIGNAL(showPart()));
222 connect( trayIcon, TQ_SIGNAL(quitSelected()),
223 kapp, TQ_SLOT(quit())) ;
225 connect( m_view, TQ_SIGNAL(signalUnreadCountChanged(
int)), trayIcon, TQ_SLOT(slotSetUnread(
int)) );
227 connect(kapp, TQ_SIGNAL(shutDown()),
this, TQ_SLOT(slotOnShutdown()));
229 m_autosaveTimer =
new TQTimer(
this);
230 connect(m_autosaveTimer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(
slotSaveFeedList()));
231 m_autosaveTimer->start(5*60*1000);
233 setXMLFile(
"akregator_part.rc",
true);
237 RSS::FileRetriever::setUserAgent(TQString(
"Akregator/%1; librss/remnants").arg(AKREGATOR_VERSION));
243 TDETrader::OfferList offers = PluginManager::query();
245 for( TDETrader::OfferList::ConstIterator it = offers.begin(), end = offers.end(); it != end; ++it )
247 Akregator::Plugin* plugin = PluginManager::createFromService(*it);
253 void Part::slotOnShutdown()
255 m_shuttingDown =
true;
257 const TQString lockLocation = locateLocal(
"data",
"akregator/lock");
258 KSimpleConfig config(lockLocation);
259 config.writeEntry(
"pid", -1);
262 m_autosaveTimer->stop();
265 saveTagSet(m_tagSetPath);
266 m_view->slotOnShutdown();
268 delete TrayIcon::getInstance();
269 TrayIcon::setInstance(0L);
275 void Part::slotSettingsChanged()
279 RSS::FileRetriever::setUseCache(Settings::useHTMLCache());
282 fonts.append(Settings::standardFont());
283 fonts.append(Settings::fixedFont());
284 fonts.append(Settings::sansSerifFont());
285 fonts.append(Settings::serifFont());
286 fonts.append(Settings::standardFont());
287 fonts.append(Settings::standardFont());
289 Settings::setFonts(fonts);
291 if (Settings::minimumFontSize() > Settings::mediumFontSize())
292 Settings::setMediumFontSize(Settings::minimumFontSize());
294 m_view->slotSettingsChanged();
295 emit signalSettingsChanged();
299 Kernel::self()->articleFilterList().writeConfig(Settings::self()->config());
305 kdDebug() <<
"Part::~Part() enter" << endl;
308 kdDebug() <<
"Part::~Part(): leaving" << endl;
309 ArticleInterceptorManager::self()->removeInterceptor(m_applyFiltersInterceptor);
310 delete m_applyFiltersInterceptor;
315 m_backedUpList =
false;
327 m_view->saveProperties(config);
339 if ( !m_standardFeedList.isEmpty() &&
openURL(m_standardFeedList) )
340 m_standardListLoaded =
true;
343 TQDomDocument Part::createDefaultFeedList()
346 TQDomProcessingInstruction z = doc.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\"");
347 doc.appendChild( z );
349 TQDomElement root = doc.createElement(
"opml" );
350 root.setAttribute(
"version",
"1.0");
351 doc.appendChild( root );
353 TQDomElement head = doc.createElement(
"head" );
354 root.appendChild(head);
356 TQDomElement text = doc.createElement(
"text" );
357 text.appendChild(doc.createTextNode(i18n(
"Feeds")));
358 head.appendChild(text);
360 TQDomElement body = doc.createElement(
"body" );
361 root.appendChild(body);
363 TQDomElement mainFolder = doc.createElement(
"outline" );
364 mainFolder.setAttribute(
"text",
"Free/Libre Software News");
365 body.appendChild(mainFolder);
367 TQDomElement tde = doc.createElement(
"outline" );
368 tde.setAttribute(
"text",i18n(
"Trinity Desktop News"));
369 tde.setAttribute(
"xmlUrl",
"http://trinitydesktop.org/rss.php");
370 mainFolder.appendChild(tde);
372 TQDomElement lxer = doc.createElement(
"outline" );
373 lxer.setAttribute(
"text",i18n(
"LXer Linux News"));
374 lxer.setAttribute(
"xmlUrl",
"http://lxer.com/module/newswire/headlines.rss");
375 mainFolder.appendChild(lxer);
377 TQDomElement tux = doc.createElement(
"outline" );
378 tux.setAttribute(
"text",i18n(
"Tuxmachines"));
379 tux.setAttribute(
"xmlUrl",
"http://www.tuxmachines.org/node/feed");
380 mainFolder.appendChild(tux);
382 TQDomElement lwn = doc.createElement(
"outline" );
383 lwn.setAttribute(
"text",i18n(
"lwn.net"));
384 lwn.setAttribute(
"xmlUrl",
"http://lwn.net/headlines/rss");
385 mainFolder.appendChild(lwn);
392 emit setStatusBarText(i18n(
"Opening Feed List...") );
398 bool fileExists = file.exists();
399 TQString listBackup = m_storage->restoreFeedList();
405 doc = createDefaultFeedList();
409 if (file.open(IO_ReadOnly))
412 TQTextStream stream(&file);
413 stream.setEncoding(TQTextStream::UnicodeUTF8);
418 if (!doc.setContent(str))
423 TQString backup = m_file +
"-backup." + TQString::number(TQDateTime::currentDateTime().toTime_t());
427 KMessageBox::error(m_view, i18n(
"<qt>The standard feed list is corrupted (invalid XML). A backup was created:<p><b>%2</b></p></qt>").arg(backup), i18n(
"XML Parsing Error") );
430 if (!doc.setContent(listBackup))
431 doc = createDefaultFeedList();
439 TQString backup = m_file +
"-backup." + TQString::number(TQDateTime::currentDateTime().toTime_t());
442 KMessageBox::error(m_view, i18n(
"<qt>The standard feed list is corrupted (no valid OPML). A backup was created:<p><b>%2</b></p></qt>").arg(backup), i18n(
"OPML Parsing Error") );
444 m_view->
loadFeeds(createDefaultFeedList());
447 emit setStatusBarText(TQString());
450 if( Settings::markAllFeedsReadOnStartup() )
453 if (Settings::fetchOnStartup())
462 if (!m_standardListLoaded)
468 TQString backup = m_file +
"~";
470 if (copyFile(backup))
471 m_backedUpList =
true;
478 if (file.open(IO_WriteOnly) ==
false)
481 KMessageBox::error(m_view, i18n(
"Access denied: cannot save feed list (%1)").arg(m_file), i18n(
"Write error") );
486 TQTextStream stream(&file);
487 stream.setEncoding(TQTextStream::UnicodeUTF8);
492 stream << xmlStr << endl;
499 return Settings::showTrayIcon();
504 if (part != m_mergedPart)
509 removeChildClient(m_mergedPart);
511 insertChildClient(part);
516 factory()->removeClient(m_mergedPart);
517 if (childClients()->containsRef(m_mergedPart))
518 removeChildClient(m_mergedPart);
521 factory()->addClient(part);
533 TQWidgetList *l = kapp->topLevelWidgets();
534 TQWidgetListIt it( *l );
538 while ( (wid = it.current()) != 0 )
542 if (TQString(wid->name()) ==
"akregator_mainwindow")
549 TQWidgetListIt it2( *l );
550 while ( (wid = it2.current()) != 0 )
553 if (TQString(wid->name()).startsWith(
"kontact-mainwindow"))
563 void Part::loadTagSet(
const TQString& path)
568 if (file.open(IO_ReadOnly))
570 doc.setContent(TQByteArray(file.readAll()));
576 doc.setContent(m_storage->restoreTagSet());
581 Kernel::self()->tagSet()->readFromXML(doc);
585 Kernel::self()->tagSet()->insert(Tag(
"http://akregator.sf.net/tags/Interesting", i18n(
"Interesting")));
589 void Part::saveTagSet(
const TQString& path)
591 TQString xmlStr = Kernel::self()->tagSet()->toXML().toString();
593 m_storage->storeTagSet(xmlStr);
597 if ( file.open(IO_WriteOnly) )
600 TQTextStream stream(&file);
601 stream.setEncoding(TQTextStream::UnicodeUTF8);
602 stream << xmlStr <<
"\n";
607 void Part::importFile(
const KURL& url)
611 bool isRemote =
false;
613 if (url.isLocalFile())
614 filename = url.path();
619 if (!TDEIO::NetAccess::download(url, filename, m_view) )
621 KMessageBox::error(m_view, TDEIO::NetAccess::lastErrorString() );
626 TQFile file(filename);
627 if (file.open(IO_ReadOnly))
631 if (doc.setContent(TQByteArray(file.readAll())))
634 KMessageBox::error(m_view, i18n(
"Could not import the file %1 (no valid OPML)").arg(filename), i18n(
"OPML Parsing Error") );
637 KMessageBox::error(m_view, i18n(
"The file %1 could not be read, check if it exists or if it is readable for the current user.").arg(filename), i18n(
"Read Error"));
640 TDEIO::NetAccess::removeTempFile(filename);
643 void Part::exportFile(
const KURL& url)
645 if (url.isLocalFile())
647 TQFile file(url.path());
649 if ( file.exists() &&
650 KMessageBox::questionYesNo(m_view,
651 i18n(
"The file %1 already exists; do you want to overwrite it?").arg(file.name()),
654 KStdGuiItem::cancel()) == KMessageBox::No )
657 if ( !file.open(IO_WriteOnly) )
659 KMessageBox::error(m_view, i18n(
"Access denied: cannot write to file %1").arg(file.name()), i18n(
"Write Error") );
663 TQTextStream stream(&file);
664 stream.setEncoding(TQTextStream::UnicodeUTF8);
672 tmpfile.setAutoDelete(
true);
674 TQTextStream stream(tmpfile.file());
675 stream.setEncoding(TQTextStream::UnicodeUTF8);
680 if (!TDEIO::NetAccess::upload(tmpfile.name(), url, m_view))
681 KMessageBox::error(m_view, TDEIO::NetAccess::lastErrorString() );
685 void Part::fileImport()
687 KURL url = KFileDialog::getOpenURL( TQString(),
688 "*.opml *.xml|" + i18n(
"OPML Outlines (*.opml, *.xml)")
689 +
"\n*|" + i18n(
"All Files") );
695 void Part::fileExport()
697 KURL url= KFileDialog::getSaveURL( TQString(),
698 "*.opml *.xml|" + i18n(
"OPML Outlines (*.opml, *.xml)")
699 +
"\n*|" + i18n(
"All Files") );
701 if ( !url.isEmpty() )
705 void Part::fileGetFeeds()
712 void Part::fileSendArticle(
bool attach)
715 TQString title, text;
717 text = m_view->currentFrame()->part()->url().prettyURL();
718 if(text.isEmpty() || text.isNull())
721 title = m_view->currentFrame()->title();
724 kapp->invokeMailer(
"",
733 kapp->invokeMailer(
"",
746 void Part::fetchFeedUrl(
const TQString&s)
748 kdDebug() <<
"fetchFeedURL==" << s << endl;
753 for (TQStringList::ConstIterator it = urls.begin(); it != urls.end(); ++it)
755 kdDebug() <<
"Akregator::Part::addFeedToGroup adding feed with URL " << *it <<
" to group " << group << endl;
771 void Part::showKNotifyOptions()
774 KNotifyDialog::configure(m_view,
"akregator_knotify_config", about);
780 if ( TDEConfigDialog::showDialog(
"settings" ) )
783 TDEConfigDialog* dialog =
new ConfigDialog( m_view,
"settings", Settings::self() );
785 connect( dialog, TQ_SIGNAL(settingsChanged()),
786 this, TQ_SLOT(slotSettingsChanged()) );
787 connect( dialog, TQ_SIGNAL(settingsChanged()),
788 TrayIcon::getInstance(), TQ_SLOT(settingsChanged()) );
795 if (factory() && m_mergedPart)
797 if (event->activated())
798 factory()->addClient(m_mergedPart);
800 factory()->removeClient(m_mergedPart);
803 MyBasePart::partActivateEvent(event);
806 KParts::Part* Part::hitTest(TQWidget *widget,
const TQPoint &globalPos)
809 TQWidget *me = this->widget();
818 widget = widget->parentWidget();
820 if (m_view && m_view->currentFrame() && child) {
821 return m_view->currentFrame()->part();
823 return MyBasePart::hitTest(widget, globalPos);
827 void Part::initFonts()
829 TQStringList fonts = Settings::fonts();
832 fonts.append(TDEGlobalSettings::generalFont().family());
833 fonts.append(TDEGlobalSettings::fixedFont().family());
834 fonts.append(TDEGlobalSettings::generalFont().family());
835 fonts.append(TDEGlobalSettings::generalFont().family());
838 Settings::setFonts(fonts);
839 if (Settings::standardFont().isEmpty())
840 Settings::setStandardFont(fonts[0]);
841 if (Settings::fixedFont().isEmpty())
842 Settings::setFixedFont(fonts[1]);
843 if (Settings::sansSerifFont().isEmpty())
844 Settings::setSansSerifFont(fonts[2]);
845 if (Settings::serifFont().isEmpty())
846 Settings::setSerifFont(fonts[3]);
848 TDEConfig* conf = Settings::self()->config();
849 conf->setGroup(
"HTML Settings");
851 TDEConfig konq(
"konquerorrc",
true,
false);
852 konq.setGroup(
"HTML Settings");
854 if (!conf->hasKey(
"MinimumFontSize"))
857 if (konq.hasKey(
"MinimumFontSize"))
858 minfs = konq.readNumEntry(
"MinimumFontSize");
860 minfs = TDEGlobalSettings::generalFont().pointSize();
861 kdDebug() <<
"Part::initFonts(): set MinimumFontSize to " << minfs << endl;
862 Settings::setMinimumFontSize(minfs);
865 if (!conf->hasKey(
"MediumFontSize"))
868 if (konq.hasKey(
"MediumFontSize"))
869 medfs = konq.readNumEntry(
"MediumFontSize");
871 medfs = TDEGlobalSettings::generalFont().pointSize();
872 kdDebug() <<
"Part::initFonts(): set MediumFontSize to " << medfs << endl;
873 Settings::setMediumFontSize(medfs);
876 if (!conf->hasKey(
"UnderlineLinks"))
878 bool underline =
true;
879 if (konq.hasKey(
"UnderlineLinks"))
880 underline = konq.readBoolEntry(
"UnderlineLinks");
882 kdDebug() <<
"Part::initFonts(): set UnderlineLinks to " << underline << endl;
883 Settings::setUnderlineLinks(underline);
886 if (!conf->hasKey(
"EnableFavicon"))
888 bool enableFavicon =
true;
889 if (konq.hasKey(
"EnableFavicon"))
890 enableFavicon = konq.readBoolEntry(
"EnableFavicon");
892 kdDebug() <<
"Part::initFonts(): set EnableFavicon to " << enableFavicon << endl;
893 Settings::setEnableFavIcon(enableFavicon);
896 if (!conf->hasKey(
"AutoLoadImages"))
898 bool autoLoadImages =
true;
899 if (konq.hasKey(
"AutoLoadImages"))
900 autoLoadImages = konq.readBoolEntry(
"AutoLoadImages");
902 kdDebug() <<
"Part::initFonts(): set AutoLoadImages to " << autoLoadImages << endl;
903 Settings::setAutoLoadImages(autoLoadImages);
908 bool Part::copyFile(
const TQString& backup)
912 if (file.open(IO_ReadOnly))
914 TQFile backupFile(backup);
915 if (backupFile.open(IO_WriteOnly))
917 TQTextStream in(&file);
918 TQTextStream out(&backupFile);
920 out << in.readLine();
934 static TQString getMyHostName()
940 if(gethostname(hostNameC, 255))
942 return TQString::fromLocal8Bit(hostNameC);
946 bool Part::tryToLock(
const TQString& backendName)
949 TQString appName = kapp->instanceName();
950 if ( appName.isEmpty() )
951 appName =
"akregator";
953 TQString programName;
954 const TDEAboutData *about = kapp->aboutData();
956 programName = about->programName();
957 if ( programName.isEmpty() )
958 programName = i18n(
"Akregator");
960 TQString lockLocation = locateLocal(
"data",
"akregator/lock");
961 KSimpleConfig config(lockLocation);
962 int oldPid = config.readNumEntry(
"pid", -1);
963 const TQString oldHostName = config.readEntry(
"hostname");
964 const TQString oldAppName = config.readEntry(
"appName", appName );
965 const TQString oldProgramName = config.readEntry(
"programName", programName );
966 const TQString hostName = getMyHostName();
967 bool first_instance =
false;
969 first_instance =
true;
973 else if (hostName == oldHostName && oldPid != getpid()) {
974 if ( kill(oldPid, 0) == -1 )
975 first_instance = ( errno == ESRCH );
978 if ( !first_instance )
981 if ( oldHostName == hostName )
986 if ( oldAppName == appName )
987 msg = i18n(
"<qt>%1 already seems to be running on another display on "
988 "this machine. <b>Running %2 more than once is not supported "
989 "by the %3 backend and "
990 "can cause the loss of archived articles and crashes at startup.</b> "
991 "You should disable the archive for now "
992 "unless you are sure that %2 is not already running.</qt>")
993 .arg( programName, programName, backendName );
999 msg = i18n(
"<qt>%1 seems to be running on another display on this "
1000 "machine. <b>Running %1 and %2 at the same "
1001 "time is not supported by the %3 backend and can cause "
1002 "the loss of archived articles and crashes at startup.</b> "
1003 "You should disable the archive for now "
1004 "unless you are sure that %2 is not already running.</qt>")
1005 .arg( oldProgramName, programName, backendName );
1009 if ( oldAppName == appName )
1010 msg = i18n(
"<qt>%1 already seems to be running on %2. <b>Running %1 more "
1011 "than once is not supported by the %3 backend and can cause "
1012 "the loss of archived articles and crashes at startup.</b> "
1013 "You should disable the archive for now "
1014 "unless you are sure that it is "
1015 "not already running on %2.</qt>")
1016 .arg( programName, oldHostName, backendName );
1018 msg = i18n(
"<qt>%1 seems to be running on %3. <b>Running %1 and %2 at the "
1019 "same time is not supported by the %4 backend and can cause "
1020 "the loss of archived articles and crashes at startup.</b> "
1021 "You should disable the archive for now "
1022 "unless you are sure that %1 is "
1023 "not running on %3.</qt>")
1024 .arg( oldProgramName, programName, oldHostName, backendName );
1027 KCursorSaver idle( KBusyPtr::idle() );
1028 if ( KMessageBox::No ==
1029 KMessageBox::warningYesNo( 0, msg, TQString(),
1030 i18n(
"Force Access"),
1031 i18n(
"Disable Archive")) )
1037 config.writeEntry(
"pid", getpid());
1038 config.writeEntry(
"hostname", hostName);
1039 config.writeEntry(
"appName", appName );
1040 config.writeEntry(
"programName", programName );
1047 #include "akregator_part.moc"