1
0
mirror of https://github.com/clementine-player/Clementine synced 2025-01-30 11:04:57 +01:00

Make podcast discovery pages without any extra widgets nicer. Load gpodder.net podcasts within tags.

This commit is contained in:
David Sansome 2012-03-06 01:17:45 +00:00
parent 4a16710b69
commit 56cc4a9140
10 changed files with 120 additions and 16 deletions

View File

@ -66,6 +66,7 @@ void AddPodcastDialog::ChangePage(int index) {
AddPodcastPage* page = pages_[index];
ui_->stack->setCurrentIndex(index);
ui_->stack->setVisible(page->has_visible_widget());
ui_->results->setModel(page->model());
ui_->results->setRootIsDecorated(page->model()->is_tree());
@ -76,10 +77,14 @@ void AddPodcastDialog::ChangePage(int index) {
SLOT(ChangePodcast(QModelIndex)));
ChangePodcast(QModelIndex());
PageBusyChanged(page_is_busy_[index]);
page->Show();
}
void AddPodcastDialog::ChangePodcast(const QModelIndex& current) {
if (!current.isValid()) {
if (!current.isValid() ||
current.data(PodcastDiscoveryModel::Role_Type).toInt() !=
PodcastDiscoveryModel::Type_Podcast) {
ui_->details->hide();
return;
}

View File

@ -53,7 +53,7 @@
<item>
<widget class="QStackedWidget" name="results_stack">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="results_page">
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -65,6 +65,12 @@
</property>
<item>
<widget class="QTreeView" name="results">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>

View File

@ -31,6 +31,9 @@ public:
PodcastDiscoveryModel* model() const { return model_; }
virtual bool has_visible_widget() const { return true; }
virtual void Show() {}
signals:
void Busy(bool busy);

View File

@ -1,32 +1,82 @@
/* This file is part of Clementine.
Copyright 2012, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gpoddertoptagsmodel.h"
#include "gpoddertoptagspage.h"
#include "podcast.h"
#include "core/closure.h"
GPodderTopTagsModel::GPodderTopTagsModel(Application* app, QObject* parent)
: PodcastDiscoveryModel(app, parent)
#include <ApiRequest.h>
GPodderTopTagsModel::GPodderTopTagsModel(mygpo::ApiRequest* api, Application* app,
QObject* parent)
: PodcastDiscoveryModel(app, parent),
api_(api)
{
set_is_tree(true);
}
bool GPodderTopTagsModel::hasChildren(const QModelIndex& parent) const {
if (parent.isValid() && parent.data(Role_Type).toInt() == Type_Folder) {
if (parent.isValid() &&
parent.data(Role_Type).toInt() == Type_Folder) {
return true;
}
return PodcastDiscoveryModel::hasChildren(parent);
}
bool GPodderTopTagsModel::canFetchMore(const QModelIndex& parent) const {
if (parent.isValid() &&
parent.data(Role_Type).toInt() == Type_Folder &&
parent.data(Role_HasLazyLoaded).toBool() == false) {
return true;
}
return PodcastDiscoveryModel::canFetchMore(parent);
}
void GPodderTopTagsModel::fetchMore(const QModelIndex& parent) {
if (!parent.isValid() ||
parent.data(Role_Type).toInt() != Type_Folder ||
parent.data(Role_HasLazyLoaded).toBool()) {
return;
}
setData(parent, true, Role_HasLazyLoaded);
mygpo::PodcastList* list =
api_->podcastsOfTag(GPodderTopTagsPage::kMaxTagCount, parent.data().toString());
NewClosure(list, SIGNAL(finished()),
this, SLOT(PodcastsOfTagFinished(QModelIndex,mygpo::PodcastList*)),
parent, list);
}
void GPodderTopTagsModel::PodcastsOfTagFinished(const QModelIndex& parent,
mygpo::PodcastList* list) {
list->deleteLater();
QStandardItem* parent_item = itemFromIndex(parent);
if (!parent_item)
return;
foreach (mygpo::PodcastPtr gpo_podcast, list->list()) {
Podcast podcast;
podcast.InitFromGpo(gpo_podcast.data());
parent_item->appendRow(CreatePodcastItem(podcast));
}
}

View File

@ -20,13 +20,33 @@
#include "podcastdiscoverymodel.h"
namespace mygpo {
class ApiRequest;
class PodcastList;
}
class GPodderTopTagsModel : public PodcastDiscoveryModel {
Q_OBJECT
public:
GPodderTopTagsModel(Application* app, QObject* parent = 0);
GPodderTopTagsModel(mygpo::ApiRequest* api, Application* app,
QObject* parent = 0);
enum Role {
Role_HasLazyLoaded = PodcastDiscoveryModel::RoleCount,
RoleCount
};
bool hasChildren(const QModelIndex& parent) const;
bool canFetchMore(const QModelIndex& parent) const;
void fetchMore(const QModelIndex& parent);
private slots:
void PodcastsOfTagFinished(const QModelIndex& parent, mygpo::PodcastList* list);
private:
mygpo::ApiRequest* api_;
};
#endif // GPODDERTOPTAGSMODEL_H

View File

@ -34,16 +34,14 @@ GPodderTopTagsPage::GPodderTopTagsPage(Application* app, QWidget* parent)
setWindowTitle(tr("Browse gpodder.net"));
setWindowIcon(QIcon(":providers/mygpo32.png"));
SetModel(new GPodderTopTagsModel(app, this));
SetModel(new GPodderTopTagsModel(api_, app, this));
}
GPodderTopTagsPage::~GPodderTopTagsPage() {
delete api_;
}
void GPodderTopTagsPage::showEvent(QShowEvent* e) {
QWidget::showEvent(e);
void GPodderTopTagsPage::Show() {
if (!done_initial_load_) {
// Start the request for list of top-level tags
emit Busy(true);

View File

@ -38,8 +38,8 @@ public:
static const int kMaxTagCount;
private:
void showEvent(QShowEvent* e);
virtual bool has_visible_widget() const { return false; }
virtual void Show();
private slots:
void TagListLoaded(mygpo::TagList* tag_list);

View File

@ -20,6 +20,8 @@
#include <QDataStream>
#include <Podcast.h>
const QStringList Podcast::kColumns = QStringList()
<< "url" << "title" << "description" << "copyright" << "link"
<< "image_url" << "author" << "owner_name" << "author_email" << "extra";
@ -140,3 +142,15 @@ void Podcast::BindToQuery(QSqlQuery* query) const {
query->bindValue(":extra", extra);
}
void Podcast::InitFromGpo(const mygpo::Podcast* podcast) {
d->url_ = podcast->url();
d->title_ = podcast->title();
d->description_ = podcast->description();
d->link_ = podcast->website();
d->image_url_ = podcast->logoUrl();
set_extra("gpodder:subscribers", podcast->subscribers());
set_extra("gpodder:subscribers_last_week", podcast->subscribersLastWeek());
set_extra("gpodder:page", podcast->mygpoUrl());
}

View File

@ -25,6 +25,10 @@
#include <QUrl>
#include <QVariantMap>
namespace mygpo {
class Podcast;
}
class Podcast {
public:
Podcast();
@ -37,6 +41,8 @@ public:
static const QString kUpdateSpec;
void InitFromQuery(const QSqlQuery& query);
void InitFromGpo(const mygpo::Podcast* podcast);
void BindToQuery(QSqlQuery* query) const;
bool is_valid() const { return database_id() != -1; }

View File

@ -38,7 +38,9 @@ public:
enum Role {
Role_Podcast = Qt::UserRole,
Role_Type
Role_Type,
RoleCount
};
bool is_tree() const { return is_tree_; }