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>nocover.png</file>
|
||||||
<file>view-choose.png</file>
|
<file>view-choose.png</file>
|
||||||
<file>download.png</file>
|
<file>download.png</file>
|
||||||
|
<file>zoom-in.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</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 <QDir>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
const char* AlbumCoverLoader::kManuallyUnsetCover = "(unset)";
|
||||||
|
|
||||||
AlbumCoverLoader::AlbumCoverLoader(QObject* parent)
|
AlbumCoverLoader::AlbumCoverLoader(QObject* parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
height_(120),
|
height_(120),
|
||||||
@ -50,11 +52,7 @@ void AlbumCoverLoader::ProcessTasks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to load the image
|
// Try to load the image
|
||||||
QImage image;
|
QImage image(TryLoadImage(task.art_automatic, task.art_manual));
|
||||||
if (!task.art_manual.isEmpty())
|
|
||||||
image.load(task.art_manual);
|
|
||||||
if (!task.art_automatic.isEmpty() && image.isNull())
|
|
||||||
image.load(task.art_automatic);
|
|
||||||
|
|
||||||
if (!image.isNull()) {
|
if (!image.isNull()) {
|
||||||
// Scale the image down
|
// Scale the image down
|
||||||
@ -75,3 +73,25 @@ void AlbumCoverLoader::ProcessTasks() {
|
|||||||
emit ImageLoaded(task.id, image);
|
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();
|
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:
|
signals:
|
||||||
void ImageLoaded(quint64 id, const QImage& image);
|
void ImageLoaded(quint64 id, const QImage& image);
|
||||||
|
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QContextMenuEvent>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
const char* AlbumCoverManager::kSettingsGroup = "CoverManager";
|
const char* AlbumCoverManager::kSettingsGroup = "CoverManager";
|
||||||
|
|
||||||
@ -21,7 +25,8 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
|
|||||||
cover_loader_(new BackgroundThread<AlbumCoverLoader>(this)),
|
cover_loader_(new BackgroundThread<AlbumCoverLoader>(this)),
|
||||||
cover_fetcher_(new AlbumCoverFetcher(this)),
|
cover_fetcher_(new AlbumCoverFetcher(this)),
|
||||||
artist_icon_(":/artist.png"),
|
artist_icon_(":/artist.png"),
|
||||||
all_artists_icon_(":/album.png")
|
all_artists_icon_(":/album.png"),
|
||||||
|
context_menu_(new QMenu(this))
|
||||||
{
|
{
|
||||||
ui_.setupUi(this);
|
ui_.setupUi(this);
|
||||||
|
|
||||||
@ -37,9 +42,9 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
|
|||||||
|
|
||||||
// View menu
|
// View menu
|
||||||
QActionGroup* filter_group = new QActionGroup(this);
|
QActionGroup* filter_group = new QActionGroup(this);
|
||||||
filter_all_ = filter_group->addAction("All albums");
|
filter_all_ = filter_group->addAction(tr("All albums"));
|
||||||
filter_with_covers_ = filter_group->addAction("Albums with covers");
|
filter_with_covers_ = filter_group->addAction(tr("Albums with covers"));
|
||||||
filter_without_covers_ = filter_group->addAction("Albums without covers");
|
filter_without_covers_ = filter_group->addAction(tr("Albums without covers"));
|
||||||
filter_all_->setCheckable(true);
|
filter_all_->setCheckable(true);
|
||||||
filter_with_covers_->setCheckable(true);
|
filter_with_covers_->setCheckable(true);
|
||||||
filter_without_covers_->setCheckable(true);
|
filter_without_covers_->setCheckable(true);
|
||||||
@ -51,6 +56,14 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
|
|||||||
|
|
||||||
ui_.view->setMenu(view_menu);
|
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
|
// Connections
|
||||||
connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised()));
|
connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised()));
|
||||||
connect(ui_.artists, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
connect(ui_.artists, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
||||||
@ -61,6 +74,10 @@ AlbumCoverManager::AlbumCoverManager(QWidget *parent)
|
|||||||
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)),
|
||||||
SLOT(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
|
// Restore settings
|
||||||
QSettings s;
|
QSettings s;
|
||||||
@ -122,7 +139,7 @@ void AlbumCoverManager::Reset() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ui_.artists->clear();
|
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()) {
|
foreach (const QString& artist, backend_->GetAllArtists()) {
|
||||||
if (artist.isEmpty())
|
if (artist.isEmpty())
|
||||||
@ -143,6 +160,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
|
|||||||
artist = current->text();
|
artist = current->text();
|
||||||
|
|
||||||
ui_.albums->clear();
|
ui_.albums->clear();
|
||||||
|
context_menu_items_.clear();
|
||||||
CancelRequests();
|
CancelRequests();
|
||||||
|
|
||||||
foreach (const LibraryBackend::Album& info,
|
foreach (const LibraryBackend::Album& info,
|
||||||
@ -154,6 +172,8 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
|
|||||||
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
|
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
|
||||||
quint64 id = cover_loader_->Worker()->LoadImageAsync(
|
quint64 id = cover_loader_->Worker()->LoadImageAsync(
|
||||||
info.art_automatic, info.art_manual);
|
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;
|
cover_loading_tasks_[id] = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,6 +256,7 @@ void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage &image) {
|
|||||||
|
|
||||||
// Update the icon in our list
|
// Update the icon in our list
|
||||||
quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), path);
|
quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), path);
|
||||||
|
item->setData(Role_PathManual, path);
|
||||||
cover_loading_tasks_[id] = item;
|
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
|
// We seem to have to reset them to sensible values each time the contents
|
||||||
// of ui_.albums changes.
|
// of ui_.albums changes.
|
||||||
ui_.albums->setVerticalScrollMode(QListWidget::ScrollPerPixel);
|
ui_.albums->setVerticalScrollMode(QListWidget::ScrollPerPixel);
|
||||||
//ui_.albums->verticalScrollBar()->setPageStep(10);
|
|
||||||
ui_.albums->verticalScrollBar()->setSingleStep(20);
|
ui_.albums->verticalScrollBar()->setSingleStep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog::event(e);
|
QDialog::event(e);
|
||||||
return false;
|
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 *);
|
void closeEvent(QCloseEvent *);
|
||||||
bool event(QEvent *);
|
bool event(QEvent *);
|
||||||
|
|
||||||
|
// For the album view context menu events
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ArtistChanged(QListWidgetItem* current);
|
void ArtistChanged(QListWidgetItem* current);
|
||||||
void CoverLoaderInitialised();
|
void CoverLoaderInitialised();
|
||||||
@ -39,6 +42,12 @@ class AlbumCoverManager : public QDialog {
|
|||||||
void FetchAlbumCovers();
|
void FetchAlbumCovers();
|
||||||
void AlbumCoverFetched(quint64 id, const QImage& image);
|
void AlbumCoverFetched(quint64 id, const QImage& image);
|
||||||
|
|
||||||
|
// On the context menu
|
||||||
|
void ShowFullsize();
|
||||||
|
void FetchSingleCover();
|
||||||
|
void ChooseManualCover();
|
||||||
|
void UnsetCover();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ArtistItemType {
|
enum ArtistItemType {
|
||||||
All_Artists,
|
All_Artists,
|
||||||
@ -48,6 +57,8 @@ class AlbumCoverManager : public QDialog {
|
|||||||
enum Role {
|
enum Role {
|
||||||
Role_ArtistName = Qt::UserRole + 1,
|
Role_ArtistName = Qt::UserRole + 1,
|
||||||
Role_AlbumName,
|
Role_AlbumName,
|
||||||
|
Role_PathAutomatic,
|
||||||
|
Role_PathManual,
|
||||||
};
|
};
|
||||||
|
|
||||||
void CancelRequests();
|
void CancelRequests();
|
||||||
@ -71,6 +82,9 @@ class AlbumCoverManager : public QDialog {
|
|||||||
QIcon artist_icon_;
|
QIcon artist_icon_;
|
||||||
QIcon all_artists_icon_;
|
QIcon all_artists_icon_;
|
||||||
QIcon no_cover_icon_;
|
QIcon no_cover_icon_;
|
||||||
|
|
||||||
|
QMenu* context_menu_;
|
||||||
|
QList<QListWidgetItem*> context_menu_items_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ALBUMCOVERMANAGER_H
|
#endif // ALBUMCOVERMANAGER_H
|
||||||
|
@ -124,6 +124,42 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</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>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
@ -140,9 +176,7 @@
|
|||||||
<tabstop>fetch</tabstop>
|
<tabstop>fetch</tabstop>
|
||||||
<tabstop>albums</tabstop>
|
<tabstop>albums</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources/>
|
||||||
<include location="../data/data.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>clear</sender>
|
<sender>clear</sender>
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "trackslider.h"
|
#include "trackslider.h"
|
||||||
#include "enginebase.h"
|
#include "enginebase.h"
|
||||||
|
#include "albumcoverloader.h"
|
||||||
|
|
||||||
const char* Song::kColumnSpec =
|
const char* Song::kColumnSpec =
|
||||||
"title, album, artist, albumartist, composer, "
|
"title, album, artist, albumartist, composer, "
|
||||||
@ -372,11 +373,9 @@ QImage Song::GetBestImage() const {
|
|||||||
if (!d->image_.isNull())
|
if (!d->image_.isNull())
|
||||||
return d->image_;
|
return d->image_;
|
||||||
|
|
||||||
if (!d->art_manual_.isEmpty())
|
QImage art(AlbumCoverLoader::TryLoadImage(d->art_automatic_, d->art_manual_));
|
||||||
return QImage(d->art_manual_);
|
if (!art.isNull())
|
||||||
|
return art;
|
||||||
if (!d->art_automatic_.isEmpty())
|
|
||||||
return QImage(d->art_automatic_);
|
|
||||||
|
|
||||||
return QImage(":/nocover.png");
|
return QImage(":/nocover.png");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user