Fix variable name
[kdepim.git] / akregator / src / akregator_part.cpp
blobe758b09344cac7de0e37bc32fdb0ac0931d3c51d
1 /*
2 This file is part of Akregator.
4 Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
5 2005 Frank Osterfeld <osterfeld@kde.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 As a special exception, permission is given to link this program
22 with any edition of Qt, and distribute the resulting executable,
23 without including the source code for Qt in the source distribution.
26 #include "akregator_part.h"
27 #include "akregator_debug.h"
28 #include "config-akregator.h"
29 #include "messageviewer/messageviewersettings.h"
30 #include "akregatorconfig.h"
31 #include "aboutdata.h"
32 #include "actionmanagerimpl.h"
33 #include "article.h"
34 #include "fetchqueue.h"
35 #include "feedlist.h"
36 #include "framemanager.h"
37 #include "kernel.h"
38 #include "loadfeedlistcommand.h"
39 #include "mainwidget.h"
40 #include "notificationmanager.h"
41 #include "plugin.h"
42 #include "pluginmanager.h"
43 #include "storage.h"
44 #include "storagefactory.h"
45 #include "storagefactoryregistry.h"
46 #include "trayicon.h"
47 #include "widgets/akregatorcentralwidget.h"
48 #include "dummystorage/storagefactorydummyimpl.h"
49 #include "utils.h"
50 #include "akregator_options.h"
51 #include <Libkdepim/BroadcastStatus>
52 #include "akregator-version.h"
53 #include <kio/filecopyjob.h>
54 #include <knotifyconfigwidget.h>
55 #include <kaboutdata.h>
56 #include <kconfig.h>
57 #include <kconfigdialog.h>
58 #include <qfiledialog.h>
59 #include <kmessagebox.h>
61 #include <QTemporaryFile>
62 #include <QWebEngineSettings>
63 #include <QSaveFile>
64 #include <kservice.h>
65 #include <kxmlguifactory.h>
66 #include <KIO/StoredTransferJob>
67 #include <KJobWidgets>
68 #include <KPluginFactory>
69 #include <KParts/Plugin>
70 #include <KCMultiDialog>
71 #include <kstandardaction.h>
73 #include <QApplication>
74 #include <QFile>
75 #include <QObject>
76 #include <QStringList>
77 #include <QTextStream>
78 #include <QTimer>
79 #include <QWidget>
80 #include <QDomDocument>
81 #include "akregratormigrateapplication.h"
82 #include "partadaptor.h"
84 #include <memory>
85 #include <QFontDatabase>
86 #include <QStandardPaths>
88 namespace
91 static QDomDocument createDefaultFeedList()
93 QDomDocument doc;
94 QDomProcessingInstruction z = doc.createProcessingInstruction(QStringLiteral("xml"), QStringLiteral("version=\"1.0\" encoding=\"UTF-8\""));
95 doc.appendChild(z);
97 QDomElement root = doc.createElement(QStringLiteral("opml"));
98 root.setAttribute(QStringLiteral("version"), QStringLiteral("1.0"));
99 doc.appendChild(root);
101 QDomElement head = doc.createElement(QStringLiteral("head"));
102 root.appendChild(head);
104 QDomElement text = doc.createElement(QStringLiteral("text"));
105 text.appendChild(doc.createTextNode(i18n("Feeds")));
106 head.appendChild(text);
108 QDomElement body = doc.createElement(QStringLiteral("body"));
109 root.appendChild(body);
111 QDomElement mainFolder = doc.createElement(QStringLiteral("outline"));
112 mainFolder.setAttribute(QStringLiteral("text"), QStringLiteral("KDE"));
113 body.appendChild(mainFolder);
115 QDomElement dot = doc.createElement(QStringLiteral("outline"));
116 dot.setAttribute(QStringLiteral("text"), i18n("KDE Dot News"));
117 dot.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://www.kde.org/dotkdeorg.rdf"));
118 mainFolder.appendChild(dot);
120 QDomElement linuxFeeds = doc.createElement(QStringLiteral("outline"));
121 linuxFeeds.setAttribute(QStringLiteral("text"), i18n("Linux.com"));
122 linuxFeeds.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("https://www.linux.com/rss/feeds.php"));
123 mainFolder.appendChild(linuxFeeds);
125 QDomElement planetkde = doc.createElement(QStringLiteral("outline"));
126 planetkde.setAttribute(QStringLiteral("text"), i18n("Planet KDE"));
127 planetkde.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://planetkde.org/rss20.xml"));
128 mainFolder.appendChild(planetkde);
130 QDomElement planetkdepim = doc.createElement(QStringLiteral("outline"));
131 planetkdepim.setAttribute(QStringLiteral("text"), i18n("Planet KDE PIM"));
132 planetkdepim.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://pim.planetkde.org/rss20.xml"));
133 mainFolder.appendChild(planetkdepim);
135 QDomElement apps = doc.createElement(QStringLiteral("outline"));
136 apps.setAttribute(QStringLiteral("text"), i18n("KDE Apps"));
137 apps.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://www.kde.org/dot/kde-apps-content.rdf"));
138 mainFolder.appendChild(apps);
140 QDomElement look = doc.createElement(QStringLiteral("outline"));
141 look.setAttribute(QStringLiteral("text"), i18n("KDE Look"));
142 look.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://www.kde.org/kde-look-content.rdf"));
143 mainFolder.appendChild(look);
145 #if 0
146 // hungarian feed(s)
147 QDomElement hungarianFolder = doc.createElement(QStringLiteral("outline"));
148 hungarianFolder.setAttribute(QStringLiteral("text"), i18n("Hungarian feeds"));
149 mainFolder.appendChild(hungarianFolder);
151 QDomElement hungarianKde = doc.createElement(QStringLiteral("outline"));
152 hungarianKde.setAttribute(QStringLiteral("text"), i18n("KDE.HU"));
153 hungarianKde.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://kde.hu/rss.xml"));
154 hungarianFolder.appendChild(hungarianKde);
155 #endif
156 // Brazilian Portuguese feeds
157 QDomElement portugueuseFolder = doc.createElement(QStringLiteral("outline"));
158 portugueuseFolder.setAttribute(QStringLiteral("text"), i18n("Brazilian Portuguese feeds"));
159 mainFolder.appendChild(portugueuseFolder);
161 QDomElement portugueuseKde = doc.createElement(QStringLiteral("outline"));
162 portugueuseKde.setAttribute(QStringLiteral("text"), i18n("Planet KDE Brazilian Portuguese"));
163 portugueuseKde.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://planetkde.org/pt-br/rss20.xml"));
164 portugueuseFolder.appendChild(portugueuseKde);
166 // spanish feed(s)
167 QDomElement spanishFolder = doc.createElement(QStringLiteral("outline"));
168 spanishFolder.setAttribute(QStringLiteral("text"), i18n("Spanish feeds"));
169 mainFolder.appendChild(spanishFolder);
171 QDomElement spanishKde = doc.createElement(QStringLiteral("outline"));
172 spanishKde.setAttribute(QStringLiteral("text"), i18n("Planet KDE EspaƱa"));
173 spanishKde.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("http://planet.kde-espana.org/atom.xml"));
174 spanishFolder.appendChild(spanishKde);
176 // french feed(s)
177 QDomElement frenchFolder = doc.createElement(QStringLiteral("outline"));
178 frenchFolder.setAttribute(QStringLiteral("text"), i18n("French feeds"));
179 mainFolder.appendChild(frenchFolder);
181 QDomElement frenchKde = doc.createElement(QStringLiteral("outline"));
182 frenchKde.setAttribute(QStringLiteral("text"), i18n("Planet KDE France"));
183 frenchKde.setAttribute(QStringLiteral("xmlUrl"), QStringLiteral("https://fr.planetkde.org/rss20.xml"));
184 frenchFolder.appendChild(frenchKde);
186 return doc;
190 namespace Akregator
193 K_PLUGIN_FACTORY(AkregatorFactory, registerPlugin<Part>();)
195 static Part *mySelf = Q_NULLPTR;
196 BrowserExtension::BrowserExtension(Part *p, const char *name)
197 : KParts::BrowserExtension(p)
199 AkregratorMigrateApplication migrate;
200 migrate.migrate();
201 setObjectName(QLatin1String(name));
202 m_part = p;
205 void BrowserExtension::saveSettings()
207 m_part->saveSettings();
210 Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList &)
211 : KParts::ReadOnlyPart(parent)
212 , m_standardListLoaded(false)
213 , m_shuttingDown(false)
214 , m_doCrashSave(false)
215 , m_backedUpList(false)
216 , m_mainWidget(0)
217 , m_storage(0)
218 , m_dialog(0)
221 mySelf = this;
222 //Make sure to initialize settings
223 Part::config();
224 initFonts();
226 setPluginLoadingMode(LoadPluginsIfEnabled);
227 setPluginInterfaceVersion(AKREGATOR_PLUGIN_INTERFACE_VERSION);
229 setComponentName(QStringLiteral("akregator"), QStringLiteral("akregator"));
230 setXMLFile(QStringLiteral("akregator_part.rc"), true);
232 new PartAdaptor(this);
233 QDBusConnection::sessionBus().registerObject(QStringLiteral("/Akregator"), this);
235 m_standardFeedList = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/akregator/data/feeds.opml");
236 QFileInfo fileInfo(m_standardFeedList);
237 QDir().mkpath(fileInfo.absolutePath());
239 Backend::StorageFactoryDummyImpl *dummyFactory = new Backend::StorageFactoryDummyImpl();
240 if (!Backend::StorageFactoryRegistry::self()->registerFactory(dummyFactory, dummyFactory->key())) {
241 // There was already a dummy factory registered.
242 delete dummyFactory;
244 loadPlugins(QStringLiteral("storage")); // FIXME: also unload them!
246 m_storage = 0;
247 Backend::StorageFactory *storageFactory = Backend::StorageFactoryRegistry::self()->getFactory(Settings::archiveBackend());
248 if (storageFactory != 0) {
249 m_storage = storageFactory->createStorage(QStringList());
252 if (!m_storage) { // Houston, we have a problem
253 m_storage = Backend::StorageFactoryRegistry::self()->getFactory(QStringLiteral("dummy"))->createStorage(QStringList());
255 KMessageBox::error(parentWidget, i18n("Unable to load storage backend plugin \"%1\". No feeds are archived.", Settings::archiveBackend()), i18n("Plugin error"));
258 m_storage->open(true);
259 Kernel::self()->setStorage(m_storage);
261 m_actionManager = new ActionManagerImpl(this);
262 ActionManager::setInstance(m_actionManager);
264 mCentralWidget = new Akregator::AkregatorCentralWidget(parentWidget);
265 connect(mCentralWidget, &AkregatorCentralWidget::restoreSession, this, &Part::slotRestoreSession);
266 m_mainWidget = new Akregator::MainWidget(this, parentWidget, m_actionManager, "akregator_view");
267 mCentralWidget->setMainWidget(m_mainWidget);
268 m_extension = new BrowserExtension(this, "ak_extension");
270 connect(Kernel::self()->frameManager(), &FrameManager::signalCaptionChanged, this, &Part::setWindowCaption);
271 connect(Kernel::self()->frameManager(), &FrameManager::signalStatusText, this, &Part::slotSetStatusText);
272 connect(Kernel::self()->frameManager(), &FrameManager::signalLoadingProgress, m_extension, &BrowserExtension::loadingProgress);
273 connect(Kernel::self()->frameManager(), &FrameManager::signalCanceled, this, &ReadOnlyPart::canceled);
274 connect(Kernel::self()->frameManager(), &FrameManager::signalStarted, this, &Part::slotStarted);
275 connect(Kernel::self()->frameManager(), SIGNAL(signalCompleted()), this, SIGNAL(completed()));
277 // notify the part that this is our internal widget
278 setWidget(mCentralWidget);
280 if (Settings::showTrayIcon() && !TrayIcon::getInstance()) {
281 TrayIcon *trayIcon = new TrayIcon(m_mainWidget->window());
282 TrayIcon::setInstance(trayIcon);
283 m_actionManager->setTrayIcon(trayIcon);
285 if (isTrayIconEnabled()) {
286 trayIcon->setStatus(KStatusNotifierItem::Active);
289 QWidget *const notificationParent = isTrayIconEnabled() ? m_mainWidget->window() : Q_NULLPTR;
290 NotificationManager::self()->setWidget(notificationParent, componentData().componentName());
292 connect(m_mainWidget.data(), &MainWidget::signalUnreadCountChanged, trayIcon, &TrayIcon::slotSetUnread);
293 connect(m_mainWidget.data(), &MainWidget::signalArticlesSelected,
294 this, &Part::signalArticlesSelected);
297 connect(qApp, &QCoreApplication::aboutToQuit, this, &Part::slotOnShutdown);
299 m_autosaveTimer = new QTimer(this);
300 connect(m_autosaveTimer, &QTimer::timeout, this, &Part::slotSaveFeedList);
301 m_autosaveTimer->start(5 * 60 * 1000); // 5 minutes
303 QString useragent = QStringLiteral("Akregator/%1; syndication").arg(QStringLiteral(AKREGATOR_VERSION));
305 if (!Settings::customUserAgent().isEmpty()) {
306 useragent = Settings::customUserAgent();
309 Syndication::FileRetriever::setUserAgent(useragent);
311 loadPlugins(QStringLiteral("extension")); // FIXME: also unload them!
312 if (mCentralWidget->previousSessionCrashed()) {
313 mCentralWidget->needToRestoreCrashedSession();
314 } else {
315 m_doCrashSave = true;
316 autoReadProperties();
320 KSharedConfig::Ptr Part::config()
322 assert(mySelf);
323 if (!mySelf->mConfig) {
324 mySelf->mConfig = KSharedConfig::openConfig(QStringLiteral("akregatorrc"));
325 MessageViewer::MessageViewerSettings::self()->setSharedConfig(mySelf->mConfig);
326 MessageViewer::MessageViewerSettings::self()->load();
328 return mySelf->mConfig;
331 void Part::updateQuickSearchLineText()
333 if (m_mainWidget) {
334 m_mainWidget->updateQuickSearchLineText();
338 void Part::loadPlugins(const QString &type)
340 const KService::List offers = PluginManager::query(QStringLiteral("[X-KDE-akregator-plugintype] == '%1'").arg(type));
342 Q_FOREACH (const KService::Ptr &i, offers) {
343 Akregator::Plugin *plugin = PluginManager::createFromService(i, this);
344 if (!plugin) {
345 continue;
347 plugin->initialize();
348 plugin->insertGuiClients(this);
352 void Part::slotStarted()
354 Q_EMIT started(Q_NULLPTR);
357 void Part::slotOnShutdown()
359 autoSaveProperties();
360 m_shuttingDown = true;
361 m_autosaveTimer->stop();
362 if (m_mainWidget) {
363 saveSettings();
364 slotSaveFeedList();
365 m_mainWidget->slotOnShutdown();
367 //delete m_mainWidget;
368 delete TrayIcon::getInstance();
369 TrayIcon::setInstance(Q_NULLPTR);
370 delete m_storage;
371 m_storage = 0;
372 //delete m_actionManager;
375 void Part::slotSettingsChanged()
377 NotificationManager::self()->setWidget(isTrayIconEnabled() ? m_mainWidget->window() : 0, componentData().componentName());
379 if (Settings::showTrayIcon() && !TrayIcon::getInstance()) {
380 TrayIcon *trayIcon = new TrayIcon(m_mainWidget->window());
381 TrayIcon::setInstance(trayIcon);
382 m_actionManager->setTrayIcon(trayIcon);
384 if (isTrayIconEnabled()) {
385 trayIcon->setStatus(KStatusNotifierItem::Active);
388 connect(m_mainWidget.data(), &MainWidget::signalUnreadCountChanged, trayIcon, &TrayIcon::slotSetUnread);
389 connect(m_mainWidget.data(), &MainWidget::signalArticlesSelected,
390 this, &Part::signalArticlesSelected);
392 m_mainWidget->slotSetTotalUnread();
394 if (!Settings::showTrayIcon()) {
395 TrayIcon::getInstance()->disconnect();
396 delete TrayIcon::getInstance();
397 TrayIcon::setInstance(0);
398 m_actionManager->setTrayIcon(0);
401 Syndication::FileRetriever::setUseCache(Settings::useHTMLCache());
403 QStringList fonts;
404 fonts.append(Settings::standardFont());
405 fonts.append(Settings::fixedFont());
406 fonts.append(Settings::sansSerifFont());
407 fonts.append(Settings::serifFont());
408 fonts.append(Settings::standardFont());
409 fonts.append(Settings::standardFont());
410 fonts.append(QStringLiteral("0"));
411 Settings::setFonts(fonts);
413 if (Settings::minimumFontSize() > Settings::mediumFontSize()) {
414 Settings::setMediumFontSize(Settings::minimumFontSize());
416 saveSettings();
417 Q_EMIT signalSettingsChanged();
420 void Part::slotSetStatusText(const QString &statusText)
422 KPIM::BroadcastStatus::instance()->setStatusMsg(statusText);
425 void Part::saveSettings()
427 m_mainWidget->saveSettings();
430 Part::~Part()
432 disconnect(qApp, &QCoreApplication::aboutToQuit, this, &Part::slotOnShutdown);
433 qCDebug(AKREGATOR_LOG) << "Part::~Part() enter";
434 // If the widget is destroyed for some reason, KParts::Part will set its
435 // widget property to 0 and then delete itself (and therefore this object).
436 // In this case, it's not safe to do our normal shutdown routine.
437 if (widget() && !m_shuttingDown) {
438 slotOnShutdown();
440 qCDebug(AKREGATOR_LOG) << "Part::~Part(): leaving";
443 void Part::readProperties(const KConfigGroup &config)
445 m_backedUpList = false;
446 openStandardFeedList();
448 if (m_mainWidget) {
449 m_mainWidget->readProperties(config);
453 void Part::saveProperties(KConfigGroup &config)
455 if (m_mainWidget) {
456 slotSaveFeedList();
457 m_mainWidget->saveProperties(config);
461 bool Part::openUrl(const QUrl &url)
463 setLocalFilePath(url.toLocalFile());
464 return openFile();
467 void Part::openStandardFeedList()
469 if (!m_standardFeedList.isEmpty()) {
470 openUrl(QUrl::fromLocalFile(m_standardFeedList));
474 bool Part::openFile()
476 if (m_loadFeedListCommand || m_standardListLoaded) {
477 return true;
479 QScopedPointer<LoadFeedListCommand> cmd(new LoadFeedListCommand(m_mainWidget));
480 cmd->setParentWidget(m_mainWidget);
481 cmd->setStorage(Kernel::self()->storage());
482 cmd->setFileName(localFilePath());
483 cmd->setDefaultFeedList(createDefaultFeedList());
484 connect(cmd.data(), &LoadFeedListCommand::result,
485 this, &Part::feedListLoaded);
486 m_loadFeedListCommand = cmd.take();
487 m_loadFeedListCommand->start();
488 return true;
491 bool Part::writeToTextFile(const QString &data, const QString &filename) const
493 QSaveFile file(filename);
494 if (!file.open(QIODevice::WriteOnly)) {
495 return false;
497 QTextStream stream(&file);
498 stream.setCodec("UTF-8");
499 stream << data << endl;
500 return file.commit();
503 void Part::feedListLoaded(const QSharedPointer<FeedList> &list)
505 Q_ASSERT(!m_standardListLoaded);
506 m_mainWidget->setFeedList(list);
507 m_standardListLoaded = list != 0;
509 if (Settings::markAllFeedsReadOnStartup()) {
510 m_mainWidget->slotMarkAllFeedsRead();
513 if (m_standardListLoaded) {
514 QTimer::singleShot(0, this, &Part::flushAddFeedRequests);
517 if (Settings::fetchOnStartup()) {
518 m_mainWidget->slotFetchAllFeeds();
522 void Part::flushAddFeedRequests()
524 Q_FOREACH (const AddFeedRequest &i, m_requests) {
525 Q_FOREACH (const QString &j, i.urls) {
526 m_mainWidget->addFeedToGroup(j, i.group);
528 NotificationManager::self()->slotNotifyFeeds(i.urls);
530 m_requests.clear();
533 void Part::slotSaveFeedList()
535 // don't save to the standard feed list, when it wasn't completely loaded before
536 if (!m_standardListLoaded) {
537 return;
540 // the first time we overwrite the feed list, we create a backup
541 if (!m_backedUpList) {
542 const QString backup = localFilePath() + QStringLiteral("~");
543 if (QFile::copy(localFilePath(), backup)) {
544 m_backedUpList = true;
548 const QString xml = m_mainWidget->feedListToOPML().toString();
549 m_storage->storeFeedList(xml);
550 if (writeToTextFile(xml, localFilePath())) {
551 return;
554 KMessageBox::error(m_mainWidget,
555 i18n("Access denied: Cannot save feed list to <b>%1</b>. Please check your permissions.", localFilePath()),
556 i18n("Write Error"));
559 bool Part::isTrayIconEnabled() const
561 return Settings::showTrayIcon();
564 void Part::importFile(const QUrl &url)
566 QString filename;
567 QTemporaryFile tempFile;
569 if (url.isLocalFile()) {
570 filename = url.toLocalFile();
571 } else {
572 if (!tempFile.open()) {
573 return;
575 filename = tempFile.fileName();
577 auto job = KIO::file_copy(url, QUrl::fromLocalFile(filename), -1, KIO::Overwrite | KIO::HideProgressInfo);
578 KJobWidgets::setWindow(job, m_mainWidget);
579 if (!job->exec()) {
580 KMessageBox::error(m_mainWidget, job->errorString());
581 return;
585 QFile file(filename);
586 if (file.open(QIODevice::ReadOnly)) {
587 // Read OPML feeds list and build QDom tree.
588 QDomDocument doc;
589 if (doc.setContent(file.readAll())) {
590 m_mainWidget->importFeedList(doc);
591 } else {
592 KMessageBox::error(m_mainWidget, i18n("Could not import the file %1 (no valid OPML)", filename), i18n("OPML Parsing Error"));
594 } else {
595 KMessageBox::error(m_mainWidget, i18n("The file %1 could not be read, check if it exists or if it is readable for the current user.", filename), i18n("Read Error"));
599 void Part::exportFile(const QUrl &url)
601 if (url.isLocalFile()) {
602 const QString fname = url.toLocalFile();
604 if (QFile::exists(fname) &&
605 KMessageBox::questionYesNo(m_mainWidget,
606 i18n("The file %1 already exists; do you want to overwrite it?", fname),
607 i18n("Export"),
608 KStandardGuiItem::overwrite(),
609 KStandardGuiItem::cancel()) == KMessageBox::No) {
610 return;
613 if (!writeToTextFile(m_mainWidget->feedListToOPML().toString(), fname)) {
614 KMessageBox::error(m_mainWidget, i18n("Access denied: cannot write to file %1. Please check your permissions.", fname), i18n("Write Error"));
617 return;
618 } else {
619 auto job = KIO::storedPut(m_mainWidget->feedListToOPML().toString().toUtf8(), url, -1);
620 KJobWidgets::setWindow(job, m_mainWidget);
621 if (!job->exec()) {
622 KMessageBox::error(m_mainWidget, job->errorString());
627 void Part::fileImport()
629 const QString filters = i18n("OPML Outlines (*.opml *.xml);;All Files (*)");
630 const QUrl url = QFileDialog::getOpenFileUrl(m_mainWidget, QString(), QUrl(), filters);
631 if (!url.isEmpty()) {
632 importFile(url);
636 void Part::fileExport()
638 const QString filters = i18n("OPML Outlines (*.opml *.xml);;All Files (*)");
639 const QUrl url = QFileDialog::getSaveFileUrl(m_mainWidget, QString(), QUrl(), filters);
641 if (!url.isEmpty()) {
642 exportFile(url);
646 void Part::fetchAllFeeds()
648 m_mainWidget->slotFetchAllFeeds();
651 void Part::fetchFeedUrl(const QString &s)
653 qCDebug(AKREGATOR_LOG) << "fetchFeedURL==" << s;
656 void Part::addFeedsToGroup(const QStringList &urls, const QString &group)
658 AddFeedRequest req;
659 req.group = group;
660 req.urls = urls;
661 m_requests.append(req);
662 if (m_standardListLoaded) {
663 flushAddFeedRequests();
667 void Part::addFeed()
669 m_mainWidget->slotFeedAdd();
672 void Part::showNotificationOptions()
674 const Akregator::AboutData about;
675 KNotifyConfigWidget::configure(m_mainWidget, about.productName());
678 void Part::showOptions()
680 saveSettings();
682 if (!m_dialog) {
683 m_dialog = new KCMultiDialog(m_mainWidget);
684 connect(m_dialog, SIGNAL(configCommitted()),
685 this, SLOT(slotSettingsChanged()));
686 connect(m_dialog, SIGNAL(configCommitted()),
687 TrayIcon::getInstance(), SLOT(settingsChanged()));
689 m_dialog->addModule(QStringLiteral("akregator_config_general"));
690 m_dialog->addModule(QStringLiteral("akregator_config_appearance"));
691 m_dialog->addModule(QStringLiteral("akregator_config_archive"));
692 m_dialog->addModule(QStringLiteral("akregator_config_browser"));
693 m_dialog->addModule(QStringLiteral("akregator_config_advanced"));
694 m_dialog->addModule(QStringLiteral("akregator_config_webengineurlinterceptor"));
697 m_dialog->show();
698 m_dialog->raise();
701 void Part::initFonts()
703 QStringList fonts = Settings::fonts();
704 if (fonts.isEmpty()) {
705 fonts.append(QFontDatabase::systemFont(QFontDatabase::GeneralFont).family());
706 fonts.append(QFontDatabase::systemFont(QFontDatabase::FixedFont).family());
707 fonts.append(QFontDatabase::systemFont(QFontDatabase::GeneralFont).family());
708 fonts.append(QFontDatabase::systemFont(QFontDatabase::GeneralFont).family());
709 fonts.append(QStringLiteral("0"));
711 Settings::setFonts(fonts);
712 if (Settings::standardFont().isEmpty()) {
713 Settings::setStandardFont(fonts[0]);
715 if (Settings::fixedFont().isEmpty()) {
716 Settings::setFixedFont(fonts[1]);
718 if (Settings::sansSerifFont().isEmpty()) {
719 Settings::setSansSerifFont(fonts[2]);
721 if (Settings::serifFont().isEmpty()) {
722 Settings::setSerifFont(fonts[3]);
725 //TODO add CursiveFont, FantasyFont
727 KConfigGroup conf(Settings::self()->config(), "HTML Settings");
729 KConfig _konq(QStringLiteral("konquerorrc"), KConfig::NoGlobals);
730 KConfigGroup konq(&_konq, "HTML Settings");
732 if (!conf.hasKey("MinimumFontSize")) {
733 int minfs;
734 if (konq.hasKey("MinimumFontSize")) {
735 minfs = konq.readEntry("MinimumFontSize", 8);
736 } else {
737 minfs = std::max(QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize() - 2, 4);
739 Settings::setMinimumFontSize(minfs);
742 if (!conf.hasKey("MediumFontSize")) {
743 int medfs;
744 if (konq.hasKey("MediumFontSize")) {
745 medfs = konq.readEntry("MediumFontSize", 12);
746 } else {
747 medfs = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize();
749 Settings::setMediumFontSize(medfs);
751 QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::StandardFont, Settings::standardFont());
752 QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::FixedFont, Settings::fixedFont());
753 QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::SerifFont, Settings::serifFont());
754 QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::SansSerifFont, Settings::sansSerifFont());
755 QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::MinimumFontSize, Settings::minimumFontSize());
756 QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::DefaultFontSize, Settings::mediumFontSize());
759 bool Part::handleCommandLine(const QStringList &args)
761 QCommandLineParser parser;
762 akregator_options(&parser);
763 parser.process(args);
765 const QString addFeedGroup = parser.isSet(QStringLiteral("group"))
766 ? parser.value(QStringLiteral("group"))
767 : i18n("Imported Folder");
769 QStringList feedsToAdd = parser.values(QStringLiteral("addfeed"));
771 if (feedsToAdd.isEmpty() && !parser.positionalArguments().isEmpty()) {
772 Q_FOREACH (const QString &url, parser.positionalArguments()) {
773 feedsToAdd.append(url);
777 if (!feedsToAdd.isEmpty()) {
778 addFeedsToGroup(feedsToAdd, addFeedGroup);
780 return true;
783 void Part::clearCrashProperties()
785 if (!m_doCrashSave) {
786 return;
788 KConfig config(QStringLiteral("crashed"), KConfig::SimpleConfig,
789 QStandardPaths::AppDataLocation);
790 KConfigGroup configGroup(&config, "Part");
791 configGroup.writeEntry("crashed", false);
794 void Part::saveCrashProperties()
796 if (!m_doCrashSave) {
797 return;
799 KConfig config(QStringLiteral("crashed"), KConfig::SimpleConfig,
800 QStandardPaths::AppDataLocation);
801 KConfigGroup configGroup(&config, "Part");
802 configGroup.deleteGroup();
804 configGroup.writeEntry("crashed", true);
806 saveProperties(configGroup);
809 void Part::slotAutoSave()
811 saveCrashProperties();
814 void Part::autoSaveProperties()
816 KConfig config(QStringLiteral("autosaved"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation);
817 KConfigGroup configGroup(&config, "Part");
818 configGroup.deleteGroup();
820 saveProperties(configGroup);
822 clearCrashProperties();
825 void Part::autoReadProperties()
827 if (qGuiApp->isSessionRestored()) {
828 return;
830 KConfig config(QStringLiteral("autosaved"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation);
831 KConfigGroup configGroup(&config, "Part");
833 readProperties(configGroup);
836 void Part::slotRestoreSession(Akregator::CrashWidget::CrashAction type)
838 switch (type) {
839 case Akregator::CrashWidget::RestoreSession: {
840 KConfig config(QStringLiteral("crashed"), KConfig::SimpleConfig,
841 QStandardPaths::AppDataLocation);
842 KConfigGroup configGroup(&config, "Part");
843 readProperties(configGroup);
844 clearCrashProperties();
845 break;
847 case Akregator::CrashWidget::NotRestoreSession:
848 clearCrashProperties();
849 break;
850 case Akregator::CrashWidget::AskMeLater:
851 break;
853 m_doCrashSave = true;
856 } // namespace Akregator
857 #include "akregator_part.moc"