Add some more options to the album cover manager: show fullsize, fetch automatically, choose manually, unset cover

This commit is contained in:
David Sansome 2010-03-03 14:29:53 +00:00
parent 4652e47c65
commit 101b30c4b5
8 changed files with 202 additions and 19 deletions

View File

@ -64,5 +64,6 @@
<file>nocover.png</file>
<file>view-choose.png</file>
<file>download.png</file>
<file>zoom-in.png</file>
</qresource>
</RCC>

BIN
data/zoom-in.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -4,6 +4,8 @@
#include <QDir>
#include <QCoreApplication>
const char* AlbumCoverLoader::kManuallyUnsetCover = "(unset)";
AlbumCoverLoader::AlbumCoverLoader(QObject* parent)
: QObject(parent),
height_(120),
@ -50,11 +52,7 @@ void AlbumCoverLoader::ProcessTasks() {
}
// Try to load the image
QImage image;
if (!task.art_manual.isEmpty())
image.load(task.art_manual);
if (!task.art_automatic.isEmpty() && image.isNull())
image.load(task.art_automatic);
QImage image(TryLoadImage(task.art_automatic, task.art_manual));
if (!image.isNull()) {
// Scale the image down
@ -75,3 +73,25 @@ void AlbumCoverLoader::ProcessTasks() {
emit ImageLoaded(task.id, image);
}
}
QImage AlbumCoverLoader::TryLoadImage(const QString &automatic, const QString &manual) {
QImage ret;
if (manual == kManuallyUnsetCover)
return ret;
if (!manual.isEmpty())
ret.load(manual);
if (!automatic.isEmpty() && ret.isNull())
ret.load(automatic);
return ret;
}
QPixmap AlbumCoverLoader::TryLoadPixmap(const QString &automatic, const QString &manual) {
QPixmap ret;
if (manual == kManuallyUnsetCover)
return ret;
if (!manual.isEmpty())
ret.load(manual);
if (!automatic.isEmpty() && ret.isNull())
ret.load(automatic);
return ret;
}

View File

@ -21,6 +21,11 @@ class AlbumCoverLoader : public QObject {
void Clear();
static QImage TryLoadImage(const QString& automatic, const QString& manual);
static QPixmap TryLoadPixmap(const QString& automatic, const QString& manual);
static const char* kManuallyUnsetCover;
signals:
void ImageLoaded(quint64 id, const QImage& image);

View File

@ -12,6 +12,10 @@
#include <QDir>
#include <QEvent>
#include <QScrollBar>
#include <QContextMenuEvent>
#include <QLabel>
#include <QFileDialog>
#include <QMessageBox>
const char* AlbumCoverManager::kSettingsGroup = "CoverManager";
@ -21,7 +25,8 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
cover_loader_(new BackgroundThread<AlbumCoverLoader>(this)),
cover_fetcher_(new AlbumCoverFetcher(this)),
artist_icon_(":/artist.png"),
all_artists_icon_(":/album.png")
all_artists_icon_(":/album.png"),
context_menu_(new QMenu(this))
{
ui_.setupUi(this);
@ -37,9 +42,9 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
// View menu
QActionGroup* filter_group = new QActionGroup(this);
filter_all_ = filter_group->addAction("All albums");
filter_with_covers_ = filter_group->addAction("Albums with covers");
filter_without_covers_ = filter_group->addAction("Albums without covers");
filter_all_ = filter_group->addAction(tr("All albums"));
filter_with_covers_ = filter_group->addAction(tr("Albums with covers"));
filter_without_covers_ = filter_group->addAction(tr("Albums without covers"));
filter_all_->setCheckable(true);
filter_with_covers_->setCheckable(true);
filter_without_covers_->setCheckable(true);
@ -51,6 +56,14 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
ui_.view->setMenu(view_menu);
// Context menu
context_menu_->addAction(ui_.action_show_fullsize);
context_menu_->addAction(ui_.action_fetch);
context_menu_->addAction(ui_.action_choose_manual);
context_menu_->addSeparator();
context_menu_->addAction(ui_.action_unset_cover);
ui_.albums->installEventFilter(this);
// Connections
connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised()));
connect(ui_.artists, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
@ -61,6 +74,10 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
connect(ui_.fetch, SIGNAL(clicked()), SLOT(FetchAlbumCovers()));
connect(cover_fetcher_, SIGNAL(AlbumCoverFetched(quint64,QImage)),
SLOT(AlbumCoverFetched(quint64,QImage)));
connect(ui_.action_show_fullsize, SIGNAL(triggered()), SLOT(ShowFullsize()));
connect(ui_.action_fetch, SIGNAL(triggered()), SLOT(FetchSingleCover()));
connect(ui_.action_choose_manual, SIGNAL(triggered()), SLOT(ChooseManualCover()));
connect(ui_.action_unset_cover, SIGNAL(triggered()), SLOT(UnsetCover()));
// Restore settings
QSettings s;
@ -122,7 +139,7 @@ void AlbumCoverManager::Reset() {
return;
ui_.artists->clear();
new QListWidgetItem(all_artists_icon_, "All artists", ui_.artists, All_Artists);
new QListWidgetItem(all_artists_icon_, tr("All artists"), ui_.artists, All_Artists);
foreach (const QString& artist, backend_->GetAllArtists()) {
if (artist.isEmpty())
@ -143,6 +160,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
artist = current->text();
ui_.albums->clear();
context_menu_items_.clear();
CancelRequests();
foreach (const LibraryBackend::Album& info,
@ -154,6 +172,8 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
quint64 id = cover_loader_->Worker()->LoadImageAsync(
info.art_automatic, info.art_manual);
item->setData(Role_PathAutomatic, info.art_automatic);
item->setData(Role_PathManual, info.art_manual);
cover_loading_tasks_[id] = item;
}
}
@ -236,6 +256,7 @@ void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage &image) {
// Update the icon in our list
quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), path);
item->setData(Role_PathManual, path);
cover_loading_tasks_[id] = item;
}
@ -250,10 +271,99 @@ bool AlbumCoverManager::event(QEvent* e) {
// We seem to have to reset them to sensible values each time the contents
// of ui_.albums changes.
ui_.albums->setVerticalScrollMode(QListWidget::ScrollPerPixel);
//ui_.albums->verticalScrollBar()->setPageStep(10);
ui_.albums->verticalScrollBar()->setSingleStep(20);
}
QDialog::event(e);
return false;
}
bool AlbumCoverManager::eventFilter(QObject *obj, QEvent *event) {
if (obj == ui_.albums && event->type() == QEvent::ContextMenu) {
context_menu_items_ = ui_.albums->selectedItems();
if (context_menu_items_.isEmpty())
return false;
bool some_with_covers = false;
foreach (QListWidgetItem* item, context_menu_items_) {
if (item->icon().cacheKey() != no_cover_icon_.cacheKey())
some_with_covers = true;
}
ui_.action_show_fullsize->setEnabled(some_with_covers && context_menu_items_.size() == 1);
ui_.action_choose_manual->setEnabled(context_menu_items_.size() == 1);
ui_.action_unset_cover->setEnabled(some_with_covers);
QContextMenuEvent* e = static_cast<QContextMenuEvent*>(event);
context_menu_->popup(e->globalPos());
return true;
}
return false;
}
void AlbumCoverManager::ShowFullsize() {
if (context_menu_items_.size() != 1)
return;
QListWidgetItem* item = context_menu_items_[0];
QString title = item->data(Role_AlbumName).toString();
if (!item->data(Role_ArtistName).toString().isNull())
title = item->data(Role_ArtistName).toString() + " - " + title;
QDialog* dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
dialog->setWindowTitle(title);
QLabel* label = new QLabel(dialog);
label->setPixmap(AlbumCoverLoader::TryLoadPixmap(
item->data(Role_PathAutomatic).toString(),
item->data(Role_PathManual).toString()));
dialog->resize(label->pixmap()->size());
dialog->show();
}
void AlbumCoverManager::FetchSingleCover() {
foreach (QListWidgetItem* item, context_menu_items_) {
quint64 id = cover_fetcher_->FetchAlbumCover(
item->data(Role_ArtistName).toString(), item->data(Role_AlbumName).toString());
cover_fetching_tasks_[id] = item;
}
}
void AlbumCoverManager::ChooseManualCover() {
if (context_menu_items_.size() != 1)
return;
QListWidgetItem* item = context_menu_items_[0];
QString cover = QFileDialog::getOpenFileName(
this, tr("Choose manual cover"), item->data(Role_PathAutomatic).toString());
if (cover.isNull())
return;
// Can we load the image?
QImage image(cover);
if (image.isNull())
return;
// Update database
backend_->UpdateManualAlbumArtAsync(item->data(Role_ArtistName).toString(),
item->data(Role_AlbumName).toString(),
cover);
// Update the icon in our list
quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), cover);
item->setData(Role_PathManual, cover);
cover_loading_tasks_[id] = item;
}
void AlbumCoverManager::UnsetCover() {
foreach (QListWidgetItem* item, context_menu_items_) {
item->setIcon(no_cover_icon_);
item->setData(Role_PathManual, AlbumCoverLoader::kManuallyUnsetCover);
backend_->UpdateManualAlbumArtAsync(item->data(Role_ArtistName).toString(),
item->data(Role_AlbumName).toString(),
AlbumCoverLoader::kManuallyUnsetCover);
}
}

View File

@ -31,6 +31,9 @@ class AlbumCoverManager : public QDialog {
void closeEvent(QCloseEvent *);
bool event(QEvent *);
// For the album view context menu events
bool eventFilter(QObject *obj, QEvent *event);
private slots:
void ArtistChanged(QListWidgetItem* current);
void CoverLoaderInitialised();
@ -39,6 +42,12 @@ class AlbumCoverManager : public QDialog {
void FetchAlbumCovers();
void AlbumCoverFetched(quint64 id, const QImage& image);
// On the context menu
void ShowFullsize();
void FetchSingleCover();
void ChooseManualCover();
void UnsetCover();
private:
enum ArtistItemType {
All_Artists,
@ -48,6 +57,8 @@ class AlbumCoverManager : public QDialog {
enum Role {
Role_ArtistName = Qt::UserRole + 1,
Role_AlbumName,
Role_PathAutomatic,
Role_PathManual,
};
void CancelRequests();
@ -71,6 +82,9 @@ class AlbumCoverManager : public QDialog {
QIcon artist_icon_;
QIcon all_artists_icon_;
QIcon no_cover_icon_;
QMenu* context_menu_;
QList<QListWidgetItem*> context_menu_items_;
};
#endif // ALBUMCOVERMANAGER_H

View File

@ -124,6 +124,42 @@
</widget>
</item>
</layout>
<action name="action_show_fullsize">
<property name="icon">
<iconset>
<normaloff>:/zoom-in.png</normaloff>:/zoom-in.png</iconset>
</property>
<property name="text">
<string>Show fullsize...</string>
</property>
</action>
<action name="action_fetch">
<property name="icon">
<iconset>
<normaloff>:/download.png</normaloff>:/download.png</iconset>
</property>
<property name="text">
<string>Fetch automatically</string>
</property>
</action>
<action name="action_choose_manual">
<property name="icon">
<iconset>
<normaloff>:/open_media.png</normaloff>:/open_media.png</iconset>
</property>
<property name="text">
<string>Choose manual cover...</string>
</property>
</action>
<action name="action_unset_cover">
<property name="icon">
<iconset>
<normaloff>:/list-remove.png</normaloff>:/list-remove.png</iconset>
</property>
<property name="text">
<string>Unset cover</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
@ -140,9 +176,7 @@
<tabstop>fetch</tabstop>
<tabstop>albums</tabstop>
</tabstops>
<resources>
<include location="../data/data.qrc"/>
</resources>
<resources/>
<connections>
<connection>
<sender>clear</sender>

View File

@ -21,6 +21,7 @@
#include "trackslider.h"
#include "enginebase.h"
#include "albumcoverloader.h"
const char* Song::kColumnSpec =
"title, album, artist, albumartist, composer, "
@ -372,11 +373,9 @@ QImage Song::GetBestImage() const {
if (!d->image_.isNull())
return d->image_;
if (!d->art_manual_.isEmpty())
return QImage(d->art_manual_);
if (!d->art_automatic_.isEmpty())
return QImage(d->art_automatic_);
QImage art(AlbumCoverLoader::TryLoadImage(d->art_automatic_, d->art_manual_));
if (!art.isNull())
return art;
return QImage(":/nocover.png");
}