mirror of https://github.com/KDE/kasts.git
Implement interval-based automatic podcast updates
This also includes a restructuring of some of the settings. BUG: 466789
This commit is contained in:
parent
98603c383e
commit
6822304c56
|
@ -44,6 +44,10 @@ Fetcher::Fetcher()
|
|||
manager->enableStrictTransportSecurityStore(true);
|
||||
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
|
||||
// setup update timer if required
|
||||
initializeUpdateTimer();
|
||||
connect(SettingsManager::self(), &SettingsManager::autoFeedUpdateIntervalChanged, this, &Fetcher::initializeUpdateTimer);
|
||||
}
|
||||
|
||||
void Fetcher::fetch(const QString &url)
|
||||
|
@ -242,3 +246,43 @@ void Fetcher::setHeader(QNetworkRequest &request) const
|
|||
{
|
||||
request.setRawHeader(QByteArray("User-Agent"), QByteArray("Kasts/") + QByteArray(KASTS_VERSION_STRING) + QByteArray(" Syndication"));
|
||||
}
|
||||
|
||||
void Fetcher::initializeUpdateTimer()
|
||||
{
|
||||
qCDebug(kastsFetcher) << "Fetcher::setUpdateTimer";
|
||||
qCDebug(kastsFetcher) << "new auto update interval =" << SettingsManager::self()->autoFeedUpdateInterval();
|
||||
|
||||
if (m_updateTimer) {
|
||||
m_updateTimer->stop();
|
||||
disconnect(m_updateTimer, &QTimer::timeout, this, &Fetcher::checkUpdateTimer);
|
||||
delete m_updateTimer;
|
||||
}
|
||||
|
||||
if (SettingsManager::self()->autoFeedUpdateInterval() > 0) {
|
||||
m_updateTriggerTime =
|
||||
QDateTime::currentDateTimeUtc().addSecs(3600 * SettingsManager::self()->autoFeedUpdateInterval()); // update interval specified in hours
|
||||
m_updateTimer = new QTimer(this);
|
||||
m_updateTimer->setTimerType(Qt::VeryCoarseTimer);
|
||||
|
||||
connect(m_updateTimer, &QTimer::timeout, this, &Fetcher::checkUpdateTimer);
|
||||
|
||||
m_updateTimer->start(m_checkInterval); // trigger every ten minutes
|
||||
}
|
||||
}
|
||||
|
||||
void Fetcher::checkUpdateTimer()
|
||||
{
|
||||
qCDebug(kastsFetcher) << "Fetcher::checkUpdateTimer; next automatic feed update in" << m_updateTriggerTime - QDateTime::currentDateTimeUtc();
|
||||
|
||||
// add a few seconds as "fuzzy match" to avoid that the trigger is delayed
|
||||
// by another 10 minutes due to a difference of just a few milliseconds
|
||||
if (QDateTime::currentDateTimeUtc().addSecs(5) > m_updateTriggerTime) {
|
||||
qCDebug(kastsFetcher) << "Trigger for feed update has been reached; updating feeds now";
|
||||
QTimer::singleShot(0, this, &Fetcher::fetchAll);
|
||||
|
||||
// set next update time
|
||||
m_updateTriggerTime =
|
||||
QDateTime::currentDateTimeUtc().addSecs(3600 * SettingsManager::self()->autoFeedUpdateInterval()); // update interval specified in hours
|
||||
qCDebug(kastsFetcher) << "new auto feed update trigger set to" << m_updateTriggerTime;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <Syndication/Syndication>
|
||||
|
||||
|
@ -50,6 +52,9 @@ public:
|
|||
QNetworkReply *get(QNetworkRequest &request) const;
|
||||
QNetworkReply *post(QNetworkRequest &request, const QByteArray &data) const;
|
||||
|
||||
void initializeUpdateTimer();
|
||||
void checkUpdateTimer();
|
||||
|
||||
Q_SIGNALS:
|
||||
void entryAdded(const QString &feedurl, const QString &id);
|
||||
void entryUpdated(const QString &feedurl, const QString &id);
|
||||
|
@ -84,4 +89,8 @@ private:
|
|||
int m_updateProgress;
|
||||
int m_updateTotal;
|
||||
bool m_updating;
|
||||
|
||||
const qint64 m_checkInterval = 10 * 60 * 1000; // trigger timer every 10 minutes
|
||||
QTimer *m_updateTimer;
|
||||
QDateTime m_updateTriggerTime;
|
||||
};
|
||||
|
|
|
@ -59,9 +59,8 @@ FormCard.FormCardPage {
|
|||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: showTimeLeft
|
||||
Kirigami.FormData.label: i18nc("@option:check Label for settings related to the play time, e.g. whether the total track time is shown or a countdown of the remaining play time", "Play time:")
|
||||
checked: SettingsManager.toggleRemainingTime
|
||||
text: i18n("Show time left instead of total track time")
|
||||
text: i18nc("@option:check Label for setting whether the total track time is shown or a countdown of the remaining play time", "Show time left instead of total track time")
|
||||
onToggled: {
|
||||
SettingsManager.toggleRemainingTime = checked;
|
||||
SettingsManager.save();
|
||||
|
@ -121,32 +120,46 @@ FormCard.FormCardPage {
|
|||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title Form header for settings related to the queue", "Queue settings")
|
||||
title: i18nc("@title Form header for settings related podcast updates", "Podcast update settings")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: continuePlayingNextEntry
|
||||
checked: SettingsManager.continuePlayingNextEntry
|
||||
text: i18nc("@option:check", "Continue playing next episode after current one finishes")
|
||||
onToggled: {
|
||||
SettingsManager.continuePlayingNextEntry = checked;
|
||||
FormCard.FormComboBoxDelegate {
|
||||
id: autoFeedUpdateInterval
|
||||
text: i18nc("@label:listbox", "Automatically fetch podcast feeds")
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [{"text": i18nc("@item:inlistbox automatic podcast update interval", "Never"), "value": 0},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every hour", "Every %1 hours", 1), "value": 1},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every hour", "Every %1 hours", 2), "value": 2},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every hour", "Every %1 hours", 4), "value": 4},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every hour", "Every %1 hours", 8), "value": 8},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every hour", "Every %1 hours", 12), "value": 12},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every day", "Every %1 days", 1), "value": 24},
|
||||
{"text": i18ncp("@item:inlistbox automatic podcast update interval", "Every day", "Every %1 days", 3), "value": 72}]
|
||||
Component.onCompleted: currentIndex = indexOfValue(SettingsManager.autoFeedUpdateInterval)
|
||||
onActivated: {
|
||||
SettingsManager.autoFeedUpdateInterval = currentValue;
|
||||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: refreshOnStartup
|
||||
Kirigami.FormData.label: i18nc("@option:check Label for settings related to podcast updates", "Update Settings:")
|
||||
checked: SettingsManager.refreshOnStartup
|
||||
text: i18n("Automatically fetch podcast updates on startup")
|
||||
text: i18nc("@option:check", "Fetch podcast updates on startup")
|
||||
onToggled: {
|
||||
SettingsManager.refreshOnStartup = checked;
|
||||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FormCard.FormDelegateSeparator { above: refreshOnStartup; below: doFullUpdate }
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: doFullUpdate
|
||||
checked: SettingsManager.doFullUpdate
|
||||
|
@ -183,17 +196,49 @@ FormCard.FormCardPage {
|
|||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title Form header for settings related to the queue", "Queue settings")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: continuePlayingNextEntry
|
||||
checked: SettingsManager.continuePlayingNextEntry
|
||||
text: i18nc("@option:check", "Continue playing next episode after current one finishes")
|
||||
onToggled: {
|
||||
SettingsManager.continuePlayingNextEntry = checked;
|
||||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator { above: continuePlayingNextEntry; below: resetPositionOnPlayed }
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: resetPositionOnPlayed
|
||||
checked: SettingsManager.resetPositionOnPlayed
|
||||
text: i18nc("@option:check", "Reset play position after an episode is played")
|
||||
onToggled: {
|
||||
SettingsManager.resetPositionOnPlayed = checked;
|
||||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator { above: resetPositionOnPlayed; below: episodeBehavior }
|
||||
|
||||
FormCard.FormDelegateSeparator { above: autoDownload; below: episodeBehavior }
|
||||
|
||||
FormCard.FormComboBoxDelegate {
|
||||
id: episodeBehavior
|
||||
text: i18nc("@label:listbox", "Played episode behavior")
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [{"text": i18n("Do not delete"), "value": 0},
|
||||
{"text": i18n("Delete immediately"), "value": 1},
|
||||
{"text": i18n("Delete at next startup"), "value": 2}]
|
||||
model: [{"text": i18nc("@item:inlistbox What to do with played episodes", "Do not delete"), "value": 0},
|
||||
{"text": i18nc("@item:inlistbox What to do with played episodes", "Delete immediately"), "value": 1},
|
||||
{"text": i18nc("@item:inlistbox What to do with played episodes", "Delete at next startup"), "value": 2}]
|
||||
Component.onCompleted: currentIndex = indexOfValue(SettingsManager.autoDeleteOnPlayed)
|
||||
onActivated: {
|
||||
SettingsManager.autoDeleteOnPlayed = currentValue;
|
||||
|
@ -218,18 +263,6 @@ FormCard.FormCardPage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator { above: markAsPlayedGracePeriod; below: resetPositionOnPlayed }
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: resetPositionOnPlayed
|
||||
checked: SettingsManager.resetPositionOnPlayed
|
||||
text: i18nc("@option:check", "Reset play position after an episode is played")
|
||||
onToggled: {
|
||||
SettingsManager.resetPositionOnPlayed = checked;
|
||||
SettingsManager.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
|
|
|
@ -5,44 +5,6 @@
|
|||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="kastsrc" />
|
||||
<group name="General">
|
||||
<entry name="ColorScheme" type="String">
|
||||
<label>Color scheme</label>
|
||||
</entry>
|
||||
<entry name="showTrayIcon" type="Bool">
|
||||
<label>Show icon in system tray</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="trayIconType" type="Enum">
|
||||
<label>Color/type of the tray icon</label>
|
||||
<choices>
|
||||
<choice name="Colorful">
|
||||
<label>Colorful</label>
|
||||
</choice>
|
||||
<choice name="Light">
|
||||
<label>Light</label>
|
||||
</choice>
|
||||
<choice name="Dark">
|
||||
<label>Dark</label>
|
||||
</choice>
|
||||
</choices>
|
||||
<default>Dark</default>
|
||||
</entry>
|
||||
<entry name="minimizeToTray" type="Bool">
|
||||
<label>Minimize to system tray instead of closing application</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="alwaysShowFeedTitles" type="Bool">
|
||||
<label>Always show the title of podcast feeds in subscription view</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="showEpisodeImage" type="Bool">
|
||||
<label>Show the image of the episode rather than the general podcast image</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="showPodcastTitle" type="Bool">
|
||||
<label>Show the podcast/feed title on the entry delegate</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="prioritizeStreaming" type="Bool">
|
||||
<label>Show streaming button instead of download button</label>
|
||||
<default>false</default>
|
||||
|
@ -71,6 +33,10 @@
|
|||
<label>Automatically download new episodes</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="autoFeedUpdateInterval" type="Int">
|
||||
<label>Interval for automatically updating feeds/podcasts. 0 means never update automatically.</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
<entry name="autoDeleteOnPlayed" type="Enum">
|
||||
<label>Setting to select if or when to delete played episode</label>
|
||||
<choices>
|
||||
|
@ -124,15 +90,55 @@
|
|||
<label>Article font size</label>
|
||||
<default>10</default>
|
||||
</entry>
|
||||
<entry name="articleFontUseSystem" type="Bool">
|
||||
<label>Use default system font</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="StoragePath" type="Url">
|
||||
<label>Custom path to store enclosures and images</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Appearance">
|
||||
<entry name="ColorScheme" type="String">
|
||||
<label>Color scheme</label>
|
||||
</entry>
|
||||
<entry name="alwaysShowFeedTitles" type="Bool">
|
||||
<label>Always show the title of podcast feeds in subscription view</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="showEpisodeImage" type="Bool">
|
||||
<label>Show the image of the episode rather than the general podcast image</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="showPodcastTitle" type="Bool">
|
||||
<label>Show the podcast/feed title on the entry delegate</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="showTrayIcon" type="Bool">
|
||||
<label>Show icon in system tray</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="trayIconType" type="Enum">
|
||||
<label>Color/type of the tray icon</label>
|
||||
<choices>
|
||||
<choice name="Colorful">
|
||||
<label>Colorful</label>
|
||||
</choice>
|
||||
<choice name="Light">
|
||||
<label>Light</label>
|
||||
</choice>
|
||||
<choice name="Dark">
|
||||
<label>Dark</label>
|
||||
</choice>
|
||||
</choices>
|
||||
<default>Dark</default>
|
||||
</entry>
|
||||
<entry name="minimizeToTray" type="Bool">
|
||||
<label>Minimize to system tray instead of closing application</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="articleFontUseSystem" type="Bool">
|
||||
<label>Use default system font</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Playback Settings">
|
||||
<entry name="playbackRates" type="IntList">
|
||||
<label>List of user-defined playback rates</label>
|
||||
|
|
Loading…
Reference in New Issue