46 #include <libkdepim/misc/broadcaststatus.h>
47 #include "kdepim-version.h"
49 #include <KActionCollection>
50 #include <knotifyconfigwidget.h>
51 #include <kaboutdata.h>
52 #include <kapplication.h>
53 #include <KCmdLineArgs>
55 #include <kconfigdialog.h>
56 #include <kfiledialog.h>
57 #include <kglobalsettings.h>
58 #include <kmessagebox.h>
59 #include <kstandarddirs.h>
60 #include <ktemporaryfile.h>
63 #include <kxmlguifactory.h>
64 #include <kio/netaccess.h>
65 #include <KPluginFactory>
66 #include <KParts/Plugin>
67 #include <KCMultiDialog>
68 #include <kstandardaction.h>
72 #include <QStringList>
73 #include <QTextStream>
76 #include <QDomDocument>
77 #include "partadaptor.h"
81 using namespace boost;
85 static QDomDocument createDefaultFeedList() {
87 QDomProcessingInstruction z = doc.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\"");
90 QDomElement root = doc.createElement(
"opml" );
91 root.setAttribute(
"version",
"1.0");
92 doc.appendChild( root );
94 QDomElement head = doc.createElement(
"head" );
95 root.appendChild(head);
97 QDomElement text = doc.createElement(
"text" );
98 text.appendChild(doc.createTextNode(i18n(
"Feeds")));
99 head.appendChild(text);
101 QDomElement body = doc.createElement(
"body" );
102 root.appendChild(body);
104 QDomElement mainFolder = doc.createElement(
"outline" );
105 mainFolder.setAttribute(
"text",
"KDE");
106 body.appendChild(mainFolder);
124 QDomElement dot = doc.createElement(
"outline" );
125 dot.setAttribute(
"text",i18n(
"KDE Dot News"));
126 dot.setAttribute(
"xmlUrl",
"http://www.kde.org/dotkdeorg.rdf");
127 mainFolder.appendChild(dot);
129 QDomElement linuxFeeds = doc.createElement(
"outline" );
130 linuxFeeds.setAttribute(
"text",i18n(
"Linux.com"));
131 linuxFeeds.setAttribute(
"xmlUrl",
"https://www.linux.com/rss/feeds.php");
132 mainFolder.appendChild(linuxFeeds);
134 QDomElement planetkde = doc.createElement(
"outline" );
135 planetkde.setAttribute(
"text",i18n(
"Planet KDE"));
136 planetkde.setAttribute(
"xmlUrl",
"http://planetkde.org/rss20.xml");
137 mainFolder.appendChild(planetkde);
139 QDomElement planetkdepim = doc.createElement(
"outline" );
140 planetkdepim.setAttribute(
"text",i18n(
"Planet KDE PIM"));
141 planetkdepim.setAttribute(
"xmlUrl",
"http://pim.planetkde.org/rss20.xml");
142 mainFolder.appendChild(planetkdepim);
144 QDomElement apps = doc.createElement(
"outline" );
145 apps.setAttribute(
"text",i18n(
"KDE Apps"));
146 apps.setAttribute(
"xmlUrl",
"http://www.kde.org/dot/kde-apps-content.rdf");
147 mainFolder.appendChild(apps);
149 QDomElement look = doc.createElement(
"outline" );
150 look.setAttribute(
"text",i18n(
"KDE Look"));
151 look.setAttribute(
"xmlUrl",
"http://www.kde.org/kde-look-content.rdf");
152 mainFolder.appendChild(look);
155 QDomElement hungarianFolder = doc.createElement(
"outline" );
156 hungarianFolder.setAttribute(
"text",i18n(
"Hungarian feeds"));
157 mainFolder.appendChild(hungarianFolder);
159 QDomElement hungarianKde = doc.createElement(
"outline" );
160 hungarianKde.setAttribute(
"text",i18n(
"KDE.HU"));
161 hungarianKde.setAttribute(
"xmlUrl",
"http://kde.hu/rss.xml");
162 hungarianFolder.appendChild(hungarianKde);
165 QDomElement spanishFolder = doc.createElement(
"outline" );
166 spanishFolder.setAttribute(
"text",i18n(
"Spanish feeds"));
167 mainFolder.appendChild(spanishFolder);
169 QDomElement spanishKde = doc.createElement(
"outline" );
170 spanishKde.setAttribute(
"text",i18n(
"Planet KDE EspaƱa"));
171 spanishKde.setAttribute(
"xmlUrl",
"http://planet.kde-espana.es/");
172 spanishFolder.appendChild(spanishKde);
178 namespace Akregator {
186 K_PLUGIN_FACTORY(AkregatorFactory, registerPlugin<Part>();)
189 BrowserExtension::BrowserExtension(
Part *p,
const char *name)
196 void BrowserExtension::saveSettings()
203 , m_standardListLoaded(false)
204 , m_shuttingDown(false)
205 , m_doCrashSave(true)
206 , m_backedUpList(false)
214 setPluginLoadingMode( LoadPluginsIfEnabled );
217 setComponentData( AkregatorFactory::componentData() );
218 setXMLFile(
"akregator_part.rc",
true);
220 new PartAdaptor(
this );
221 QDBusConnection::sessionBus().registerObject(
"/Akregator",
this);
226 m_standardFeedList = KGlobal::dirs()->saveLocation(
"data",
"akregator/data") +
"/feeds.opml";
233 loadPlugins( QLatin1String(
"storage") );
237 if (storageFactory != 0)
244 KMessageBox::error(parentWidget, i18n(
"Unable to load storage backend plugin \"%1\". No feeds are archived.",
Settings::archiveBackend()), i18n(
"Plugin error") );
247 m_storage->
open(
true);
256 connect(
Kernel::self()->frameManager(), SIGNAL(signalCaptionChanged(QString)),
this, SIGNAL(setWindowCaption(QString)));
257 connect(
Kernel::self()->frameManager(), SIGNAL(signalStatusText(QString)),
this, SLOT(slotSetStatusText(QString)));
258 connect(
Kernel::self()->frameManager(), SIGNAL(signalLoadingProgress(
int)), m_extension, SIGNAL(loadingProgress(
int)));
259 connect(
Kernel::self()->frameManager(), SIGNAL(signalCanceled(QString)),
this, SIGNAL(canceled(QString)));
260 connect(
Kernel::self()->frameManager(), SIGNAL(signalStarted()),
this, SLOT(slotStarted()));
261 connect(
Kernel::self()->frameManager(), SIGNAL(signalCompleted()),
this, SIGNAL(completed()));
264 setWidget(m_mainWidget);
272 if ( isTrayIconEnabled() )
273 trayIcon->setStatus( KStatusNotifierItem::Active );
275 QWidget*
const notificationParent = isTrayIconEnabled() ? m_mainWidget->window() : 0;
278 connect( m_mainWidget, SIGNAL(signalUnreadCountChanged(
int)), trayIcon, SLOT(slotSetUnread(
int)) );
283 connect(kapp, SIGNAL(aboutToQuit()),
this, SLOT(slotOnShutdown()));
285 m_autosaveTimer =
new QTimer(
this);
286 connect(m_autosaveTimer, SIGNAL(timeout()),
this, SLOT(
slotSaveFeedList()));
287 m_autosaveTimer->start(5*60*1000);
289 QString useragent = QString(
"Akregator/%1; syndication" ).arg( KDEPIM_VERSION );
294 Syndication::FileRetriever::setUserAgent( useragent );
296 loadPlugins( QLatin1String(
"extension") );
298 if (!readCrashProperties())
299 autoReadProperties();
302 void Part::loadPlugins(
const QString& type )
304 const KService::List offers =
PluginManager::query( QString::fromLatin1(
"[X-KDE-akregator-plugintype] == '%1'").arg( type ) );
306 Q_FOREACH (
const KService::Ptr& i, offers ) {
315 void Part::slotStarted()
320 void Part::slotOnShutdown()
322 autoSaveProperties();
323 m_shuttingDown =
true;
324 m_autosaveTimer->stop();
336 void Part::slotSettingsChanged()
342 TrayIcon* trayIcon =
new TrayIcon( m_mainWidget->window() );
346 if ( isTrayIconEnabled() )
347 trayIcon->setStatus( KStatusNotifierItem::Active );
349 connect( m_mainWidget, SIGNAL(signalUnreadCountChanged(
int)), trayIcon, SLOT(slotSetUnread(
int)) );
381 void Part::slotSetStatusText(
const QString& statusText )
383 KPIM::BroadcastStatus::instance()->setStatusMsg( statusText );
393 kDebug() <<
"Part::~Part() enter";
397 kDebug() <<
"Part::~Part(): leaving";
402 m_backedUpList =
false;
420 setLocalFilePath(url.toLocalFile());
426 if ( !m_standardFeedList.isEmpty() )
427 openUrl( KUrl::fromPath( m_standardFeedList ) );
430 bool Part::openFile() {
431 if ( m_loadFeedListCommand || m_standardListLoaded )
434 cmd->setParentWidget( m_mainWidget );
436 cmd->setFileName( localFilePath() );
437 cmd->setDefaultFeedList( createDefaultFeedList() );
438 connect( cmd.get(), SIGNAL(result(boost::shared_ptr<Akregator::FeedList>)),
439 this, SLOT(feedListLoaded(boost::shared_ptr<Akregator::FeedList>)) );
440 m_loadFeedListCommand = cmd.release();
441 m_loadFeedListCommand->start();
445 bool Part::writeToTextFile(
const QString& data,
const QString& filename )
const {
446 KSaveFile file( filename );
447 if ( !file.open( QIODevice::WriteOnly ) )
449 QTextStream stream( &file );
450 stream.setCodec(
"UTF-8" );
451 stream << data << endl;
452 return file.finalize();
455 void Part::feedListLoaded(
const shared_ptr<FeedList>& list ) {
456 assert( !m_standardListLoaded );
458 m_standardListLoaded = list != 0;
463 if ( m_standardListLoaded )
464 QTimer::singleShot( 0,
this, SLOT(flushAddFeedRequests()) );
470 void Part::flushAddFeedRequests() {
471 Q_FOREACH(
const AddFeedRequest& i, m_requests ) {
472 Q_FOREACH (
const QString& j, i.urls )
473 m_mainWidget->addFeedToGroup( j, i.group );
474 NotificationManager::self()->slotNotifyFeeds( i.urls );
482 if ( !m_standardListLoaded )
486 if ( !m_backedUpList )
488 const QString backup = localFilePath() + QLatin1String(
"~" );
489 if ( QFile::copy( localFilePath(), backup ) )
490 m_backedUpList =
true;
495 if ( writeToTextFile( xml, localFilePath() ) )
498 KMessageBox::error( m_mainWidget,
499 i18n(
"Access denied: Cannot save feed list to <b>%1</b>. Please check your permissions.", localFilePath() ),
500 i18n(
"Write Error" ) );
503 bool Part::isTrayIconEnabled()
const
508 void Part::importFile(
const KUrl& url)
512 bool isRemote =
false;
514 if (url.isLocalFile())
515 filename = url.toLocalFile();
520 if (!KIO::NetAccess::download(url, filename, m_mainWidget) )
522 KMessageBox::error(m_mainWidget, KIO::NetAccess::lastErrorString() );
527 QFile file(filename);
528 if (file.open(QIODevice::ReadOnly))
532 if (doc.setContent(file.readAll()))
535 KMessageBox::error(m_mainWidget, i18n(
"Could not import the file %1 (no valid OPML)", filename), i18n(
"OPML Parsing Error") );
538 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"));
541 KIO::NetAccess::removeTempFile(filename);
546 if (url.isLocalFile())
548 const QString fname = url.toLocalFile();
550 if ( QFile::exists( fname ) &&
551 KMessageBox::questionYesNo(m_mainWidget,
552 i18n(
"The file %1 already exists; do you want to overwrite it?", fname ),
554 KStandardGuiItem::overwrite(),
555 KStandardGuiItem::cancel()) == KMessageBox::No )
558 if ( !writeToTextFile( m_mainWidget->
feedListToOPML().toString(), fname ) )
559 KMessageBox::error(m_mainWidget, i18n(
"Access denied: cannot write to file %1. Please check your permissions.", fname), i18n(
"Write Error") );
565 KTemporaryFile tmpfile;
568 QTextStream stream(&tmpfile);
569 stream.setCodec(
"UTF-8");
574 if (!KIO::NetAccess::upload(tmpfile.fileName(), url, m_mainWidget))
575 KMessageBox::error(m_mainWidget, KIO::NetAccess::lastErrorString() );
581 KUrl url = KFileDialog::getOpenUrl( KUrl(),
582 "*.opml *.xml|" + i18n(
"OPML Outlines (*.opml, *.xml)")
583 +
"\n*|" + i18n(
"All Files") );
591 KUrl url= KFileDialog::getSaveUrl( KUrl(),
592 "*.opml *.xml|" + i18n(
"OPML Outlines (*.opml, *.xml)")
593 +
"\n*|" + i18n(
"All Files") );
595 if ( !url.isEmpty() )
606 kDebug() <<
"fetchFeedURL==" << s;
614 m_requests.append( req );
615 if ( m_standardListLoaded )
616 flushAddFeedRequests();
627 KNotifyConfigWidget::configure(m_mainWidget, about.appName() );
635 m_dialog =
new KCMultiDialog( m_mainWidget );
636 connect( m_dialog, SIGNAL(configCommitted()),
637 this, SLOT(slotSettingsChanged()) );
638 connect( m_dialog, SIGNAL(configCommitted()),
642 const QString constraint =
"[X-KDE-ParentApp] == 'akregator'";
643 const KService::List offers = KServiceTypeTrader::self()->query(
"KCModule", constraint );
644 foreach(
const KService::Ptr &service, offers ) {
645 m_dialog->addModule( service->storageId() );
653 KParts::Part* Part::hitTest(
QWidget *widget,
const QPoint &globalPos)
676 return inherited::hitTest(widget, globalPos);
680 void Part::initFonts()
685 fonts.append(KGlobalSettings::generalFont().family());
686 fonts.append(KGlobalSettings::fixedFont().family());
687 fonts.append(KGlobalSettings::generalFont().family());
688 fonts.append(KGlobalSettings::generalFont().family());
703 KConfig _konq(
"konquerorrc", KConfig::NoGlobals );
704 KConfigGroup konq(&_konq,
"HTML Settings");
706 if (!conf.hasKey(
"MinimumFontSize"))
709 if (konq.hasKey(
"MinimumFontSize"))
710 minfs = konq.readEntry(
"MinimumFontSize", 8);
712 minfs = std::max( KGlobalSettings::generalFont().pointSize() - 2, 4 );
716 if (!conf.hasKey(
"MediumFontSize"))
719 if (konq.hasKey(
"MediumFontSize"))
720 medfs = konq.readEntry(
"MediumFontSize", 12);
722 medfs = KGlobalSettings::generalFont().pointSize();
726 if (!conf.hasKey(
"UnderlineLinks"))
728 bool underline =
true;
729 if (konq.hasKey(
"UnderlineLinks"))
730 underline = konq.readEntry(
"UnderlineLinks",
false);
736 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
737 QString addFeedGroup = !args->getOption(
"group").isEmpty() ?
738 args->getOption(
"group")
739 : i18n(
"Imported Folder");
741 QStringList feedsToAdd = args->getOptionList(
"addfeed");
743 if (feedsToAdd.isEmpty() && args->count() > 0) {
744 QString url = args->url(0).url();
746 feedsToAdd.append(url);
749 if (!feedsToAdd.isEmpty())
754 void Part::clearCrashProperties()
758 KConfig config(
"crashed", KConfig::SimpleConfig,
760 KConfigGroup configGroup(&config,
"Part");
761 configGroup.writeEntry(
"crashed",
false);
765 void Part::saveCrashProperties()
769 KConfig config(
"crashed", KConfig::SimpleConfig,
771 KConfigGroup configGroup(&config,
"Part");
772 configGroup.deleteGroup();
774 configGroup.writeEntry(
"crashed",
true);
779 bool Part::readCrashProperties()
781 KConfig config(
"crashed", KConfig::SimpleConfig,
783 KConfigGroup configGroup(&config,
"Part");
785 if (!configGroup.readEntry(
"crashed",
false))
788 const int choice = KMessageBox::questionYesNoCancel( m_mainWidget,
789 i18n(
"Akregator did not close correctly. Would you like to restore the previous session?"),
790 i18n(
"Restore Session?"),
791 KGuiItem(i18n(
"Restore Session"),
"window-new"),
792 KGuiItem(i18n(
"Do Not Restore"),
"dialog-close"),
793 KGuiItem(i18n(
"Ask Me Later"),
"chronometer"),
794 "Restore session when akregator didn't close correctly" );
796 case KMessageBox::Yes:
798 clearCrashProperties();
800 case KMessageBox::No:
801 clearCrashProperties();
806 m_doCrashSave =
false;
812 saveCrashProperties();
815 void Part::autoSaveProperties()
817 KConfig config(
"autosaved", KConfig::SimpleConfig,
"appdata");
818 KConfigGroup configGroup(&config,
"Part");
819 configGroup.deleteGroup();
823 clearCrashProperties();
826 void Part::autoReadProperties()
828 if(kapp->isSessionRestored())
831 KConfig config(
"autosaved", KConfig::SimpleConfig,
"appdata");
832 KConfigGroup configGroup(&config,
"Part");
839 #include "akregator_part.moc"
static void setSansSerifFont(const QString &v)
Set Sans Serif Font.
void saveProperties(KConfigGroup &config)
static void setFonts(const QStringList &v)
Set Fonts.
void saveSettings()
saves settings.
static QString sansSerifFont()
Get Sans Serif Font.
void slotFeedAdd()
adds a new feed to the feed tree
static QString customUserAgent()
Get Custom UserAgent.
#define AKREGATOR_PLUGIN_INTERFACE_VERSION
This is the main widget of the view, containing tree view, article list, viewer etc.
static QString archiveBackend()
Get Archive Backend.
virtual void readProperties(const KConfigGroup &config)
This method is called when this app is restored.
void saveSettings()
Used to save settings after changing them from configuration dialog.
void importFeedList(const QDomDocument &doc)
Adds the feeds in doc to the "Imported Folder".
void setFeedList(const boost::shared_ptr< FeedList > &feedList)
virtual QString key() const
identifier of the storage type, like "metakit", "postgres" etc.
static QString standardFont()
Get Standard Font.
void setStorage(Backend::Storage *storage)
void signalSettingsChanged()
static int minimumFontSize()
Get MinimumFontSize.
void addFeedsToGroup(const QStringList &urls, const QString &group)
Add a feed to a group.
static void setInstance(ActionManager *manager)
static int mediumFontSize()
Get MediumFontSize.
static QString serifFont()
Get Serif Font.
This is a RSS Aggregator "Part".
static bool showTrayIcon()
Get Show tray icon.
static void setMediumFontSize(int v)
Set MediumFontSize.
virtual void saveProperties(KConfigGroup &config)
This method is called when it is time for the app to save its properties for session management purpo...
static StorageFactoryRegistry * self()
virtual void insertGuiClients(KXMLGUIClient *parent)
void setTrayIcon(TrayIcon *trayIcon)
void signalArticlesSelected(const QList< Akregator::Article > &)
void showNotificationOptions()
void slotSetTotalUnread()
emits signalUnreadCountChanged(int)
void setWidget(QWidget *widget, const KComponentData &inst=KComponentData())
the widget used for notification, normally either the mainwindow or the tray icon ...
static KService::List query(const QString &constraint=QString())
It will return a list of services that match your specifications.
void exportFile(const KUrl &url)
Akregator-specific implementation of the ActionManager interface.
static NotificationManager * self()
singleton instance of notification manager
static void setInstance(TrayIcon *trayIcon)
static bool markAllFeedsReadOnStartup()
Get Mark all feeds as read on startup.
static void setFixedFont(const QString &v)
Set Fixed Font.
void readProperties(const KConfigGroup &config)
session management
static QString fixedFont()
Get Fixed Font.
void slotSaveFeedList()
Saves the standard feed list to it's default location.
virtual void storeFeedList(const QString &opmlStr)=0
stores the feed list in the storage backend.
void slotFetchAllFeeds()
starts fetching of all feeds in the tree
StorageFactory * getFactory(const QString &typestr)
virtual bool open(bool autoCommit=false)=0
Open storage and prepare it for work.
void showOptions()
Shows configuration dialog.
virtual Storage * createStorage(const QStringList ¶ms) const =0
creates a storage object with given parameters
bool openUrl(const KUrl &url)
Opens feedlist.
static void setUnderlineLinks(bool v)
Set UnderlineLinks.
static TrayIcon * getInstance()
K_EXPORT_PLUGIN(AkregatorFactory(createAboutData())) BrowserExtension
void slotMarkAllFeedsRead()
marks all articles in all feeds in the tree as read
static QStringList fonts()
Get Fonts.
QDomDocument feedListToOPML()
void fetchAllFeeds()
Fetch all feeds in the feed tree.
static Akregator::Plugin * createFromService(const KService::Ptr service, QObject *parent=0)
Load and instantiate plugin from service.
void fetchFeedUrl(const QString &)
static void setSerifFont(const QString &v)
Set Serif Font.
static bool useHTMLCache()
Get Use HTML Cache.
static void setMinimumFontSize(int v)
Set MinimumFontSize.
static bool fetchOnStartup()
Get Fetch on startup.
void slotAutoSave()
Call to auto save.
static void setStandardFont(const QString &v)
Set Standard Font.
void openStandardFeedList()
Opens standard feedlist.
static FeedIconManager * self()
KParts::ReadOnlyPart inherited
static const KAboutData & createAboutData()