Keep track of some statistics while searching for album covers, and show a statistics dialog at the end. Fixes issue 1921
This commit is contained in:
parent
42801a967b
commit
7773e98ebf
|
@ -100,6 +100,8 @@ set(SOURCES
|
||||||
covers/artloader.cpp
|
covers/artloader.cpp
|
||||||
covers/coverprovider.cpp
|
covers/coverprovider.cpp
|
||||||
covers/coverproviders.cpp
|
covers/coverproviders.cpp
|
||||||
|
covers/coversearchstatistics.cpp
|
||||||
|
covers/coversearchstatisticsdialog.cpp
|
||||||
covers/kittenloader.cpp
|
covers/kittenloader.cpp
|
||||||
|
|
||||||
devices/connecteddevice.cpp
|
devices/connecteddevice.cpp
|
||||||
|
@ -329,6 +331,7 @@ set(HEADERS
|
||||||
covers/artloader.h
|
covers/artloader.h
|
||||||
covers/coverprovider.h
|
covers/coverprovider.h
|
||||||
covers/coverproviders.h
|
covers/coverproviders.h
|
||||||
|
covers/coversearchstatisticsdialog.h
|
||||||
covers/kittenloader.h
|
covers/kittenloader.h
|
||||||
|
|
||||||
devices/connecteddevice.h
|
devices/connecteddevice.h
|
||||||
|
@ -499,6 +502,8 @@ set(HEADERS
|
||||||
)
|
)
|
||||||
|
|
||||||
set(UI
|
set(UI
|
||||||
|
covers/coversearchstatisticsdialog.ui
|
||||||
|
|
||||||
devices/deviceproperties.ui
|
devices/deviceproperties.ui
|
||||||
|
|
||||||
library/groupbydialog.ui
|
library/groupbydialog.ui
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
const int AlbumCoverFetcher::kMaxConcurrentRequests = 5;
|
const int AlbumCoverFetcher::kMaxConcurrentRequests = 5;
|
||||||
|
|
||||||
|
|
||||||
AlbumCoverFetcher::AlbumCoverFetcher(QObject* parent, QNetworkAccessManager* network)
|
AlbumCoverFetcher::AlbumCoverFetcher(QObject* parent, QNetworkAccessManager* network)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
network_(network ? network : new NetworkAccessManager(this)),
|
network_(network ? network : new NetworkAccessManager(this)),
|
||||||
|
@ -100,16 +101,17 @@ void AlbumCoverFetcher::StartRequests() {
|
||||||
SLOT(SingleCoverFetched(quint64, const QImage&)));
|
SLOT(SingleCoverFetched(quint64, const QImage&)));
|
||||||
|
|
||||||
search->Start();
|
search->Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverFetcher::SingleSearchFinished(quint64 request_id, CoverSearchResults results) {
|
void AlbumCoverFetcher::SingleSearchFinished(quint64 request_id, CoverSearchResults results) {
|
||||||
active_requests_.take(request_id)->deleteLater();
|
AlbumCoverFetcherSearch* search = active_requests_.take(request_id);
|
||||||
emit SearchFinished(request_id, results);
|
search->deleteLater();
|
||||||
|
emit SearchFinished(request_id, results, search->statistics());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverFetcher::SingleCoverFetched(quint64 request_id, const QImage& image) {
|
void AlbumCoverFetcher::SingleCoverFetched(quint64 request_id, const QImage& image) {
|
||||||
active_requests_.take(request_id)->deleteLater();
|
AlbumCoverFetcherSearch* search = active_requests_.take(request_id);
|
||||||
emit AlbumCoverFetched(request_id, image);
|
search->deleteLater();
|
||||||
|
emit AlbumCoverFetched(request_id, image, search->statistics());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#ifndef ALBUMCOVERFETCHER_H
|
#ifndef ALBUMCOVERFETCHER_H
|
||||||
#define ALBUMCOVERFETCHER_H
|
#define ALBUMCOVERFETCHER_H
|
||||||
|
|
||||||
|
#include "coversearchstatistics.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
@ -52,9 +54,9 @@ struct CoverSearchRequest {
|
||||||
// It contains an URL that leads to a found cover plus it's description (usually
|
// It contains an URL that leads to a found cover plus it's description (usually
|
||||||
// the "artist - album" string).
|
// the "artist - album" string).
|
||||||
struct CoverSearchResult {
|
struct CoverSearchResult {
|
||||||
// used for grouping in the user interface. defaults to the name of the
|
// used for grouping in the user interface. This is set automatically - don't
|
||||||
// provider that this result came from.
|
// set it manually in your cover provider.
|
||||||
QString category;
|
QString provider;
|
||||||
|
|
||||||
// description of this result (we suggest using the "artist - album" format)
|
// description of this result (we suggest using the "artist - album" format)
|
||||||
QString description;
|
QString description;
|
||||||
|
@ -64,11 +66,13 @@ struct CoverSearchResult {
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(CoverSearchResult);
|
Q_DECLARE_METATYPE(CoverSearchResult);
|
||||||
|
|
||||||
|
|
||||||
// This is a complete result of a single search request (a list of results, each
|
// This is a complete result of a single search request (a list of results, each
|
||||||
// describing one image, actually).
|
// describing one image, actually).
|
||||||
typedef QList<CoverSearchResult> CoverSearchResults;
|
typedef QList<CoverSearchResult> CoverSearchResults;
|
||||||
Q_DECLARE_METATYPE(QList<CoverSearchResult>);
|
Q_DECLARE_METATYPE(QList<CoverSearchResult>);
|
||||||
|
|
||||||
|
|
||||||
// This class searches for album covers for a given query or artist/album and
|
// This class searches for album covers for a given query or artist/album and
|
||||||
// returns URLs. It's NOT thread-safe.
|
// returns URLs. It's NOT thread-safe.
|
||||||
class AlbumCoverFetcher : public QObject {
|
class AlbumCoverFetcher : public QObject {
|
||||||
|
@ -86,8 +90,10 @@ class AlbumCoverFetcher : public QObject {
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void AlbumCoverFetched(quint64, const QImage& cover);
|
void AlbumCoverFetched(quint64, const QImage& cover,
|
||||||
void SearchFinished(quint64, const CoverSearchResults& results);
|
const CoverSearchStatistics& statistics);
|
||||||
|
void SearchFinished(quint64, const CoverSearchResults& results,
|
||||||
|
const CoverSearchStatistics& statistics);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SingleSearchFinished(quint64, CoverSearchResults results);
|
void SingleSearchFinished(quint64, CoverSearchResults results);
|
||||||
|
|
|
@ -68,6 +68,7 @@ void AlbumCoverFetcherSearch::Start() {
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
pending_requests_[id] = provider;
|
pending_requests_[id] = provider;
|
||||||
|
statistics_.network_requests_made_ ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,9 +78,9 @@ void AlbumCoverFetcherSearch::Start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CompareCategories(const CoverSearchResult& a,
|
static bool CompareProviders(const CoverSearchResult& a,
|
||||||
const CoverSearchResult& b) {
|
const CoverSearchResult& b) {
|
||||||
return a.category < b.category;
|
return a.provider < b.provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverFetcherSearch::ProviderSearchFinished(
|
void AlbumCoverFetcherSearch::ProviderSearchFinished(
|
||||||
|
@ -90,15 +91,14 @@ void AlbumCoverFetcherSearch::ProviderSearchFinished(
|
||||||
CoverProvider* provider = pending_requests_.take(id);
|
CoverProvider* provider = pending_requests_.take(id);
|
||||||
|
|
||||||
CoverSearchResults results_copy(results);
|
CoverSearchResults results_copy(results);
|
||||||
// Add categories to the results if the provider didn't specify them
|
// Set categories on the results
|
||||||
for (int i=0 ; i<results_copy.count() ; ++i) {
|
for (int i=0 ; i<results_copy.count() ; ++i) {
|
||||||
if (results_copy[i].category.isEmpty()) {
|
results_copy[i].provider = provider->name();
|
||||||
results_copy[i].category = provider->name();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add results from the current provider to our pool
|
// Add results from the current provider to our pool
|
||||||
results_.append(results_copy);
|
results_.append(results_copy);
|
||||||
|
statistics_.total_images_by_provider_[provider->name()] ++;
|
||||||
|
|
||||||
// do we have more providers left?
|
// do we have more providers left?
|
||||||
if(!pending_requests_.isEmpty()) {
|
if(!pending_requests_.isEmpty()) {
|
||||||
|
@ -121,6 +121,7 @@ void AlbumCoverFetcherSearch::AllProvidersFinished() {
|
||||||
|
|
||||||
// no results?
|
// no results?
|
||||||
if (results_.isEmpty()) {
|
if (results_.isEmpty()) {
|
||||||
|
statistics_.missing_images_ ++;
|
||||||
emit AlbumCoverFetched(request_.id, QImage());
|
emit AlbumCoverFetched(request_.id, QImage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -130,27 +131,29 @@ void AlbumCoverFetcherSearch::AllProvidersFinished() {
|
||||||
// from each category and use some heuristics to score them. If no images
|
// from each category and use some heuristics to score them. If no images
|
||||||
// are good enough we'll keep loading more images until we find one that is
|
// are good enough we'll keep loading more images until we find one that is
|
||||||
// or we run out of results.
|
// or we run out of results.
|
||||||
qStableSort(results_.begin(), results_.end(), CompareCategories);
|
qStableSort(results_.begin(), results_.end(), CompareProviders);
|
||||||
FetchMoreImages();
|
FetchMoreImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverFetcherSearch::FetchMoreImages() {
|
void AlbumCoverFetcherSearch::FetchMoreImages() {
|
||||||
// Try the first one in each category.
|
// Try the first one in each category.
|
||||||
QString last_category;
|
QString last_provider;
|
||||||
for (int i=0 ; i<results_.count() ; ++i) {
|
for (int i=0 ; i<results_.count() ; ++i) {
|
||||||
if (results_[i].category == last_category) {
|
if (results_[i].provider == last_provider) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoverSearchResult result = results_.takeAt(i--);
|
CoverSearchResult result = results_.takeAt(i--);
|
||||||
last_category = result.category;
|
last_provider = result.provider;
|
||||||
|
|
||||||
qLog(Debug) << "Loading" << result.image_url << "from" << result.category;
|
qLog(Debug) << "Loading" << result.image_url << "from" << result.provider;
|
||||||
|
|
||||||
QNetworkReply* image_reply = network_->get(QNetworkRequest(result.image_url));
|
QNetworkReply* image_reply = network_->get(QNetworkRequest(result.image_url));
|
||||||
connect(image_reply, SIGNAL(finished()), SLOT(ProviderCoverFetchFinished()));
|
connect(image_reply, SIGNAL(finished()), SLOT(ProviderCoverFetchFinished()));
|
||||||
pending_image_loads_ << image_reply;
|
pending_image_loads_[image_reply] = result.provider;
|
||||||
image_load_timeout_->AddReply(image_reply);
|
image_load_timeout_->AddReply(image_reply);
|
||||||
|
|
||||||
|
statistics_.network_requests_made_ ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending_image_loads_.isEmpty()) {
|
if (pending_image_loads_.isEmpty()) {
|
||||||
|
@ -162,7 +165,9 @@ void AlbumCoverFetcherSearch::FetchMoreImages() {
|
||||||
void AlbumCoverFetcherSearch::ProviderCoverFetchFinished() {
|
void AlbumCoverFetcherSearch::ProviderCoverFetchFinished() {
|
||||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
pending_image_loads_.removeAll(reply);
|
const QString provider = pending_image_loads_.take(reply);
|
||||||
|
|
||||||
|
statistics_.bytes_transferred_ += reply->bytesAvailable();
|
||||||
|
|
||||||
if (cancel_requested_) {
|
if (cancel_requested_) {
|
||||||
return;
|
return;
|
||||||
|
@ -176,7 +181,7 @@ void AlbumCoverFetcherSearch::ProviderCoverFetchFinished() {
|
||||||
qLog(Info) << "Error decoding image data from" << reply->url();
|
qLog(Info) << "Error decoding image data from" << reply->url();
|
||||||
} else {
|
} else {
|
||||||
const float score = ScoreImage(image);
|
const float score = ScoreImage(image);
|
||||||
candidate_images_.insertMulti(score, image);
|
candidate_images_.insertMulti(score, CandidateImage(provider, image));
|
||||||
|
|
||||||
qLog(Debug) << reply->url() << "scored" << score;
|
qLog(Debug) << reply->url() << "scored" << score;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +225,15 @@ void AlbumCoverFetcherSearch::SendBestImage() {
|
||||||
QImage image;
|
QImage image;
|
||||||
|
|
||||||
if (!candidate_images_.isEmpty()) {
|
if (!candidate_images_.isEmpty()) {
|
||||||
image = candidate_images_.values().back();
|
const CandidateImage best_image = candidate_images_.values().back();
|
||||||
|
image = best_image.second;
|
||||||
|
|
||||||
|
statistics_.chosen_images_by_provider_[best_image.first] ++;
|
||||||
|
statistics_.chosen_images_ ++;
|
||||||
|
statistics_.chosen_width_ += image.width();
|
||||||
|
statistics_.chosen_height_ += image.height();
|
||||||
|
} else {
|
||||||
|
statistics_.missing_images_ ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit AlbumCoverFetched(request_.id, image);
|
emit AlbumCoverFetched(request_.id, image);
|
||||||
|
@ -232,7 +245,7 @@ void AlbumCoverFetcherSearch::Cancel() {
|
||||||
if (!pending_requests_.isEmpty()) {
|
if (!pending_requests_.isEmpty()) {
|
||||||
TerminateSearch();
|
TerminateSearch();
|
||||||
} else if (!pending_image_loads_.isEmpty()) {
|
} else if (!pending_image_loads_.isEmpty()) {
|
||||||
foreach (QNetworkReply* reply, pending_image_loads_) {
|
foreach (QNetworkReply* reply, pending_image_loads_.keys()) {
|
||||||
reply->abort();
|
reply->abort();
|
||||||
}
|
}
|
||||||
pending_image_loads_.clear();
|
pending_image_loads_.clear();
|
||||||
|
|
|
@ -45,9 +45,12 @@ class AlbumCoverFetcherSearch : public QObject {
|
||||||
// is the caller's responsibility to delete the AlbumCoverFetcherSearch.
|
// is the caller's responsibility to delete the AlbumCoverFetcherSearch.
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
|
CoverSearchStatistics statistics() const { return statistics_; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// It's the end of search (when there was no fetch-me-a-cover request).
|
// It's the end of search (when there was no fetch-me-a-cover request).
|
||||||
void SearchFinished(quint64, const CoverSearchResults& results);
|
void SearchFinished(quint64, const CoverSearchResults& results);
|
||||||
|
|
||||||
// It's the end of search and we've fetched a cover.
|
// It's the end of search and we've fetched a cover.
|
||||||
void AlbumCoverFetched(quint64, const QImage& cover);
|
void AlbumCoverFetched(quint64, const QImage& cover);
|
||||||
|
|
||||||
|
@ -69,6 +72,8 @@ private:
|
||||||
static const int kTargetSize;
|
static const int kTargetSize;
|
||||||
static const float kGoodScore;
|
static const float kGoodScore;
|
||||||
|
|
||||||
|
CoverSearchStatistics statistics_;
|
||||||
|
|
||||||
// Search request encapsulated by this AlbumCoverFetcherSearch.
|
// Search request encapsulated by this AlbumCoverFetcherSearch.
|
||||||
CoverSearchRequest request_;
|
CoverSearchRequest request_;
|
||||||
|
|
||||||
|
@ -76,11 +81,12 @@ private:
|
||||||
CoverSearchResults results_;
|
CoverSearchResults results_;
|
||||||
|
|
||||||
QMap<int, CoverProvider*> pending_requests_;
|
QMap<int, CoverProvider*> pending_requests_;
|
||||||
QList<QNetworkReply*> pending_image_loads_;
|
QMap<QNetworkReply*, QString> pending_image_loads_;
|
||||||
NetworkTimeouts* image_load_timeout_;
|
NetworkTimeouts* image_load_timeout_;
|
||||||
|
|
||||||
// QMap happens to be sorted by key (score)
|
// QMap is sorted by key (score). Values are (provider_name, image)
|
||||||
QMap<float, QImage> candidate_images_;
|
typedef QPair<QString, QImage> CandidateImage;
|
||||||
|
QMap<float, CandidateImage> candidate_images_;
|
||||||
|
|
||||||
QNetworkAccessManager* network_;
|
QNetworkAccessManager* network_;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 "coversearchstatistics.h"
|
||||||
|
|
||||||
|
CoverSearchStatistics::CoverSearchStatistics()
|
||||||
|
: network_requests_made_(0),
|
||||||
|
bytes_transferred_(0),
|
||||||
|
chosen_images_(0),
|
||||||
|
missing_images_(0),
|
||||||
|
chosen_width_(0),
|
||||||
|
chosen_height_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CoverSearchStatistics& CoverSearchStatistics::operator +=(const CoverSearchStatistics& other) {
|
||||||
|
network_requests_made_ += other.network_requests_made_;
|
||||||
|
bytes_transferred_ += other.bytes_transferred_;
|
||||||
|
|
||||||
|
foreach (const QString& key, other.chosen_images_by_provider_.keys()) {
|
||||||
|
chosen_images_by_provider_[key] += other.chosen_images_by_provider_[key];
|
||||||
|
}
|
||||||
|
foreach (const QString& key, other.total_images_by_provider_.keys()) {
|
||||||
|
total_images_by_provider_[key] += other.total_images_by_provider_[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
chosen_images_ += other.chosen_images_;
|
||||||
|
missing_images_ += other.missing_images_;
|
||||||
|
|
||||||
|
chosen_width_ += other.chosen_width_;
|
||||||
|
chosen_height_ += other.chosen_height_;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CoverSearchStatistics::AverageDimensions() const {
|
||||||
|
if (chosen_images_ == 0) {
|
||||||
|
return "0x0";
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::number(chosen_width_ / chosen_images_) + "x" +
|
||||||
|
QString::number(chosen_height_ / chosen_images_);
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COVERSEARCHSTATISTICS_H
|
||||||
|
#define COVERSEARCHSTATISTICS_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
struct CoverSearchStatistics {
|
||||||
|
CoverSearchStatistics();
|
||||||
|
|
||||||
|
CoverSearchStatistics& operator +=(const CoverSearchStatistics& other);
|
||||||
|
|
||||||
|
quint64 network_requests_made_;
|
||||||
|
quint64 bytes_transferred_;
|
||||||
|
QMap<QString, quint64> total_images_by_provider_;
|
||||||
|
QMap<QString, quint64> chosen_images_by_provider_;
|
||||||
|
|
||||||
|
quint64 chosen_images_;
|
||||||
|
quint64 missing_images_;
|
||||||
|
|
||||||
|
quint64 chosen_width_;
|
||||||
|
quint64 chosen_height_;
|
||||||
|
|
||||||
|
QString AverageDimensions() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COVERSEARCHSTATISTICS_H
|
|
@ -0,0 +1,96 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 "coversearchstatisticsdialog.h"
|
||||||
|
#include "ui_coversearchstatisticsdialog.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
|
||||||
|
CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
|
||||||
|
: QDialog(parent),
|
||||||
|
ui_(new Ui_CoverSearchStatisticsDialog)
|
||||||
|
{
|
||||||
|
ui_->setupUi(this);
|
||||||
|
details_layout_ = new QVBoxLayout(ui_->details);
|
||||||
|
details_layout_->setSpacing(0);
|
||||||
|
|
||||||
|
setStyleSheet(
|
||||||
|
"#details {"
|
||||||
|
" background-color: palette(base);"
|
||||||
|
"}"
|
||||||
|
"#details QLabel[type=\"label\"] {"
|
||||||
|
" border: 2px solid transparent;"
|
||||||
|
" border-right: 2px solid palette(midlight);"
|
||||||
|
" margin-right: 10px;"
|
||||||
|
"}"
|
||||||
|
"#details QLabel[type=\"value\"] {"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" max-width: 100px;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoverSearchStatisticsDialog::~CoverSearchStatisticsDialog() {
|
||||||
|
delete ui_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoverSearchStatisticsDialog::Show(const CoverSearchStatistics& statistics) {
|
||||||
|
QStringList providers(statistics.total_images_by_provider_.keys());
|
||||||
|
qSort(providers);
|
||||||
|
|
||||||
|
ui_->summary->setText(tr("Got %1 covers out of %2 (%3 failed)")
|
||||||
|
.arg(statistics.chosen_images_)
|
||||||
|
.arg(statistics.chosen_images_ + statistics.missing_images_)
|
||||||
|
.arg(statistics.missing_images_));
|
||||||
|
|
||||||
|
foreach (const QString& provider, providers) {
|
||||||
|
AddLine(tr("Covers from %1").arg(provider),
|
||||||
|
QString::number(statistics.chosen_images_by_provider_[provider]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!providers.isEmpty()) {
|
||||||
|
AddSpacer();
|
||||||
|
}
|
||||||
|
|
||||||
|
AddLine(tr("Total network requests made"),
|
||||||
|
QString::number(statistics.network_requests_made_));
|
||||||
|
AddLine(tr("Average image size"), statistics.AverageDimensions());
|
||||||
|
AddLine(tr("Total bytes transferred"),
|
||||||
|
statistics.bytes_transferred_
|
||||||
|
? Utilities::PrettySize(statistics.bytes_transferred_)
|
||||||
|
: "0 bytes");
|
||||||
|
|
||||||
|
details_layout_->addStretch();
|
||||||
|
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoverSearchStatisticsDialog::AddLine(const QString& label, const QString& value) {
|
||||||
|
QLabel* label1 = new QLabel(label);
|
||||||
|
QLabel* label2 = new QLabel(value);
|
||||||
|
|
||||||
|
label1->setProperty("type", "label");
|
||||||
|
label2->setProperty("type", "value");
|
||||||
|
|
||||||
|
QHBoxLayout* layout = new QHBoxLayout;
|
||||||
|
layout->addWidget(label1);
|
||||||
|
layout->addWidget(label2);
|
||||||
|
details_layout_->addLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoverSearchStatisticsDialog::AddSpacer() {
|
||||||
|
details_layout_->addSpacing(20);
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COVERSEARCHSTATISTICSDIALOG_H
|
||||||
|
#define COVERSEARCHSTATISTICSDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
#include "coversearchstatistics.h"
|
||||||
|
|
||||||
|
class Ui_CoverSearchStatisticsDialog;
|
||||||
|
|
||||||
|
class QVBoxLayout;
|
||||||
|
|
||||||
|
class CoverSearchStatisticsDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
CoverSearchStatisticsDialog(QWidget* parent = 0);
|
||||||
|
~CoverSearchStatisticsDialog();
|
||||||
|
|
||||||
|
void Show(const CoverSearchStatistics& statistics);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddLine(const QString& label, const QString& value);
|
||||||
|
void AddSpacer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui_CoverSearchStatisticsDialog* ui_;
|
||||||
|
QVBoxLayout* details_layout_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COVERSEARCHSTATISTICSDIALOG_H
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CoverSearchStatisticsDialog</class>
|
||||||
|
<widget class="QDialog" name="CoverSearchStatisticsDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>425</width>
|
||||||
|
<height>214</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Fetch completed</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="summary">
|
||||||
|
<property name="text">
|
||||||
|
<string>Got %1 covers out of %2 (%3 failed)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="details">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Sunken</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>CoverSearchStatisticsDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>CoverSearchStatisticsDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -54,6 +54,11 @@
|
||||||
#include <taskmanager.h>
|
#include <taskmanager.h>
|
||||||
#include <urlhandler.h>
|
#include <urlhandler.h>
|
||||||
|
|
||||||
|
void PythonQtWrapper_AlbumCoverFetcherSearch::Cancel(AlbumCoverFetcherSearch* theWrappedObject)
|
||||||
|
{
|
||||||
|
( theWrappedObject->Cancel());
|
||||||
|
}
|
||||||
|
|
||||||
void PythonQtWrapper_AlbumCoverFetcherSearch::Start(AlbumCoverFetcherSearch* theWrappedObject)
|
void PythonQtWrapper_AlbumCoverFetcherSearch::Start(AlbumCoverFetcherSearch* theWrappedObject)
|
||||||
{
|
{
|
||||||
( theWrappedObject->Start());
|
( theWrappedObject->Start());
|
||||||
|
|
|
@ -61,6 +61,7 @@ class PythonQtWrapper_AlbumCoverFetcherSearch : public QObject
|
||||||
public:
|
public:
|
||||||
public slots:
|
public slots:
|
||||||
void delete_AlbumCoverFetcherSearch(AlbumCoverFetcherSearch* obj) { delete obj; }
|
void delete_AlbumCoverFetcherSearch(AlbumCoverFetcherSearch* obj) { delete obj; }
|
||||||
|
void Cancel(AlbumCoverFetcherSearch* theWrappedObject);
|
||||||
void Start(AlbumCoverFetcherSearch* theWrappedObject);
|
void Start(AlbumCoverFetcherSearch* theWrappedObject);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,8 +139,8 @@ PythonQtShell_CoverSearchResult* a = new PythonQtShell_CoverSearchResult();
|
||||||
*((CoverSearchResult*)a) = other;
|
*((CoverSearchResult*)a) = other;
|
||||||
return a; }
|
return a; }
|
||||||
void delete_CoverSearchResult(CoverSearchResult* obj) { delete obj; }
|
void delete_CoverSearchResult(CoverSearchResult* obj) { delete obj; }
|
||||||
void py_set_category(CoverSearchResult* theWrappedObject, QString category){ theWrappedObject->category = category; }
|
void py_set_provider(CoverSearchResult* theWrappedObject, QString provider){ theWrappedObject->provider = provider; }
|
||||||
QString py_get_category(CoverSearchResult* theWrappedObject){ return theWrappedObject->category; }
|
QString py_get_provider(CoverSearchResult* theWrappedObject){ return theWrappedObject->provider; }
|
||||||
void py_set_description(CoverSearchResult* theWrappedObject, QString description){ theWrappedObject->description = description; }
|
void py_set_description(CoverSearchResult* theWrappedObject, QString description){ theWrappedObject->description = description; }
|
||||||
QString py_get_description(CoverSearchResult* theWrappedObject){ return theWrappedObject->description; }
|
QString py_get_description(CoverSearchResult* theWrappedObject){ return theWrappedObject->description; }
|
||||||
void py_set_image_url(CoverSearchResult* theWrappedObject, QString image_url){ theWrappedObject->image_url = image_url; }
|
void py_set_image_url(CoverSearchResult* theWrappedObject, QString image_url){ theWrappedObject->image_url = image_url; }
|
||||||
|
|
|
@ -80,7 +80,6 @@ bool PythonScript::Unload() {
|
||||||
// running. This is important because those connections will hold references
|
// running. This is important because those connections will hold references
|
||||||
// to bound methods in the script's classes, so the classes won't get deleted.
|
// to bound methods in the script's classes, so the classes won't get deleted.
|
||||||
foreach (const SignalConnection& conn, signal_connections_) {
|
foreach (const SignalConnection& conn, signal_connections_) {
|
||||||
qLog(Debug) << "Disconnecting signal" << conn.signal_id_;
|
|
||||||
conn.receiver_->removeSignalHandler(conn.signal_id_, conn.callable_);
|
conn.receiver_->removeSignalHandler(conn.signal_id_, conn.callable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +119,5 @@ bool PythonScript::Unload() {
|
||||||
|
|
||||||
void PythonScript::RegisterSignalConnection(PythonQtSignalReceiver* receiver,
|
void PythonScript::RegisterSignalConnection(PythonQtSignalReceiver* receiver,
|
||||||
int signal_id, PyObject* callable) {
|
int signal_id, PyObject* callable) {
|
||||||
qLog(Debug) << "Signal" << signal_id << "registered to an object in" << info().id();
|
|
||||||
signal_connections_ << SignalConnection(receiver, signal_id, callable);
|
signal_connections_ << SignalConnection(receiver, signal_id, callable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,10 @@ msgstr ""
|
||||||
msgid "%1 tracks"
|
msgid "%1 tracks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, qt-format
|
||||||
|
msgid "%1 transferred"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, qt-format
|
#, qt-format
|
||||||
msgid "%1: Wiimotedev module"
|
msgid "%1: Wiimotedev module"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -472,6 +476,9 @@ msgstr ""
|
||||||
msgid "Average bitrate"
|
msgid "Average bitrate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Average image size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BPM"
|
msgid "BPM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1186,6 +1193,9 @@ msgstr ""
|
||||||
msgid "Fetch automatically"
|
msgid "Fetch automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Fetch completed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Fetching cover error"
|
msgid "Fetching cover error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2834,6 +2844,12 @@ msgstr ""
|
||||||
msgid "Toggle visibility for the pretty on-screen-display"
|
msgid "Toggle visibility for the pretty on-screen-display"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Total bytes transferred"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Total network requests made"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Track"
|
msgid "Track"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,10 @@ msgstr ""
|
||||||
msgid "%1 tracks"
|
msgid "%1 tracks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, qt-format
|
||||||
|
msgid "%1 transferred"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, qt-format
|
#, qt-format
|
||||||
msgid "%1: Wiimotedev module"
|
msgid "%1: Wiimotedev module"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -462,6 +466,9 @@ msgstr ""
|
||||||
msgid "Average bitrate"
|
msgid "Average bitrate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Average image size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BPM"
|
msgid "BPM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1176,6 +1183,9 @@ msgstr ""
|
||||||
msgid "Fetch automatically"
|
msgid "Fetch automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Fetch completed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Fetching cover error"
|
msgid "Fetching cover error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2824,6 +2834,12 @@ msgstr ""
|
||||||
msgid "Toggle visibility for the pretty on-screen-display"
|
msgid "Toggle visibility for the pretty on-screen-display"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Total bytes transferred"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Total network requests made"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Track"
|
msgid "Track"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
#include "albumcoversearcher.h"
|
#include "albumcoversearcher.h"
|
||||||
#include "iconloader.h"
|
#include "iconloader.h"
|
||||||
#include "ui_albumcovermanager.h"
|
#include "ui_albumcovermanager.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
#include "covers/albumcoverfetcher.h"
|
#include "covers/albumcoverfetcher.h"
|
||||||
#include "covers/coverproviders.h"
|
#include "covers/coverproviders.h"
|
||||||
|
#include "covers/coversearchstatisticsdialog.h"
|
||||||
#include "library/librarybackend.h"
|
#include "library/librarybackend.h"
|
||||||
#include "library/libraryquery.h"
|
#include "library/libraryquery.h"
|
||||||
#include "library/sqlrow.h"
|
#include "library/sqlrow.h"
|
||||||
|
@ -59,9 +61,7 @@ AlbumCoverManager::AlbumCoverManager(LibraryBackend* backend, QWidget* parent,
|
||||||
all_artists_icon_(IconLoader::Load("x-clementine-album")),
|
all_artists_icon_(IconLoader::Load("x-clementine-album")),
|
||||||
context_menu_(new QMenu(this)),
|
context_menu_(new QMenu(this)),
|
||||||
progress_bar_(new QProgressBar(this)),
|
progress_bar_(new QProgressBar(this)),
|
||||||
jobs_(0),
|
jobs_(0)
|
||||||
got_covers_(0),
|
|
||||||
missing_covers_(0)
|
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
ui_->albums->set_cover_manager(this);
|
ui_->albums->set_cover_manager(this);
|
||||||
|
@ -155,8 +155,8 @@ void AlbumCoverManager::Init() {
|
||||||
connect(filter_group, SIGNAL(triggered(QAction*)), SLOT(UpdateFilter()));
|
connect(filter_group, SIGNAL(triggered(QAction*)), SLOT(UpdateFilter()));
|
||||||
connect(ui_->view, SIGNAL(clicked()), ui_->view, SLOT(showMenu()));
|
connect(ui_->view, SIGNAL(clicked()), ui_->view, SLOT(showMenu()));
|
||||||
connect(ui_->fetch, SIGNAL(clicked()), SLOT(FetchAlbumCovers()));
|
connect(ui_->fetch, SIGNAL(clicked()), SLOT(FetchAlbumCovers()));
|
||||||
connect(cover_fetcher_, SIGNAL(AlbumCoverFetched(quint64,QImage)),
|
connect(cover_fetcher_, SIGNAL(AlbumCoverFetched(quint64,QImage,CoverSearchStatistics)),
|
||||||
SLOT(AlbumCoverFetched(quint64,QImage)));
|
SLOT(AlbumCoverFetched(quint64,QImage,CoverSearchStatistics)));
|
||||||
connect(ui_->action_fetch, SIGNAL(triggered()), SLOT(FetchSingleCover()));
|
connect(ui_->action_fetch, SIGNAL(triggered()), SLOT(FetchSingleCover()));
|
||||||
connect(ui_->albums, SIGNAL(doubleClicked(QModelIndex)), SLOT(AlbumDoubleClicked(QModelIndex)));
|
connect(ui_->albums, SIGNAL(doubleClicked(QModelIndex)), SLOT(AlbumDoubleClicked(QModelIndex)));
|
||||||
connect(ui_->action_add_to_playlist, SIGNAL(triggered()), SLOT(AddSelectedToPlaylist()));
|
connect(ui_->action_add_to_playlist, SIGNAL(triggered()), SLOT(AddSelectedToPlaylist()));
|
||||||
|
@ -384,19 +384,17 @@ void AlbumCoverManager::FetchAlbumCovers() {
|
||||||
|
|
||||||
progress_bar_->setMaximum(jobs_);
|
progress_bar_->setMaximum(jobs_);
|
||||||
progress_bar_->show();
|
progress_bar_->show();
|
||||||
|
fetch_statistics_ = CoverSearchStatistics();
|
||||||
UpdateStatusText();
|
UpdateStatusText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage &image) {
|
void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage& image,
|
||||||
|
const CoverSearchStatistics& statistics) {
|
||||||
if (!cover_fetching_tasks_.contains(id))
|
if (!cover_fetching_tasks_.contains(id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QListWidgetItem* item = cover_fetching_tasks_.take(id);
|
QListWidgetItem* item = cover_fetching_tasks_.take(id);
|
||||||
if (image.isNull()) {
|
if (!image.isNull()) {
|
||||||
missing_covers_ ++;
|
|
||||||
} else {
|
|
||||||
got_covers_ ++;
|
|
||||||
|
|
||||||
SaveAndSetCover(item, image);
|
SaveAndSetCover(item, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,22 +402,34 @@ void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage &image) {
|
||||||
ResetFetchCoversButton();
|
ResetFetchCoversButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetch_statistics_ += statistics;
|
||||||
UpdateStatusText();
|
UpdateStatusText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumCoverManager::UpdateStatusText() {
|
void AlbumCoverManager::UpdateStatusText() {
|
||||||
QString message = tr("Got %1 covers out of %2 (%3 failed)")
|
QString message = tr("Got %1 covers out of %2 (%3 failed)")
|
||||||
.arg(got_covers_).arg(jobs_).arg(missing_covers_);
|
.arg(fetch_statistics_.chosen_images_)
|
||||||
|
.arg(jobs_)
|
||||||
|
.arg(fetch_statistics_.missing_images_);
|
||||||
|
|
||||||
|
if (fetch_statistics_.bytes_transferred_) {
|
||||||
|
message += ", " + tr("%1 transferred")
|
||||||
|
.arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
|
||||||
|
}
|
||||||
|
|
||||||
statusBar()->showMessage(message);
|
statusBar()->showMessage(message);
|
||||||
progress_bar_->setValue(got_covers_ + missing_covers_);
|
progress_bar_->setValue(fetch_statistics_.chosen_images_ +
|
||||||
|
fetch_statistics_.missing_images_);
|
||||||
|
|
||||||
if (cover_fetching_tasks_.isEmpty()) {
|
if (cover_fetching_tasks_.isEmpty()) {
|
||||||
QTimer::singleShot(2000, statusBar(), SLOT(clearMessage()));
|
QTimer::singleShot(2000, statusBar(), SLOT(clearMessage()));
|
||||||
progress_bar_->hide();
|
progress_bar_->hide();
|
||||||
|
|
||||||
|
CoverSearchStatisticsDialog* dialog = new CoverSearchStatisticsDialog(this);
|
||||||
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
dialog->Show(fetch_statistics_);
|
||||||
|
|
||||||
jobs_ = 0;
|
jobs_ = 0;
|
||||||
got_covers_ = 0;
|
|
||||||
missing_covers_ = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "core/backgroundthread.h"
|
#include "core/backgroundthread.h"
|
||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
#include "covers/albumcoverloader.h"
|
#include "covers/albumcoverloader.h"
|
||||||
|
#include "covers/coversearchstatistics.h"
|
||||||
|
|
||||||
class AlbumCoverChoiceController;
|
class AlbumCoverChoiceController;
|
||||||
class AlbumCoverFetcher;
|
class AlbumCoverFetcher;
|
||||||
|
@ -78,7 +79,8 @@ class AlbumCoverManager : public QMainWindow {
|
||||||
void CoverImageLoaded(quint64 id, const QImage& image);
|
void CoverImageLoaded(quint64 id, const QImage& image);
|
||||||
void UpdateFilter();
|
void UpdateFilter();
|
||||||
void FetchAlbumCovers();
|
void FetchAlbumCovers();
|
||||||
void AlbumCoverFetched(quint64 id, const QImage& image);
|
void AlbumCoverFetched(quint64 id, const QImage& image,
|
||||||
|
const CoverSearchStatistics& statistics);
|
||||||
|
|
||||||
// On the context menu
|
// On the context menu
|
||||||
void FetchSingleCover();
|
void FetchSingleCover();
|
||||||
|
@ -152,6 +154,7 @@ class AlbumCoverManager : public QMainWindow {
|
||||||
|
|
||||||
AlbumCoverFetcher* cover_fetcher_;
|
AlbumCoverFetcher* cover_fetcher_;
|
||||||
QMap<quint64, QListWidgetItem*> cover_fetching_tasks_;
|
QMap<quint64, QListWidgetItem*> cover_fetching_tasks_;
|
||||||
|
CoverSearchStatistics fetch_statistics_;
|
||||||
|
|
||||||
AlbumCoverSearcher* cover_searcher_;
|
AlbumCoverSearcher* cover_searcher_;
|
||||||
|
|
||||||
|
@ -165,8 +168,6 @@ class AlbumCoverManager : public QMainWindow {
|
||||||
|
|
||||||
QProgressBar* progress_bar_;
|
QProgressBar* progress_bar_;
|
||||||
int jobs_;
|
int jobs_;
|
||||||
int got_covers_;
|
|
||||||
int missing_covers_;
|
|
||||||
|
|
||||||
LineEditInterface* filter_;
|
LineEditInterface* filter_;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ AlbumCoverSearcher::~AlbumCoverSearcher() {
|
||||||
void AlbumCoverSearcher::Init(AlbumCoverFetcher* fetcher) {
|
void AlbumCoverSearcher::Init(AlbumCoverFetcher* fetcher) {
|
||||||
fetcher_ = fetcher;
|
fetcher_ = fetcher;
|
||||||
|
|
||||||
connect(fetcher_, SIGNAL(SearchFinished(quint64,CoverSearchResults)), SLOT(SearchFinished(quint64,CoverSearchResults)));
|
connect(fetcher_, SIGNAL(SearchFinished(quint64,CoverSearchResults,CoverSearchStatistics)),
|
||||||
|
SLOT(SearchFinished(quint64,CoverSearchResults)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage AlbumCoverSearcher::Exec(const QString& artist, const QString& album) {
|
QImage AlbumCoverSearcher::Exec(const QString& artist, const QString& album) {
|
||||||
|
@ -126,7 +127,7 @@ void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& re
|
||||||
item->setData(id, Role_ImageRequestId);
|
item->setData(id, Role_ImageRequestId);
|
||||||
item->setData(false, Role_ImageFetchFinished);
|
item->setData(false, Role_ImageFetchFinished);
|
||||||
item->setData(QVariant(Qt::AlignTop | Qt::AlignHCenter), Qt::TextAlignmentRole);
|
item->setData(QVariant(Qt::AlignTop | Qt::AlignHCenter), Qt::TextAlignmentRole);
|
||||||
item->setData(result.category, GroupedIconView::Role_Group);
|
item->setData(result.provider, GroupedIconView::Role_Group);
|
||||||
|
|
||||||
model_->appendRow(item);
|
model_->appendRow(item);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue