Add some more options to the album cover manager: show fullsize, fetch automatically, choose manually, unset cover
This commit is contained in:
parent
4652e47c65
commit
101b30c4b5
@ -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
BIN
data/zoom-in.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user