00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <dcopclient.h>
00026 #include <tdeaboutdata.h>
00027 #include <tdeaction.h>
00028 #include <tdeactionclasses.h>
00029 #include <tdeactioncollection.h>
00030 #include <tdeapplication.h>
00031 #include <tdeconfig.h>
00032 #include <tdeconfigdialog.h>
00033 #include <tdefiledialog.h>
00034 #include <tdeglobalsettings.h>
00035 #include <tdehtmldefaults.h>
00036 #include <kinstance.h>
00037 #include <tdemainwindow.h>
00038 #include <tdemessagebox.h>
00039 #include <knotifyclient.h>
00040 #include <knotifydialog.h>
00041 #include <tdepopupmenu.h>
00042 #include <kservice.h>
00043 #include <kstandarddirs.h>
00044 #include <kstdaction.h>
00045 #include <tdetempfile.h>
00046 #include <ktrader.h>
00047 #include <tdeio/netaccess.h>
00048 #include <tdeparts/browserinterface.h>
00049 #include <tdeparts/genericfactory.h>
00050 #include <tdeparts/partmanager.h>
00051
00052 #include <tqfile.h>
00053 #include <tqobjectlist.h>
00054 #include <tqstringlist.h>
00055 #include <tqtimer.h>
00056 #include <tqwidgetlist.h>
00057 #include <tqucomextra_p.h>
00058
00059 #include <cerrno>
00060 #include <sys/types.h>
00061 #include <signal.h>
00062 #include <stdio.h>
00063 #include <stdlib.h>
00064 #include <unistd.h>
00065
00066 #include "aboutdata.h"
00067 #include "actionmanagerimpl.h"
00068 #include "akregator_part.h"
00069 #include "akregator_view.h"
00070 #include "akregatorconfig.h"
00071 #include "articlefilter.h"
00072 #include "articleinterceptor.h"
00073 #include "configdialog.h"
00074 #include "fetchqueue.h"
00075 #include "frame.h"
00076 #include "article.h"
00077 #include "kernel.h"
00078 #include "kcursorsaver.h"
00079 #include "notificationmanager.h"
00080 #include "pageviewer.h"
00081 #include "plugin.h"
00082 #include "pluginmanager.h"
00083 #include "storage.h"
00084 #include "storagefactory.h"
00085 #include "storagefactorydummyimpl.h"
00086 #include "storagefactoryregistry.h"
00087 #include "speechclient.h"
00088 #include "trayicon.h"
00089 #include "tagset.h"
00090 #include "tag.h"
00091
00092 namespace Akregator {
00093
00094 typedef KParts::GenericFactory<Part> AkregatorFactory;
00095 K_EXPORT_COMPONENT_FACTORY( libakregatorpart, AkregatorFactory )
00096
00097 BrowserExtension::BrowserExtension(Part *p, const char *name)
00098 : KParts::BrowserExtension( p, name )
00099 {
00100 m_part=p;
00101 }
00102
00103 void BrowserExtension::saveSettings()
00104 {
00105 m_part->saveSettings();
00106 }
00107
00108 class Part::ApplyFiltersInterceptor : public ArticleInterceptor
00109 {
00110 public:
00111 virtual ~ApplyFiltersInterceptor() {}
00112
00113 virtual void processArticle(Article& article)
00114 {
00115 Filters::ArticleFilterList list = Kernel::self()->articleFilterList();
00116 for (Filters::ArticleFilterList::ConstIterator it = list.begin(); it != list.end(); ++it)
00117 (*it).applyTo(article);
00118 }
00119 };
00120
00121 Part::Part( TQWidget *parentWidget, const char * ,
00122 TQObject *parent, const char *name, const TQStringList& )
00123 : DCOPObject("AkregatorIface")
00124 , MyBasePart(parent, name)
00125 , m_standardListLoaded(false)
00126 , m_shuttingDown(false)
00127 , m_mergedPart(0)
00128 , m_view(0)
00129 , m_backedUpList(false)
00130 , m_storage(0)
00131 {
00132
00133 setInstance( AkregatorFactory::instance() );
00134
00135
00136 KNotifyClient::startDaemon();
00137
00138 m_standardFeedList = TDEGlobal::dirs()->saveLocation("data", "akregator/data") + "/feeds.opml";
00139
00140 m_tagSetPath = TDEGlobal::dirs()->saveLocation("data", "akregator/data") + "/tagset.xml";
00141
00142 Backend::StorageFactoryDummyImpl* dummyFactory = new Backend::StorageFactoryDummyImpl();
00143 Backend::StorageFactoryRegistry::self()->registerFactory(dummyFactory, dummyFactory->key());
00144 loadPlugins();
00145
00146 m_storage = 0;
00147 Backend::StorageFactory* factory = Backend::StorageFactoryRegistry::self()->getFactory(Settings::archiveBackend());
00148
00149 TQStringList storageParams;
00150
00151 storageParams.append(TQString("taggingEnabled=%1").arg(Settings::showTaggingGUI() ? "true" : "false"));
00152
00153 if (factory != 0)
00154 {
00155 if (factory->allowsMultipleWriteAccess())
00156 {
00157 m_storage = factory->createStorage(storageParams);
00158 }
00159 else
00160 {
00161 if (tryToLock(factory->name()))
00162 m_storage = factory->createStorage(storageParams);
00163 else
00164 m_storage = dummyFactory->createStorage(storageParams);
00165 }
00166 }
00167
00168
00169 if (!m_storage)
00170 {
00171 m_storage = Backend::StorageFactoryRegistry::self()->getFactory("dummy")->createStorage(storageParams);
00172
00173 KMessageBox::error(parentWidget, i18n("Unable to load storage backend plugin \"%1\". No feeds are archived.").arg(Settings::archiveBackend()), i18n("Plugin error") );
00174 }
00175
00176 Filters::ArticleFilterList list;
00177 list.readConfig(Settings::self()->config());
00178 Kernel::self()->setArticleFilterList(list);
00179
00180 m_applyFiltersInterceptor = new ApplyFiltersInterceptor();
00181 ArticleInterceptorManager::self()->addInterceptor(m_applyFiltersInterceptor);
00182
00183 m_storage->open(true);
00184 Kernel::self()->setStorage(m_storage);
00185 Backend::Storage::setInstance(m_storage);
00186
00187 loadTagSet(m_tagSetPath);
00188
00189 m_actionManager = new ActionManagerImpl(this);
00190 ActionManager::setInstance(m_actionManager);
00191
00192 m_view = new Akregator::View(this, parentWidget, m_actionManager, "akregator_view");
00193 m_actionManager->initView(m_view);
00194 m_actionManager->setTagSet(Kernel::self()->tagSet());
00195
00196 m_extension = new BrowserExtension(this, "ak_extension");
00197
00198 connect(m_view, TQT_SIGNAL(setWindowCaption(const TQString&)), this, TQT_SIGNAL(setWindowCaption(const TQString&)));
00199 connect(m_view, TQT_SIGNAL(setStatusBarText(const TQString&)), this, TQT_SIGNAL(setStatusBarText(const TQString&)));
00200 connect(m_view, TQT_SIGNAL(setProgress(int)), m_extension, TQT_SIGNAL(loadingProgress(int)));
00201 connect(m_view, TQT_SIGNAL(signalCanceled(const TQString&)), this, TQT_SIGNAL(canceled(const TQString&)));
00202 connect(m_view, TQT_SIGNAL(signalStarted(TDEIO::Job*)), this, TQT_SIGNAL(started(TDEIO::Job*)));
00203 connect(m_view, TQT_SIGNAL(signalCompleted()), this, TQT_SIGNAL(completed()));
00204
00205
00206 setWidget(m_view);
00207
00208 TrayIcon* trayIcon = new TrayIcon( getMainWindow() );
00209 TrayIcon::setInstance(trayIcon);
00210 m_actionManager->initTrayIcon(trayIcon);
00211
00212 connect(trayIcon, TQT_SIGNAL(showPart()), this, TQT_SIGNAL(showPart()));
00213
00214 if ( isTrayIconEnabled() )
00215 {
00216 trayIcon->show();
00217 NotificationManager::self()->setWidget(trayIcon, instance());
00218 }
00219 else
00220 NotificationManager::self()->setWidget(getMainWindow(), instance());
00221
00222 connect( trayIcon, TQT_SIGNAL(quitSelected()),
00223 kapp, TQT_SLOT(quit())) ;
00224
00225 connect( m_view, TQT_SIGNAL(signalUnreadCountChanged(int)), trayIcon, TQT_SLOT(slotSetUnread(int)) );
00226
00227 connect(kapp, TQT_SIGNAL(shutDown()), this, TQT_SLOT(slotOnShutdown()));
00228
00229 m_autosaveTimer = new TQTimer(this);
00230 connect(m_autosaveTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotSaveFeedList()));
00231 m_autosaveTimer->start(5*60*1000);
00232
00233 setXMLFile("akregator_part.rc", true);
00234
00235 initFonts();
00236
00237 RSS::FileRetriever::setUserAgent(TQString("Akregator/%1; librss/remnants").arg(AKREGATOR_VERSION));
00238 }
00239
00240 void Part::loadPlugins()
00241 {
00242
00243 TDETrader::OfferList offers = PluginManager::query();
00244
00245 for( TDETrader::OfferList::ConstIterator it = offers.begin(), end = offers.end(); it != end; ++it )
00246 {
00247 Akregator::Plugin* plugin = PluginManager::createFromService(*it);
00248 if (plugin)
00249 plugin->init();
00250 }
00251 }
00252
00253 void Part::slotOnShutdown()
00254 {
00255 m_shuttingDown = true;
00256
00257 const TQString lockLocation = locateLocal("data", "akregator/lock");
00258 KSimpleConfig config(lockLocation);
00259 config.writeEntry("pid", -1);
00260 config.sync();
00261
00262 m_autosaveTimer->stop();
00263 saveSettings();
00264 slotSaveFeedList();
00265 saveTagSet(m_tagSetPath);
00266 m_view->slotOnShutdown();
00267
00268 delete TrayIcon::getInstance();
00269 TrayIcon::setInstance(0L);
00270 delete m_storage;
00271 m_storage = 0;
00272
00273 }
00274
00275 void Part::slotSettingsChanged()
00276 {
00277 NotificationManager::self()->setWidget(isTrayIconEnabled() ? TrayIcon::getInstance() : getMainWindow(), instance());
00278
00279 RSS::FileRetriever::setUseCache(Settings::useHTMLCache());
00280
00281 TQStringList fonts;
00282 fonts.append(Settings::standardFont());
00283 fonts.append(Settings::fixedFont());
00284 fonts.append(Settings::sansSerifFont());
00285 fonts.append(Settings::serifFont());
00286 fonts.append(Settings::standardFont());
00287 fonts.append(Settings::standardFont());
00288 fonts.append("0");
00289 Settings::setFonts(fonts);
00290
00291 if (Settings::minimumFontSize() > Settings::mediumFontSize())
00292 Settings::setMediumFontSize(Settings::minimumFontSize());
00293 saveSettings();
00294 m_view->slotSettingsChanged();
00295 emit signalSettingsChanged();
00296 }
00297 void Part::saveSettings()
00298 {
00299 Kernel::self()->articleFilterList().writeConfig(Settings::self()->config());
00300 m_view->saveSettings();
00301 }
00302
00303 Part::~Part()
00304 {
00305 kdDebug() << "Part::~Part() enter" << endl;
00306 if (!m_shuttingDown)
00307 slotOnShutdown();
00308 kdDebug() << "Part::~Part(): leaving" << endl;
00309 ArticleInterceptorManager::self()->removeInterceptor(m_applyFiltersInterceptor);
00310 delete m_applyFiltersInterceptor;
00311 }
00312
00313 void Part::readProperties(TDEConfig* config)
00314 {
00315 m_backedUpList = false;
00316 openStandardFeedList();
00317
00318 if(m_view)
00319 m_view->readProperties(config);
00320 }
00321
00322 void Part::saveProperties(TDEConfig* config)
00323 {
00324 if (m_view)
00325 {
00326 slotSaveFeedList();
00327 m_view->saveProperties(config);
00328 }
00329 }
00330
00331 bool Part::openURL(const KURL& url)
00332 {
00333 m_file = url.path();
00334 return openFile();
00335 }
00336
00337 void Part::openStandardFeedList()
00338 {
00339 if ( !m_standardFeedList.isEmpty() && openURL(m_standardFeedList) )
00340 m_standardListLoaded = true;
00341 }
00342
00343 TQDomDocument Part::createDefaultFeedList()
00344 {
00345 TQDomDocument doc;
00346 TQDomProcessingInstruction z = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
00347 doc.appendChild( z );
00348
00349 TQDomElement root = doc.createElement( "opml" );
00350 root.setAttribute("version","1.0");
00351 doc.appendChild( root );
00352
00353 TQDomElement head = doc.createElement( "head" );
00354 root.appendChild(head);
00355
00356 TQDomElement text = doc.createElement( "text" );
00357 text.appendChild(doc.createTextNode(i18n("Feeds")));
00358 head.appendChild(text);
00359
00360 TQDomElement body = doc.createElement( "body" );
00361 root.appendChild(body);
00362
00363 TQDomElement mainFolder = doc.createElement( "outline" );
00364 mainFolder.setAttribute("text","Free/Libre Software News");
00365 body.appendChild(mainFolder);
00366
00367 TQDomElement tde = doc.createElement( "outline" );
00368 tde.setAttribute("text",i18n("Trinity Desktop News"));
00369 tde.setAttribute("xmlUrl","http://trinitydesktop.org/rss.php");
00370 mainFolder.appendChild(tde);
00371
00372 TQDomElement lxer = doc.createElement( "outline" );
00373 lxer.setAttribute("text",i18n("LXer Linux News"));
00374 lxer.setAttribute("xmlUrl","http://lxer.com/module/newswire/headlines.rss");
00375 mainFolder.appendChild(lxer);
00376
00377 TQDomElement tux = doc.createElement( "outline" );
00378 tux.setAttribute("text",i18n("Tuxmachines"));
00379 tux.setAttribute("xmlUrl","http://www.tuxmachines.org/node/feed");
00380 mainFolder.appendChild(tux);
00381
00382 TQDomElement lwn = doc.createElement( "outline" );
00383 lwn.setAttribute("text",i18n("lwn.net"));
00384 lwn.setAttribute("xmlUrl","http://lwn.net/headlines/rss");
00385 mainFolder.appendChild(lwn);
00386
00387 return doc;
00388 }
00389
00390 bool Part::openFile()
00391 {
00392 emit setStatusBarText(i18n("Opening Feed List...") );
00393
00394 TQString str;
00395
00396 TQFile file(m_file);
00397
00398 bool fileExists = file.exists();
00399 TQString listBackup = m_storage->restoreFeedList();
00400
00401 TQDomDocument doc;
00402
00403 if (!fileExists)
00404 {
00405 doc = createDefaultFeedList();
00406 }
00407 else
00408 {
00409 if (file.open(IO_ReadOnly))
00410 {
00411
00412 TQTextStream stream(&file);
00413 stream.setEncoding(TQTextStream::UnicodeUTF8);
00414 str = stream.read();
00415 file.close();
00416 }
00417
00418 if (!doc.setContent(str))
00419 {
00420
00421 if (file.size() > 0)
00422 {
00423 TQString backup = m_file + "-backup." + TQString::number(TQDateTime::currentDateTime().toTime_t());
00424
00425 copyFile(backup);
00426
00427 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") );
00428 }
00429
00430 if (!doc.setContent(listBackup))
00431 doc = createDefaultFeedList();
00432 }
00433 }
00434
00435 if (!m_view->loadFeeds(doc))
00436 {
00437 if (file.size() > 0)
00438 {
00439 TQString backup = m_file + "-backup." + TQString::number(TQDateTime::currentDateTime().toTime_t());
00440 copyFile(backup);
00441
00442 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") );
00443 }
00444 m_view->loadFeeds(createDefaultFeedList());
00445 }
00446
00447 emit setStatusBarText(TQString());
00448
00449
00450 if( Settings::markAllFeedsReadOnStartup() )
00451 m_view->slotMarkAllFeedsRead();
00452
00453 if (Settings::fetchOnStartup())
00454 m_view->slotFetchAllFeeds();
00455
00456 return true;
00457 }
00458
00459 void Part::slotSaveFeedList()
00460 {
00461
00462 if (!m_standardListLoaded)
00463 return;
00464
00465
00466 if (!m_backedUpList)
00467 {
00468 TQString backup = m_file + "~";
00469
00470 if (copyFile(backup))
00471 m_backedUpList = true;
00472 }
00473
00474 TQString xmlStr = m_view->feedListToOPML().toString();
00475 m_storage->storeFeedList(xmlStr);
00476
00477 TQFile file(m_file);
00478 if (file.open(IO_WriteOnly) == false)
00479 {
00480
00481 KMessageBox::error(m_view, i18n("Access denied: cannot save feed list (%1)").arg(m_file), i18n("Write error") );
00482 return;
00483 }
00484
00485
00486 TQTextStream stream(&file);
00487 stream.setEncoding(TQTextStream::UnicodeUTF8);
00488
00489
00490
00491
00492 stream << xmlStr << endl;
00493
00494 file.close();
00495 }
00496
00497 bool Part::isTrayIconEnabled() const
00498 {
00499 return Settings::showTrayIcon();
00500 }
00501
00502 bool Part::mergePart(KParts::Part* part)
00503 {
00504 if (part != m_mergedPart)
00505 {
00506 if (!factory())
00507 {
00508 if (m_mergedPart)
00509 removeChildClient(m_mergedPart);
00510 else
00511 insertChildClient(part);
00512 }
00513 else
00514 {
00515 if (m_mergedPart) {
00516 factory()->removeClient(m_mergedPart);
00517 if (childClients()->containsRef(m_mergedPart))
00518 removeChildClient(m_mergedPart);
00519 }
00520 if (part)
00521 factory()->addClient(part);
00522 }
00523
00524 m_mergedPart = part;
00525 }
00526 return true;
00527 }
00528
00529 TQWidget* Part::getMainWindow()
00530 {
00531
00532
00533 TQWidgetList *l = kapp->topLevelWidgets();
00534 TQWidgetListIt it( *l );
00535 TQWidget *wid;
00536
00537
00538 while ( (wid = it.current()) != 0 )
00539 {
00540 ++it;
00541
00542 if (TQString(wid->name()) == "akregator_mainwindow")
00543 {
00544 delete l;
00545 return wid;
00546 }
00547 }
00548
00549 TQWidgetListIt it2( *l );
00550 while ( (wid = it2.current()) != 0 )
00551 {
00552 ++it2;
00553 if (TQString(wid->name()).startsWith("kontact-mainwindow"))
00554 {
00555 delete l;
00556 return wid;
00557 }
00558 }
00559 delete l;
00560 return 0;
00561 }
00562
00563 void Part::loadTagSet(const TQString& path)
00564 {
00565 TQDomDocument doc;
00566
00567 TQFile file(path);
00568 if (file.open(IO_ReadOnly))
00569 {
00570 doc.setContent(TQByteArray(file.readAll()));
00571 file.close();
00572 }
00573
00574 if (doc.isNull())
00575 {
00576 doc.setContent(m_storage->restoreTagSet());
00577 }
00578
00579 if (!doc.isNull())
00580 {
00581 Kernel::self()->tagSet()->readFromXML(doc);
00582 }
00583 else
00584 {
00585 Kernel::self()->tagSet()->insert(Tag("http://akregator.sf.net/tags/Interesting", i18n("Interesting")));
00586 }
00587 }
00588
00589 void Part::saveTagSet(const TQString& path)
00590 {
00591 TQString xmlStr = Kernel::self()->tagSet()->toXML().toString();
00592
00593 m_storage->storeTagSet(xmlStr);
00594
00595 TQFile file(path);
00596
00597 if ( file.open(IO_WriteOnly) )
00598 {
00599
00600 TQTextStream stream(&file);
00601 stream.setEncoding(TQTextStream::UnicodeUTF8);
00602 stream << xmlStr << "\n";
00603 file.close();
00604 }
00605 }
00606
00607 void Part::importFile(const KURL& url)
00608 {
00609 TQString filename;
00610
00611 bool isRemote = false;
00612
00613 if (url.isLocalFile())
00614 filename = url.path();
00615 else
00616 {
00617 isRemote = true;
00618
00619 if (!TDEIO::NetAccess::download(url, filename, m_view) )
00620 {
00621 KMessageBox::error(m_view, TDEIO::NetAccess::lastErrorString() );
00622 return;
00623 }
00624 }
00625
00626 TQFile file(filename);
00627 if (file.open(IO_ReadOnly))
00628 {
00629
00630 TQDomDocument doc;
00631 if (doc.setContent(TQByteArray(file.readAll())))
00632 m_view->importFeeds(doc);
00633 else
00634 KMessageBox::error(m_view, i18n("Could not import the file %1 (no valid OPML)").arg(filename), i18n("OPML Parsing Error") );
00635 }
00636 else
00637 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"));
00638
00639 if (isRemote)
00640 TDEIO::NetAccess::removeTempFile(filename);
00641 }
00642
00643 void Part::exportFile(const KURL& url)
00644 {
00645 if (url.isLocalFile())
00646 {
00647 TQFile file(url.path());
00648
00649 if ( file.exists() &&
00650 KMessageBox::questionYesNo(m_view,
00651 i18n("The file %1 already exists; do you want to overwrite it?").arg(file.name()),
00652 i18n("Export"),
00653 i18n("Overwrite"),
00654 KStdGuiItem::cancel()) == KMessageBox::No )
00655 return;
00656
00657 if ( !file.open(IO_WriteOnly) )
00658 {
00659 KMessageBox::error(m_view, i18n("Access denied: cannot write to file %1").arg(file.name()), i18n("Write Error") );
00660 return;
00661 }
00662
00663 TQTextStream stream(&file);
00664 stream.setEncoding(TQTextStream::UnicodeUTF8);
00665
00666 stream << m_view->feedListToOPML().toString() << "\n";
00667 file.close();
00668 }
00669 else
00670 {
00671 KTempFile tmpfile;
00672 tmpfile.setAutoDelete(true);
00673
00674 TQTextStream stream(tmpfile.file());
00675 stream.setEncoding(TQTextStream::UnicodeUTF8);
00676
00677 stream << m_view->feedListToOPML().toString() << "\n";
00678 tmpfile.close();
00679
00680 if (!TDEIO::NetAccess::upload(tmpfile.name(), url, m_view))
00681 KMessageBox::error(m_view, TDEIO::NetAccess::lastErrorString() );
00682 }
00683 }
00684
00685 void Part::fileImport()
00686 {
00687 KURL url = KFileDialog::getOpenURL( TQString(),
00688 "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
00689 +"\n*|" + i18n("All Files") );
00690
00691 if (!url.isEmpty())
00692 importFile(url);
00693 }
00694
00695 void Part::fileExport()
00696 {
00697 KURL url= KFileDialog::getSaveURL( TQString(),
00698 "*.opml *.xml|" + i18n("OPML Outlines (*.opml, *.xml)")
00699 +"\n*|" + i18n("All Files") );
00700
00701 if ( !url.isEmpty() )
00702 exportFile(url);
00703 }
00704
00705 void Part::fileGetFeeds()
00706 {
00707
00708
00709
00710 }
00711
00712 void Part::fileSendArticle(bool attach)
00713 {
00714
00715 TQString title, text;
00716
00717 text = m_view->currentFrame()->part()->url().prettyURL();
00718 if(text.isEmpty() || text.isNull())
00719 return;
00720
00721 title = m_view->currentFrame()->title();
00722
00723 if(attach) {
00724 kapp->invokeMailer("",
00725 "",
00726 "",
00727 title,
00728 text,
00729 "",
00730 text);
00731 }
00732 else {
00733 kapp->invokeMailer("",
00734 "",
00735 "",
00736 title,
00737 text);
00738 }
00739 }
00740
00741 void Part::fetchAllFeeds()
00742 {
00743 m_view->slotFetchAllFeeds();
00744 }
00745
00746 void Part::fetchFeedUrl(const TQString&s)
00747 {
00748 kdDebug() << "fetchFeedURL==" << s << endl;
00749 }
00750
00751 void Part::addFeedsToGroup(const TQStringList& urls, const TQString& group)
00752 {
00753 for (TQStringList::ConstIterator it = urls.begin(); it != urls.end(); ++it)
00754 {
00755 kdDebug() << "Akregator::Part::addFeedToGroup adding feed with URL " << *it << " to group " << group << endl;
00756 m_view->addFeedToGroup(*it, group);
00757 }
00758 NotificationManager::self()->slotNotifyFeeds(urls);
00759 }
00760
00761 void Part::addFeed()
00762 {
00763 m_view->slotFeedAdd();
00764 }
00765
00766 TDEAboutData *Part::createAboutData()
00767 {
00768 return new Akregator::AboutData;
00769 }
00770
00771 void Part::showKNotifyOptions()
00772 {
00773 TDEAboutData* about = new Akregator::AboutData;
00774 KNotifyDialog::configure(m_view, "akregator_knotify_config", about);
00775 delete about;
00776 }
00777
00778 void Part::showOptions()
00779 {
00780 if ( TDEConfigDialog::showDialog( "settings" ) )
00781 return;
00782
00783 TDEConfigDialog* dialog = new ConfigDialog( m_view, "settings", Settings::self() );
00784
00785 connect( dialog, TQT_SIGNAL(settingsChanged()),
00786 this, TQT_SLOT(slotSettingsChanged()) );
00787 connect( dialog, TQT_SIGNAL(settingsChanged()),
00788 TrayIcon::getInstance(), TQT_SLOT(settingsChanged()) );
00789
00790 dialog->show();
00791 }
00792
00793 void Part::partActivateEvent(KParts::PartActivateEvent* event)
00794 {
00795 if (factory() && m_mergedPart)
00796 {
00797 if (event->activated())
00798 factory()->addClient(m_mergedPart);
00799 else
00800 factory()->removeClient(m_mergedPart);
00801 }
00802
00803 MyBasePart::partActivateEvent(event);
00804 }
00805
00806 KParts::Part* Part::hitTest(TQWidget *widget, const TQPoint &globalPos)
00807 {
00808 bool child = false;
00809 TQWidget *me = this->widget();
00810 while (widget) {
00811 if (widget == me) {
00812 child = true;
00813 break;
00814 }
00815 if (!widget) {
00816 break;
00817 }
00818 widget = widget->parentWidget();
00819 }
00820 if (m_view && m_view->currentFrame() && child) {
00821 return m_view->currentFrame()->part();
00822 } else {
00823 return MyBasePart::hitTest(widget, globalPos);
00824 }
00825 }
00826
00827 void Part::initFonts()
00828 {
00829 TQStringList fonts = Settings::fonts();
00830 if (fonts.isEmpty())
00831 {
00832 fonts.append(TDEGlobalSettings::generalFont().family());
00833 fonts.append(TDEGlobalSettings::fixedFont().family());
00834 fonts.append(TDEGlobalSettings::generalFont().family());
00835 fonts.append(TDEGlobalSettings::generalFont().family());
00836 fonts.append("0");
00837 }
00838 Settings::setFonts(fonts);
00839 if (Settings::standardFont().isEmpty())
00840 Settings::setStandardFont(fonts[0]);
00841 if (Settings::fixedFont().isEmpty())
00842 Settings::setFixedFont(fonts[1]);
00843 if (Settings::sansSerifFont().isEmpty())
00844 Settings::setSansSerifFont(fonts[2]);
00845 if (Settings::serifFont().isEmpty())
00846 Settings::setSerifFont(fonts[3]);
00847
00848 TDEConfig* conf = Settings::self()->config();
00849 conf->setGroup("HTML Settings");
00850
00851 TDEConfig konq("konquerorrc", true, false);
00852 konq.setGroup("HTML Settings");
00853
00854 if (!conf->hasKey("MinimumFontSize"))
00855 {
00856 int minfs;
00857 if (konq.hasKey("MinimumFontSize"))
00858 minfs = konq.readNumEntry("MinimumFontSize");
00859 else
00860 minfs = TDEGlobalSettings::generalFont().pointSize();
00861 kdDebug() << "Part::initFonts(): set MinimumFontSize to " << minfs << endl;
00862 Settings::setMinimumFontSize(minfs);
00863 }
00864
00865 if (!conf->hasKey("MediumFontSize"))
00866 {
00867 int medfs;
00868 if (konq.hasKey("MediumFontSize"))
00869 medfs = konq.readNumEntry("MediumFontSize");
00870 else
00871 medfs = TDEGlobalSettings::generalFont().pointSize();
00872 kdDebug() << "Part::initFonts(): set MediumFontSize to " << medfs << endl;
00873 Settings::setMediumFontSize(medfs);
00874 }
00875
00876 if (!conf->hasKey("UnderlineLinks"))
00877 {
00878 bool underline = true;
00879 if (konq.hasKey("UnderlineLinks"))
00880 underline = konq.readBoolEntry("UnderlineLinks");
00881
00882 kdDebug() << "Part::initFonts(): set UnderlineLinks to " << underline << endl;
00883 Settings::setUnderlineLinks(underline);
00884 }
00885
00886 if (!conf->hasKey("EnableFavicon"))
00887 {
00888 bool enableFavicon = true;
00889 if (konq.hasKey("EnableFavicon"))
00890 enableFavicon = konq.readBoolEntry("EnableFavicon");
00891
00892 kdDebug() << "Part::initFonts(): set EnableFavicon to " << enableFavicon << endl;
00893 Settings::setEnableFavIcon(enableFavicon);
00894 }
00895
00896 if (!conf->hasKey("AutoLoadImages"))
00897 {
00898 bool autoLoadImages = true;
00899 if (konq.hasKey("AutoLoadImages"))
00900 autoLoadImages = konq.readBoolEntry("AutoLoadImages");
00901
00902 kdDebug() << "Part::initFonts(): set AutoLoadImages to " << autoLoadImages << endl;
00903 Settings::setAutoLoadImages(autoLoadImages);
00904 }
00905
00906 }
00907
00908 bool Part::copyFile(const TQString& backup)
00909 {
00910 TQFile file(m_file);
00911
00912 if (file.open(IO_ReadOnly))
00913 {
00914 TQFile backupFile(backup);
00915 if (backupFile.open(IO_WriteOnly))
00916 {
00917 TQTextStream in(&file);
00918 TQTextStream out(&backupFile);
00919 while (!in.atEnd())
00920 out << in.readLine();
00921 backupFile.close();
00922 file.close();
00923 return true;
00924 }
00925 else
00926 {
00927 file.close();
00928 return false;
00929 }
00930 }
00931 return false;
00932 }
00933
00934 static TQString getMyHostName()
00935 {
00936 char hostNameC[256];
00937
00938 hostNameC[255] = 0;
00939
00940 if(gethostname(hostNameC, 255))
00941 hostNameC[0] = 0;
00942 return TQString::fromLocal8Bit(hostNameC);
00943 }
00944
00945
00946 bool Part::tryToLock(const TQString& backendName)
00947 {
00948
00949 TQString appName = kapp->instanceName();
00950 if ( appName.isEmpty() )
00951 appName = "akregator";
00952
00953 TQString programName;
00954 const TDEAboutData *about = kapp->aboutData();
00955 if ( about )
00956 programName = about->programName();
00957 if ( programName.isEmpty() )
00958 programName = i18n("Akregator");
00959
00960 TQString lockLocation = locateLocal("data", "akregator/lock");
00961 KSimpleConfig config(lockLocation);
00962 int oldPid = config.readNumEntry("pid", -1);
00963 const TQString oldHostName = config.readEntry("hostname");
00964 const TQString oldAppName = config.readEntry( "appName", appName );
00965 const TQString oldProgramName = config.readEntry( "programName", programName );
00966 const TQString hostName = getMyHostName();
00967 bool first_instance = false;
00968 if ( oldPid == -1 )
00969 first_instance = true;
00970
00971
00972
00973 else if (hostName == oldHostName && oldPid != getpid()) {
00974 if ( kill(oldPid, 0) == -1 )
00975 first_instance = ( errno == ESRCH );
00976 }
00977
00978 if ( !first_instance )
00979 {
00980 TQString msg;
00981 if ( oldHostName == hostName )
00982 {
00983
00984
00985
00986 if ( oldAppName == appName )
00987 msg = i18n("<qt>%1 already seems to be running on another display on "
00988 "this machine. <b>Running %2 more than once is not supported "
00989 "by the %3 backend and "
00990 "can cause the loss of archived articles and crashes at startup.</b> "
00991 "You should disable the archive for now "
00992 "unless you are sure that %2 is not already running.</qt>")
00993 .arg( programName, programName, backendName );
00994
00995
00996
00997
00998 else
00999 msg = i18n("<qt>%1 seems to be running on another display on this "
01000 "machine. <b>Running %1 and %2 at the same "
01001 "time is not supported by the %3 backend and can cause "
01002 "the loss of archived articles and crashes at startup.</b> "
01003 "You should disable the archive for now "
01004 "unless you are sure that %2 is not already running.</qt>")
01005 .arg( oldProgramName, programName, backendName );
01006 }
01007 else
01008 {
01009 if ( oldAppName == appName )
01010 msg = i18n("<qt>%1 already seems to be running on %2. <b>Running %1 more "
01011 "than once is not supported by the %3 backend and can cause "
01012 "the loss of archived articles and crashes at startup.</b> "
01013 "You should disable the archive for now "
01014 "unless you are sure that it is "
01015 "not already running on %2.</qt>")
01016 .arg( programName, oldHostName, backendName );
01017 else
01018 msg = i18n("<qt>%1 seems to be running on %3. <b>Running %1 and %2 at the "
01019 "same time is not supported by the %4 backend and can cause "
01020 "the loss of archived articles and crashes at startup.</b> "
01021 "You should disable the archive for now "
01022 "unless you are sure that %1 is "
01023 "not running on %3.</qt>")
01024 .arg( oldProgramName, programName, oldHostName, backendName );
01025 }
01026
01027 KCursorSaver idle( KBusyPtr::idle() );
01028 if ( KMessageBox::No ==
01029 KMessageBox::warningYesNo( 0, msg, TQString(),
01030 i18n("Force Access"),
01031 i18n("Disable Archive")) )
01032 {
01033 return false;
01034 }
01035 }
01036
01037 config.writeEntry("pid", getpid());
01038 config.writeEntry("hostname", hostName);
01039 config.writeEntry( "appName", appName );
01040 config.writeEntry( "programName", programName );
01041 config.sync();
01042 return true;
01043 }
01044
01045
01046 }
01047 #include "akregator_part.moc"