@@ -19,7 +19,9 @@
19import QtQuick 2.4
19import QtQuick 2.4
20import Ubuntu.Components 1.3
20import Ubuntu.Components 1.3
21import Ubuntu.Components.Popups 1.3
21import Ubuntu.Components.Popups 1.3
22+import QtQuick.LocalStorage 2.0
22import "../components"
23import "../components"
24+import "../podcasts.js" as Podcasts
25 id: settingsPage
27 id: settingsPage
@@ -210,6 +212,103 @@ Page {
210 onClicked: mainStack.push(Qt.resolvedUrl("../settings/DownloadSetting.qml"))
212 onClicked: mainStack.push(Qt.resolvedUrl("../settings/DownloadSetting.qml"))
216+ id: refreshArtListItem
218+ property int numberOfPodcasts: 0
219+ property int queueLength: imageDownloader.queueLength
223+ title.text: i18n.tr("Refresh podcast artwork")
224+ title.color: podbird.appTheme.baseText
225+ summary.text: i18n.tr("Update all podcasts artwork and fix missing ones (this only works with podcasts added via iTunes® search)")
226+ summary.color: podbird.appTheme.baseSubText
227+ summary.maximumLineCount: 3
233+ anchors { top: refreshArt.bottom; left: parent.left; right: parent.right; leftMargin: units.gu(2); rightMargin: units.gu(2) }
234+ progress: (refreshArtListItem.numberOfPodcasts - refreshArtListItem.queueLength) * (100 / refreshArtListItem.numberOfPodcasts)
235+ height: progress > 0 && progress < 100 ? units.dp(5) : 0
238+ divider.visible: false
239+ height: refreshArt.height + progressBar.height
241+ var db = Podcasts.init()
242+ db.transaction(function (tx) {
243+ var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
244+ refreshArtListItem.numberOfPodcasts = rs.rows.length
245+ for (var i=0; i < rs.rows.length; i++) {
246+ var podcast = rs.rows.item(i);
247+ settingsPage.getPodcastCoverArt(podcast.name, podcast.feed, podcast.image)
254+ title.text: i18n.tr("Storage Settings")
260+ property int fileCount: 0
261+ property int linkCount: 0
265+ title.text: i18n.tr("Delete orphaned files and links")
266+ title.color: podbird.appTheme.baseText
267+ summary.text: i18n.tr("Free space by removing orphaned downloaded files and links")
268+ summary.color: podbird.appTheme.baseSubText
273+ id: orphanProgressBar
275+ anchors { top: orphanLayout.bottom; left: parent.left; right: parent.right; leftMargin: units.gu(2); rightMargin: units.gu(2) }
276+ height: indeterminateProgress ? units.dp(5) : 0
279+ divider.visible: false
280+ height: orphanLayout.height + orphanProgressBar.height
282+ orphanProgressBar.indeterminateProgress = true
283+ settingsPage.removeOrphans()
284+ orphanProgressBar.indeterminateProgress = false
285+ var popup = PopupUtils.open(cleanUpDialog, settingsPage);
286+ popup.orphanCount = orphanListItem.fileCount + orphanListItem.linkCount
295+ property int orphanCount: 0
297+ title: orphanCount > 0 ? i18n.tr("Removed Orphaned files and links") : i18n.tr("No Orphans found!")
298+ text: orphanCount > 0 ? i18n.tr("All orphaned files have been deleted to recover disk space. Orphaned links \
299+pointing at invalid files have also been cleaned up.")
300+ : i18n.tr("No orphaned files have been found to recover disk space. Podbird database is clean.")
303+ text: i18n.tr("Close")
304+ color: podbird.appTheme.positiveActionButton
306+ PopupUtils.close(dialogInternal)
213 HeaderListItem {
312 HeaderListItem {
214 // TRANSLATORS: Shortened form of "Miscellaneous" which is shown to denote other setting options
313 // TRANSLATORS: Shortened form of "Miscellaneous" which is shown to denote other setting options
215 // that doesn't fit into any other category.
314 // that doesn't fit into any other category.
@@ -238,6 +337,96 @@ Page {
341+ function getPodcastCoverArt(name, feedUrl, image) {
343+ var url = "https://itunes.apple.com/search?term=" + name + "&media=podcast&entity=podcast"
344+ var xhr = new XMLHttpRequest;
345+ xhr.open("GET", url);
346+ xhr.onreadystatechange = function() {
347+ if (xhr.readyState === XMLHttpRequest.DONE) {
348+ var json = JSON.parse(xhr.responseText);
349+ var db = Podcasts.init();
351+ for(var i in json.results) {
352+ if (name == json.results[i].trackName) {
353+ if (feedUrl == json.results[i].feedUrl) {
354+ fileManager.deleteFile(image);
355+ coverArt = json.results[i].artworkUrl600
357+ imageDownloader.addDownload(feedUrl, coverArt)
367+ function removeOrphans() {
368+ var filelist = fileManager.getDownloadedEpisodes()
370+ orphanListItem.fileCount = 0
371+ orphanListItem.linkCount = 0
373+ var db = Podcasts.init()
374+ db.transaction(function (tx) {
375+ var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
377+ // Go through every downloaded file and check if they are orphaned
378+ for (var l = 0; l < filelist.length; l++) {
379+ var isOrphanFile = true
381+ // Go through every podcast
382+ for (var i=0; i < rs.rows.length; i++) {
383+ var podcast = rs.rows.item(i);
384+ var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=?", [podcast.rowid]);
386+ // Go through every episode in the podcast
387+ for (var j=0; j < rs2.rows.length; j++) {
388+ var episode = rs2.rows.item(j);
389+ if (episode.downloadedfile) {
390+ if(fileManager.podcastDirectory + "/" + filelist[l] === episode.downloadedfile) {
391+ isOrphanFile = false
398+ orphanListItem.fileCount++
399+ fileManager.deleteFile(fileManager.podcastDirectory + "/" + filelist[l])
400+ console.log("[LOG]: Removed Orphan File: " + fileManager.podcastDirectory + "/" + filelist[l])
404+ // Go through every podcast in the db and find orphaned links
405+ for (i=0; i < rs.rows.length; i++) {
406+ var isOrphanLink = true
407+ podcast = rs.rows.item(i);
408+ rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=?", [podcast.rowid]);
410+ // Go through every episode in the podcast
411+ for (j=0; j < rs2.rows.length; j++) {
412+ episode = rs2.rows.item(j);
413+ if (episode.downloadedfile) {
414+ for (l = 0; l < filelist.length; l++) {
415+ if(episode.downloadedfile === fileManager.podcastDirectory + "/" + filelist[l]) {
416+ isOrphanLink = false
421+ orphanListItem.linkCount++
422+ tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [episode.guid]);
423+ console.log("[LOG]: Removed Orphan Link: " + episode.downloadedfile)