Return more useful aggregate information from the PodcastBackend, show something in the Internet service
This commit is contained in:
parent
e8a879372d
commit
f2885c0319
|
@ -31,6 +31,6 @@ CREATE TABLE podcast_episodes (
|
||||||
|
|
||||||
CREATE INDEX podcast_idx_url ON podcasts(url);
|
CREATE INDEX podcast_idx_url ON podcasts(url);
|
||||||
|
|
||||||
CREATE INDEX podcast_episodes_idx_podcast_id ON podcast_episodes(podcast_id);
|
CREATE INDEX podcast_episodes_idx_aggregate ON podcast_episodes(podcast_id, listened);
|
||||||
|
|
||||||
UPDATE schema_version SET version=37;
|
UPDATE schema_version SET version=37;
|
||||||
|
|
|
@ -38,6 +38,8 @@ Application::Application(QObject* parent)
|
||||||
tag_reader_client_(NULL),
|
tag_reader_client_(NULL),
|
||||||
database_(NULL),
|
database_(NULL),
|
||||||
album_cover_loader_(NULL),
|
album_cover_loader_(NULL),
|
||||||
|
playlist_backend_(NULL),
|
||||||
|
podcast_backend_(NULL),
|
||||||
appearance_(NULL),
|
appearance_(NULL),
|
||||||
cover_providers_(NULL),
|
cover_providers_(NULL),
|
||||||
task_manager_(NULL),
|
task_manager_(NULL),
|
||||||
|
@ -47,9 +49,7 @@ Application::Application(QObject* parent)
|
||||||
global_search_(NULL),
|
global_search_(NULL),
|
||||||
internet_model_(NULL),
|
internet_model_(NULL),
|
||||||
library_(NULL),
|
library_(NULL),
|
||||||
playlist_backend_(NULL),
|
device_manager_(NULL)
|
||||||
device_manager_(NULL),
|
|
||||||
podcast_backend_(NULL)
|
|
||||||
{
|
{
|
||||||
tag_reader_client_ = new TagReaderClient(this);
|
tag_reader_client_ = new TagReaderClient(this);
|
||||||
MoveToNewThread(tag_reader_client_);
|
MoveToNewThread(tag_reader_client_);
|
||||||
|
@ -61,6 +61,12 @@ Application::Application(QObject* parent)
|
||||||
album_cover_loader_ = new AlbumCoverLoader(this);
|
album_cover_loader_ = new AlbumCoverLoader(this);
|
||||||
MoveToNewThread(album_cover_loader_);
|
MoveToNewThread(album_cover_loader_);
|
||||||
|
|
||||||
|
playlist_backend_ = new PlaylistBackend(this, this);
|
||||||
|
MoveToThread(playlist_backend_, database_->thread());
|
||||||
|
|
||||||
|
podcast_backend_ = new PodcastBackend(this, this);
|
||||||
|
MoveToThread(podcast_backend_, database_->thread());
|
||||||
|
|
||||||
appearance_ = new Appearance(this);
|
appearance_ = new Appearance(this);
|
||||||
cover_providers_ = new CoverProviders(this);
|
cover_providers_ = new CoverProviders(this);
|
||||||
task_manager_ = new TaskManager(this);
|
task_manager_ = new TaskManager(this);
|
||||||
|
@ -72,13 +78,8 @@ Application::Application(QObject* parent)
|
||||||
|
|
||||||
library_ = new Library(this, this);
|
library_ = new Library(this, this);
|
||||||
|
|
||||||
playlist_backend_ = new PlaylistBackend(this, this);
|
|
||||||
MoveToThread(playlist_backend_, database_->thread());
|
|
||||||
|
|
||||||
device_manager_ = new DeviceManager(this, this);
|
device_manager_ = new DeviceManager(this, this);
|
||||||
|
|
||||||
podcast_backend_ = new PodcastBackend(this, this);
|
|
||||||
MoveToThread(podcast_backend_, database_->thread());
|
|
||||||
|
|
||||||
library_->Init();
|
library_->Init();
|
||||||
library_->StartThreads();
|
library_->StartThreads();
|
||||||
|
|
|
@ -49,6 +49,8 @@ public:
|
||||||
TagReaderClient* tag_reader_client() const { return tag_reader_client_; }
|
TagReaderClient* tag_reader_client() const { return tag_reader_client_; }
|
||||||
Database* database() const { return database_; }
|
Database* database() const { return database_; }
|
||||||
AlbumCoverLoader* album_cover_loader() const { return album_cover_loader_; }
|
AlbumCoverLoader* album_cover_loader() const { return album_cover_loader_; }
|
||||||
|
PlaylistBackend* playlist_backend() const { return playlist_backend_; }
|
||||||
|
PodcastBackend* podcast_backend() const { return podcast_backend_; }
|
||||||
Appearance* appearance() const { return appearance_; }
|
Appearance* appearance() const { return appearance_; }
|
||||||
CoverProviders* cover_providers() const { return cover_providers_; }
|
CoverProviders* cover_providers() const { return cover_providers_; }
|
||||||
TaskManager* task_manager() const { return task_manager_; }
|
TaskManager* task_manager() const { return task_manager_; }
|
||||||
|
@ -57,11 +59,8 @@ public:
|
||||||
CurrentArtLoader* current_art_loader() const { return current_art_loader_; }
|
CurrentArtLoader* current_art_loader() const { return current_art_loader_; }
|
||||||
GlobalSearch* global_search() const { return global_search_; }
|
GlobalSearch* global_search() const { return global_search_; }
|
||||||
InternetModel* internet_model() const { return internet_model_; }
|
InternetModel* internet_model() const { return internet_model_; }
|
||||||
|
|
||||||
Library* library() const { return library_; }
|
Library* library() const { return library_; }
|
||||||
PlaylistBackend* playlist_backend() const { return playlist_backend_; }
|
|
||||||
DeviceManager* device_manager() const { return device_manager_; }
|
DeviceManager* device_manager() const { return device_manager_; }
|
||||||
PodcastBackend* podcast_backend() const { return podcast_backend_; }
|
|
||||||
|
|
||||||
LibraryBackend* library_backend() const;
|
LibraryBackend* library_backend() const;
|
||||||
LibraryModel* library_model() const;
|
LibraryModel* library_model() const;
|
||||||
|
@ -79,6 +78,8 @@ private:
|
||||||
TagReaderClient* tag_reader_client_;
|
TagReaderClient* tag_reader_client_;
|
||||||
Database* database_;
|
Database* database_;
|
||||||
AlbumCoverLoader* album_cover_loader_;
|
AlbumCoverLoader* album_cover_loader_;
|
||||||
|
PlaylistBackend* playlist_backend_;
|
||||||
|
PodcastBackend* podcast_backend_;
|
||||||
Appearance* appearance_;
|
Appearance* appearance_;
|
||||||
CoverProviders* cover_providers_;
|
CoverProviders* cover_providers_;
|
||||||
TaskManager* task_manager_;
|
TaskManager* task_manager_;
|
||||||
|
@ -87,11 +88,8 @@ private:
|
||||||
CurrentArtLoader* current_art_loader_;
|
CurrentArtLoader* current_art_loader_;
|
||||||
GlobalSearch* global_search_;
|
GlobalSearch* global_search_;
|
||||||
InternetModel* internet_model_;
|
InternetModel* internet_model_;
|
||||||
|
|
||||||
Library* library_;
|
Library* library_;
|
||||||
PlaylistBackend* playlist_backend_;
|
|
||||||
DeviceManager* device_manager_;
|
DeviceManager* device_manager_;
|
||||||
PodcastBackend* podcast_backend_;
|
|
||||||
|
|
||||||
QList<QObject*> objects_in_threads_;
|
QList<QObject*> objects_in_threads_;
|
||||||
QList<QThread*> threads_;
|
QList<QThread*> threads_;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "addpodcastdialog.h"
|
#include "addpodcastdialog.h"
|
||||||
#include "addpodcastbyurl.h"
|
#include "addpodcastbyurl.h"
|
||||||
#include "gpoddertoptagspage.h"
|
#include "gpoddertoptagspage.h"
|
||||||
|
#include "podcastbackend.h"
|
||||||
#include "podcastdiscoverymodel.h"
|
#include "podcastdiscoverymodel.h"
|
||||||
#include "ui_addpodcastdialog.h"
|
#include "ui_addpodcastdialog.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
|
|
||||||
AddPodcastDialog::AddPodcastDialog(Application* app, QWidget* parent)
|
AddPodcastDialog::AddPodcastDialog(Application* app, QWidget* parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
|
app_(app),
|
||||||
ui_(new Ui_AddPodcastDialog)
|
ui_(new Ui_AddPodcastDialog)
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
|
@ -100,7 +102,10 @@ void AddPodcastDialog::ChangePodcast(const QModelIndex& current) {
|
||||||
ui_->details_scroll_area->show();
|
ui_->details_scroll_area->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_->details->SetPodcast(current.data(PodcastDiscoveryModel::Role_Podcast).value<Podcast>());
|
current_podcast_ = current.data(PodcastDiscoveryModel::Role_Podcast).value<Podcast>();
|
||||||
|
ui_->details->SetPodcast(current_podcast_);
|
||||||
|
|
||||||
|
add_button_->setEnabled(current_podcast_.url().isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPodcastDialog::PageBusyChanged(bool busy) {
|
void AddPodcastDialog::PageBusyChanged(bool busy) {
|
||||||
|
@ -116,4 +121,5 @@ void AddPodcastDialog::PageBusyChanged(bool busy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPodcastDialog::AddPodcast() {
|
void AddPodcastDialog::AddPodcast() {
|
||||||
|
app_->podcast_backend()->Subscribe(¤t_podcast_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#ifndef ADDPODCASTDIALOG_H
|
#ifndef ADDPODCASTDIALOG_H
|
||||||
#define ADDPODCASTDIALOG_H
|
#define ADDPODCASTDIALOG_H
|
||||||
|
|
||||||
|
#include "podcast.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
class AddPodcastPage;
|
class AddPodcastPage;
|
||||||
|
@ -45,6 +47,8 @@ private:
|
||||||
void AddPage(AddPodcastPage* page);
|
void AddPage(AddPodcastPage* page);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Application* app_;
|
||||||
|
|
||||||
Ui_AddPodcastDialog* ui_;
|
Ui_AddPodcastDialog* ui_;
|
||||||
QPushButton* add_button_;
|
QPushButton* add_button_;
|
||||||
|
|
||||||
|
@ -52,6 +56,8 @@ private:
|
||||||
QList<bool> page_is_busy_;
|
QList<bool> page_is_busy_;
|
||||||
|
|
||||||
WidgetFadeHelper* fader_;
|
WidgetFadeHelper* fader_;
|
||||||
|
|
||||||
|
Podcast current_podcast_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ADDPODCASTDIALOG_H
|
#endif // ADDPODCASTDIALOG_H
|
||||||
|
|
|
@ -24,9 +24,10 @@
|
||||||
|
|
||||||
const QStringList Podcast::kColumns = QStringList()
|
const QStringList Podcast::kColumns = QStringList()
|
||||||
<< "url" << "title" << "description" << "copyright" << "link"
|
<< "url" << "title" << "description" << "copyright" << "link"
|
||||||
<< "image_url" << "author" << "owner_name" << "author_email" << "extra";
|
<< "image_url" << "author" << "owner_name" << "owner_email" << "extra";
|
||||||
|
|
||||||
const QString Podcast::kColumnSpec = Podcast::kColumns.join(", ");
|
const QString Podcast::kColumnSpec = Podcast::kColumns.join(", ");
|
||||||
|
const QString Podcast::kJoinSpec = Utilities::Prepend("p.", Podcast::kColumns).join(", ");
|
||||||
const QString Podcast::kBindSpec = Utilities::Prepend(":", Podcast::kColumns).join(", ");
|
const QString Podcast::kBindSpec = Utilities::Prepend(":", Podcast::kColumns).join(", ");
|
||||||
const QString Podcast::kUpdateSpec = Utilities::Updateify(Podcast::kColumns).join(", ");
|
const QString Podcast::kUpdateSpec = Utilities::Updateify(Podcast::kColumns).join(", ");
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
|
|
||||||
static const QStringList kColumns;
|
static const QStringList kColumns;
|
||||||
static const QString kColumnSpec;
|
static const QString kColumnSpec;
|
||||||
|
static const QString kJoinSpec;
|
||||||
static const QString kBindSpec;
|
static const QString kBindSpec;
|
||||||
static const QString kUpdateSpec;
|
static const QString kUpdateSpec;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ void PodcastBackend::Subscribe(Podcast* podcast) {
|
||||||
|
|
||||||
// Insert the podcast.
|
// Insert the podcast.
|
||||||
QSqlQuery q("INSERT INTO podcasts (" + Podcast::kColumnSpec + ")"
|
QSqlQuery q("INSERT INTO podcasts (" + Podcast::kColumnSpec + ")"
|
||||||
" VALUES " + Podcast::kBindSpec, db);
|
" VALUES (" + Podcast::kBindSpec + ")", db);
|
||||||
podcast->BindToQuery(&q);
|
podcast->BindToQuery(&q);
|
||||||
|
|
||||||
q.exec();
|
q.exec();
|
||||||
|
@ -67,11 +67,13 @@ void PodcastBackend::Subscribe(Podcast* podcast) {
|
||||||
|
|
||||||
// Add those episodes to the database.
|
// Add those episodes to the database.
|
||||||
AddEpisodes(episodes, &db);
|
AddEpisodes(episodes, &db);
|
||||||
|
|
||||||
|
t.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PodcastBackend::AddEpisodes(PodcastEpisodeList* episodes, QSqlDatabase* db) {
|
void PodcastBackend::AddEpisodes(PodcastEpisodeList* episodes, QSqlDatabase* db) {
|
||||||
QSqlQuery q("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec + ")"
|
QSqlQuery q("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec + ")"
|
||||||
" VALUES " + PodcastEpisode::kBindSpec, *db);
|
" VALUES (" + PodcastEpisode::kBindSpec + ")", *db);
|
||||||
|
|
||||||
for (PodcastEpisodeList::iterator it = episodes->begin() ; it != episodes->end() ; ++it) {
|
for (PodcastEpisodeList::iterator it = episodes->begin() ; it != episodes->end() ; ++it) {
|
||||||
it->BindToQuery(&q);
|
it->BindToQuery(&q);
|
||||||
|
@ -84,22 +86,46 @@ void PodcastBackend::AddEpisodes(PodcastEpisodeList* episodes, QSqlDatabase* db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SELECT_PODCAST_QUERY(where_clauses) \
|
||||||
|
"SELECT p.ROWID, " + Podcast::kJoinSpec + "," \
|
||||||
|
" COUNT(e.ROWID), SUM(e.listened)" \
|
||||||
|
" FROM podcasts AS p" \
|
||||||
|
" LEFT JOIN podcast_episodes AS e" \
|
||||||
|
" ON p.ROWID = e.podcast_id" \
|
||||||
|
" " where_clauses \
|
||||||
|
" GROUP BY p.ROWID" \
|
||||||
|
" ORDER BY p.title"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void AddAggregatePodcastFields(const QSqlQuery& q, int column_count, Podcast* podcast) {
|
||||||
|
const int episode_count = q.value(column_count + 1).toInt();
|
||||||
|
const int listened_count = q.value(column_count + 2).toInt();
|
||||||
|
|
||||||
|
podcast->set_extra("db:episode_count", episode_count);
|
||||||
|
podcast->set_extra("db:unlistened_count", episode_count - listened_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PodcastList PodcastBackend::GetAllSubscriptions() {
|
PodcastList PodcastBackend::GetAllSubscriptions() {
|
||||||
PodcastList ret;
|
PodcastList ret;
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec +
|
QSqlQuery q(SELECT_PODCAST_QUERY(""), db);
|
||||||
" FROM podcasts", db);
|
|
||||||
|
|
||||||
q.exec();
|
q.exec();
|
||||||
if (db_->CheckErrors(q))
|
if (db_->CheckErrors(q))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
static const int kPodcastColumnCount = Podcast::kColumns.count();
|
||||||
|
|
||||||
while (q.next()) {
|
while (q.next()) {
|
||||||
Podcast podcast;
|
Podcast podcast;
|
||||||
podcast.InitFromQuery(q);
|
podcast.InitFromQuery(q);
|
||||||
|
|
||||||
|
AddAggregatePodcastFields(q, kPodcastColumnCount, &podcast);
|
||||||
|
|
||||||
ret << podcast;
|
ret << podcast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,14 +138,12 @@ Podcast PodcastBackend::GetSubscriptionById(int id) {
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec +
|
QSqlQuery q(SELECT_PODCAST_QUERY("WHERE ROWID = :id"), db);
|
||||||
" FROM podcasts"
|
|
||||||
" WHERE ROWID = :id", db);
|
|
||||||
|
|
||||||
q.bindValue(":id", id);
|
q.bindValue(":id", id);
|
||||||
q.exec();
|
q.exec();
|
||||||
if (!db_->CheckErrors(q) && q.next()) {
|
if (!db_->CheckErrors(q) && q.next()) {
|
||||||
ret.InitFromQuery(q);
|
ret.InitFromQuery(q);
|
||||||
|
AddAggregatePodcastFields(q, Podcast::kColumns.count(), &ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -131,14 +155,12 @@ Podcast PodcastBackend::GetSubscriptionByUrl(const QUrl& url) {
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec +
|
QSqlQuery q(SELECT_PODCAST_QUERY("WHERE p.url = :url"), db);
|
||||||
" FROM podcasts"
|
|
||||||
" WHERE url = :url", db);
|
|
||||||
|
|
||||||
q.bindValue(":url", url.toEncoded());
|
q.bindValue(":url", url.toEncoded());
|
||||||
q.exec();
|
q.exec();
|
||||||
if (!db_->CheckErrors(q) && q.next()) {
|
if (!db_->CheckErrors(q) && q.next()) {
|
||||||
ret.InitFromQuery(q);
|
ret.InitFromQuery(q);
|
||||||
|
AddAggregatePodcastFields(q, Podcast::kColumns.count(), &ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -41,6 +41,11 @@ public:
|
||||||
// episodes associated with this podcast.
|
// episodes associated with this podcast.
|
||||||
void Unsubscribe(const Podcast& podcast);
|
void Unsubscribe(const Podcast& podcast);
|
||||||
|
|
||||||
|
// Returns a list of all the subscribed podcasts. For efficiency the Podcast
|
||||||
|
// objects returned won't contain any PodcastEpisode objects, but they will
|
||||||
|
// contain aggregate information about total number of episodes and number of
|
||||||
|
// unlistened episodes, in the extra fields "db:episode_count" and
|
||||||
|
// "db:unlistened_count".
|
||||||
PodcastList GetAllSubscriptions();
|
PodcastList GetAllSubscriptions();
|
||||||
Podcast GetSubscriptionById(int id);
|
Podcast GetSubscriptionById(int id);
|
||||||
Podcast GetSubscriptionByUrl(const QUrl& url);
|
Podcast GetSubscriptionByUrl(const QUrl& url);
|
||||||
|
|
|
@ -27,6 +27,7 @@ const QStringList PodcastEpisode::kColumns = QStringList()
|
||||||
<< "downloaded" << "local_url" << "extra";
|
<< "downloaded" << "local_url" << "extra";
|
||||||
|
|
||||||
const QString PodcastEpisode::kColumnSpec = PodcastEpisode::kColumns.join(", ");
|
const QString PodcastEpisode::kColumnSpec = PodcastEpisode::kColumns.join(", ");
|
||||||
|
const QString PodcastEpisode::kJoinSpec = Utilities::Prepend("e.", PodcastEpisode::kColumns).join(", ");
|
||||||
const QString PodcastEpisode::kBindSpec = Utilities::Prepend(":", PodcastEpisode::kColumns).join(", ");
|
const QString PodcastEpisode::kBindSpec = Utilities::Prepend(":", PodcastEpisode::kColumns).join(", ");
|
||||||
const QString PodcastEpisode::kUpdateSpec = Utilities::Updateify(PodcastEpisode::kColumns).join(", ");
|
const QString PodcastEpisode::kUpdateSpec = Utilities::Updateify(PodcastEpisode::kColumns).join(", ");
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
static const QStringList kColumns;
|
static const QStringList kColumns;
|
||||||
static const QString kColumnSpec;
|
static const QString kColumnSpec;
|
||||||
|
static const QString kJoinSpec;
|
||||||
static const QString kBindSpec;
|
static const QString kBindSpec;
|
||||||
static const QString kUpdateSpec;
|
static const QString kUpdateSpec;
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ void PodcastInfoWidget::SetPodcast(const Podcast& podcast) {
|
||||||
SetText(podcast.author(), ui_->author, ui_->author_label);
|
SetText(podcast.author(), ui_->author, ui_->author_label);
|
||||||
SetText(podcast.owner_name(), ui_->owner, ui_->owner_label);
|
SetText(podcast.owner_name(), ui_->owner, ui_->owner_label);
|
||||||
SetText(podcast.link().toString(), ui_->website, ui_->website_label);
|
SetText(podcast.link().toString(), ui_->website, ui_->website_label);
|
||||||
|
SetText(podcast.extra("gpodder:subscribers").toString(), ui_->subscribers, ui_->subscribers_label);
|
||||||
|
|
||||||
if (!image_id_) {
|
if (!image_id_) {
|
||||||
emit LoadingFinished();
|
emit LoadingFinished();
|
||||||
|
|
|
@ -98,22 +98,12 @@ QLineEdit {
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="copyright_label">
|
<widget class="QLineEdit" name="website">
|
||||||
<property name="text">
|
<property name="frame">
|
||||||
<string>Copyright</string>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="field_label" stdset="0">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="owner_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Owner</string>
|
|
||||||
</property>
|
|
||||||
<property name="field_label" stdset="0">
|
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -128,7 +118,17 @@ QLineEdit {
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="owner">
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="website_label">
|
<widget class="QLabel" name="website_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Website</string>
|
<string>Website</string>
|
||||||
|
@ -148,6 +148,16 @@ QLineEdit {
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="copyright_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copyright</string>
|
||||||
|
</property>
|
||||||
|
<property name="field_label" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="author">
|
<widget class="QLineEdit" name="author">
|
||||||
<property name="frame">
|
<property name="frame">
|
||||||
|
@ -158,18 +168,28 @@ QLineEdit {
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="0">
|
||||||
<widget class="QLineEdit" name="owner">
|
<widget class="QLabel" name="owner_label">
|
||||||
<property name="frame">
|
<property name="text">
|
||||||
<bool>false</bool>
|
<string>Owner</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="field_label" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="subscribers_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Subscribers</string>
|
||||||
|
</property>
|
||||||
|
<property name="field_label" stdset="0">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLineEdit" name="website">
|
<widget class="QLineEdit" name="subscribers">
|
||||||
<property name="frame">
|
<property name="frame">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "addpodcastdialog.h"
|
#include "addpodcastdialog.h"
|
||||||
|
#include "podcastbackend.h"
|
||||||
#include "podcastservice.h"
|
#include "podcastservice.h"
|
||||||
|
#include "core/application.h"
|
||||||
#include "internet/internetmodel.h"
|
#include "internet/internetmodel.h"
|
||||||
#include "ui/iconloader.h"
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
|
@ -28,7 +30,8 @@ const char* PodcastService::kSettingsGroup = "Podcasts";
|
||||||
PodcastService::PodcastService(Application* app, InternetModel* parent)
|
PodcastService::PodcastService(Application* app, InternetModel* parent)
|
||||||
: InternetService(kServiceName, app, parent, parent),
|
: InternetService(kServiceName, app, parent, parent),
|
||||||
context_menu_(NULL),
|
context_menu_(NULL),
|
||||||
root_(NULL)
|
root_(NULL),
|
||||||
|
backend_(app->podcast_backend())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +40,39 @@ PodcastService::~PodcastService() {
|
||||||
|
|
||||||
QStandardItem* PodcastService::CreateRootItem() {
|
QStandardItem* PodcastService::CreateRootItem() {
|
||||||
root_ = new QStandardItem(QIcon(":providers/podcast16.png"), tr("Podcasts"));
|
root_ = new QStandardItem(QIcon(":providers/podcast16.png"), tr("Podcasts"));
|
||||||
|
root_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||||
return root_;
|
return root_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PodcastService::LazyPopulate(QStandardItem* parent) {
|
void PodcastService::LazyPopulate(QStandardItem* parent) {
|
||||||
|
switch (parent->data(InternetModel::Role_Type).toInt()) {
|
||||||
|
case InternetModel::Type_Service:
|
||||||
|
PopulatePodcastList(parent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PodcastService::PopulatePodcastList(QStandardItem* parent) {
|
||||||
|
foreach (const Podcast& podcast, backend_->GetAllSubscriptions()) {
|
||||||
|
const int unlistened_count = podcast.extra("db:unlistened_count").toInt();
|
||||||
|
QString title = podcast.title();
|
||||||
|
|
||||||
|
QStandardItem* item = new QStandardItem;
|
||||||
|
|
||||||
|
if (unlistened_count > 0) {
|
||||||
|
// Add the number of new episodes after the title.
|
||||||
|
title.append(QString(" (%1)").arg(unlistened_count));
|
||||||
|
|
||||||
|
// Set a bold font
|
||||||
|
QFont font(item->font());
|
||||||
|
font.setBold(true);
|
||||||
|
item->setFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
item->setText(podcast.title());
|
||||||
|
|
||||||
|
parent->appendRow(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PodcastService::ShowContextMenu(const QModelIndex& index,
|
void PodcastService::ShowContextMenu(const QModelIndex& index,
|
||||||
|
|
|
@ -18,12 +18,13 @@
|
||||||
#ifndef PODCASTSERVICE_H
|
#ifndef PODCASTSERVICE_H
|
||||||
#define PODCASTSERVICE_H
|
#define PODCASTSERVICE_H
|
||||||
|
|
||||||
|
#include "internet/internetmodel.h"
|
||||||
#include "internet/internetservice.h"
|
#include "internet/internetservice.h"
|
||||||
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
class AddPodcastDialog;
|
class AddPodcastDialog;
|
||||||
|
class PodcastBackend;
|
||||||
|
|
||||||
class PodcastService : public InternetService {
|
class PodcastService : public InternetService {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -35,6 +36,12 @@ public:
|
||||||
static const char* kServiceName;
|
static const char* kServiceName;
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
Type_AddPodcast = InternetModel::TypeCount,
|
||||||
|
Type_Podcast,
|
||||||
|
Type_Episode
|
||||||
|
};
|
||||||
|
|
||||||
QStandardItem* CreateRootItem();
|
QStandardItem* CreateRootItem();
|
||||||
void LazyPopulate(QStandardItem* parent);
|
void LazyPopulate(QStandardItem* parent);
|
||||||
|
|
||||||
|
@ -46,10 +53,15 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void AddPodcast();
|
void AddPodcast();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PopulatePodcastList(QStandardItem* parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMenu* context_menu_;
|
QMenu* context_menu_;
|
||||||
QStandardItem* root_;
|
QStandardItem* root_;
|
||||||
|
|
||||||
|
PodcastBackend* backend_;
|
||||||
|
|
||||||
QScopedPointer<AddPodcastDialog> add_podcast_dialog_;
|
QScopedPointer<AddPodcastDialog> add_podcast_dialog_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue