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

Show a Loading... indicator for the gpodder, lazy load images properly

This commit is contained in:
David Sansome 2012-03-06 16:37:15 +00:00
parent 3a88d8fcda
commit e8a879372d
6 changed files with 146 additions and 20 deletions

View File

@ -32,6 +32,7 @@ AddPodcastDialog::AddPodcastDialog(Application* app, QWidget* parent)
{
ui_->setupUi(this);
ui_->details->SetApplication(app);
ui_->results->SetExpandOnReset(false);
ui_->results_stack->setCurrentWidget(ui_->results_page);
fader_ = new WidgetFadeHelper(ui_->details_scroll_area);

View File

@ -53,7 +53,7 @@
<item>
<widget class="QStackedWidget" name="results_stack">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="results_page">
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -64,7 +64,7 @@
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="results">
<widget class="AutoExpandingTreeView" name="results">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
@ -80,15 +80,61 @@
</widget>
<widget class="QWidget" name="busy_page">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="BusyIndicator" name="widget" native="true">
<property name="text" stdset="0">
<string>Loading...</string>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>192</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="BusyIndicator" name="widget" native="true">
<property name="text" stdset="0">
<string>Loading...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
@ -97,8 +143,8 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>367</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
@ -168,6 +214,11 @@
<header>podcasts/podcastinfowidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>AutoExpandingTreeView</class>
<extends>QTreeView</extends>
<header>widgets/autoexpandingtreeview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>

View File

@ -22,6 +22,8 @@
#include <ApiRequest.h>
#include <QMessageBox>
GPodderTopTagsModel::GPodderTopTagsModel(mygpo::ApiRequest* api, Application* app,
QObject* parent)
: PodcastDiscoveryModel(app, parent),
@ -57,24 +59,36 @@ void GPodderTopTagsModel::fetchMore(const QModelIndex& parent) {
}
setData(parent, true, Role_HasLazyLoaded);
qLog(Debug) << "Fetching podcasts for" << parent.data().toString();
// Create a little Loading... item.
itemFromIndex(parent)->appendRow(CreateLoadingIndicator());
mygpo::PodcastList* list =
api_->podcastsOfTag(GPodderTopTagsPage::kMaxTagCount, parent.data().toString());
NewClosure(list, SIGNAL(finished()),
this, SLOT(PodcastsOfTagFinished(QModelIndex,mygpo::PodcastList*)),
parent, list);
NewClosure(list, SIGNAL(parseError()),
this, SLOT(PodcastsOfTagFailed(QModelIndex,mygpo::PodcastList*)),
parent, list);
NewClosure(list, SIGNAL(requestError(QNetworkReply::NetworkError)),
this, SLOT(PodcastsOfTagFailed(QModelIndex,mygpo::PodcastList*)),
parent, list);
}
void GPodderTopTagsModel::PodcastsOfTagFinished(const QModelIndex& parent,
mygpo::PodcastList* list) {
list->deleteLater();
qLog(Debug) << "Tag list finished";
QStandardItem* parent_item = itemFromIndex(parent);
if (!parent_item)
return;
// Remove the Loading... item.
while (parent_item->hasChildren()) {
parent_item->removeRow(0);
}
foreach (mygpo::PodcastPtr gpo_podcast, list->list()) {
Podcast podcast;
podcast.InitFromGpo(gpo_podcast.data());
@ -82,3 +96,29 @@ void GPodderTopTagsModel::PodcastsOfTagFinished(const QModelIndex& parent,
parent_item->appendRow(CreatePodcastItem(podcast));
}
}
void GPodderTopTagsModel::PodcastsOfTagFailed(const QModelIndex& parent,
mygpo::PodcastList* list) {
list->deleteLater();
QStandardItem* parent_item = itemFromIndex(parent);
if (!parent_item)
return;
// Remove the Loading... item.
while (parent_item->hasChildren()) {
parent_item->removeRow(0);
}
if (QMessageBox::warning(
NULL, tr("Failed to fetch podcasts"),
tr("There was a problem communicating with gpodder.net"),
QMessageBox::Retry | QMessageBox::Close,
QMessageBox::Retry) != QMessageBox::Retry) {
return;
}
// Try fetching the list again.
setData(parent, false, Role_HasLazyLoaded);
fetchMore(parent);
}

View File

@ -44,6 +44,7 @@ public:
private slots:
void PodcastsOfTagFinished(const QModelIndex& parent, mygpo::PodcastList* list);
void PodcastsOfTagFailed(const QModelIndex& parent, mygpo::PodcastList* list);
private:
mygpo::ApiRequest* api_;

View File

@ -37,20 +37,23 @@ PodcastDiscoveryModel::PodcastDiscoveryModel(Application* app, QObject* parent)
connect(this, SIGNAL(modelAboutToBeReset()), SLOT(CancelPendingImages()));
}
QVariant PodcastDiscoveryModel::data(const QModelIndex& index, int role) const {
if (index.isValid() &&
role == Qt::DecorationRole &&
QStandardItemModel::data(index, Role_Type).toInt() == Type_Podcast &&
QStandardItemModel::data(index, Role_StartedLoadingImage).toBool() == false) {
const_cast<PodcastDiscoveryModel*>(this)->LazyLoadImage(index);
}
return QStandardItemModel::data(index, role);
}
QStandardItem* PodcastDiscoveryModel::CreatePodcastItem(const Podcast& podcast) {
QStandardItem* item = new QStandardItem;
item->setIcon(default_icon_);
item->setText(podcast.title());
item->setData(QVariant::fromValue(podcast), Role_Podcast);
item->setData(Type_Podcast, Role_Type);
if (podcast.image_url().isValid()) {
// Start loading an image for this item.
quint64 id = app_->album_cover_loader()->LoadImageAsync(
cover_options_, podcast.image_url().toString(), QString());
pending_covers_[id] = item;
}
return item;
}
@ -66,15 +69,37 @@ QStandardItem* PodcastDiscoveryModel::CreateFolder(const QString& name) {
return item;
}
void PodcastDiscoveryModel::LazyLoadImage(const QModelIndex& index) {
QStandardItem* item = itemFromIndex(index);
item->setData(true, Role_StartedLoadingImage);
Podcast podcast = index.data(Role_Podcast).value<Podcast>();
if (podcast.image_url().isValid()) {
quint64 id = app_->album_cover_loader()->LoadImageAsync(
cover_options_, podcast.image_url().toString(), QString());
pending_covers_[id] = item;
}
}
void PodcastDiscoveryModel::ImageLoaded(quint64 id, const QImage& image) {
QStandardItem* item = pending_covers_.take(id);
if (!item)
return;
item->setIcon(QIcon(QPixmap::fromImage(image)));
if (!image.isNull()) {
item->setIcon(QIcon(QPixmap::fromImage(image)));
}
}
void PodcastDiscoveryModel::CancelPendingImages() {
app_->album_cover_loader()->CancelTasks(QSet<quint64>::fromList(pending_covers_.keys()));
pending_covers_.clear();
}
QStandardItem* PodcastDiscoveryModel::CreateLoadingIndicator() {
QStandardItem* item = new QStandardItem;
item->setText(tr("Loading..."));
item->setData(Type_LoadingIndicator, Role_Type);
return item;
}

View File

@ -33,12 +33,14 @@ public:
enum Type {
Type_Folder,
Type_Podcast
Type_Podcast,
Type_LoadingIndicator
};
enum Role {
Role_Podcast = Qt::UserRole,
Role_Type,
Role_StartedLoadingImage,
RoleCount
};
@ -48,10 +50,16 @@ public:
QStandardItem* CreatePodcastItem(const Podcast& podcast);
QStandardItem* CreateFolder(const QString& name);
QStandardItem* CreateLoadingIndicator();
QVariant data(const QModelIndex& index, int role) const;
private slots:
void CancelPendingImages();
void ImageLoaded(quint64 id, const QImage& image);
private:
void LazyLoadImage(const QModelIndex& index);
private:
Application* app_;