- Finished album cover exporter from keirangtp's branch "export-covers".
- Updated export dialog layout. - Added option to export downloaded and/or embedded covers. - Auto. cover fetcher and exporter is now cancelable. - Minor covermanager layout improvements. - Covermanager shows count of total and missing covers. Fixed issue 520.
This commit is contained in:
parent
f7c46c724a
commit
4e2ded9178
|
@ -114,10 +114,12 @@ set(SOURCES
|
|||
core/urlhandler.cpp
|
||||
core/utilities.cpp
|
||||
|
||||
covers/albumcoverexporter.cpp
|
||||
covers/albumcoverfetcher.cpp
|
||||
covers/albumcoverfetchersearch.cpp
|
||||
covers/albumcoverloader.cpp
|
||||
covers/amazoncoverprovider.cpp
|
||||
covers/coverexportrunnable.cpp
|
||||
covers/coverprovider.cpp
|
||||
covers/coverproviders.cpp
|
||||
covers/coversearchstatistics.cpp
|
||||
|
@ -321,6 +323,7 @@ set(SOURCES
|
|||
ui/about.cpp
|
||||
ui/addstreamdialog.cpp
|
||||
ui/albumcoverchoicecontroller.cpp
|
||||
ui/albumcoverexport.cpp
|
||||
ui/albumcovermanager.cpp
|
||||
ui/albumcovermanagerlist.cpp
|
||||
ui/albumcoversearcher.cpp
|
||||
|
@ -417,10 +420,12 @@ set(HEADERS
|
|||
core/taskmanager.h
|
||||
core/urlhandler.h
|
||||
|
||||
covers/albumcoverexporter.h
|
||||
covers/albumcoverfetcher.h
|
||||
covers/albumcoverfetchersearch.h
|
||||
covers/albumcoverloader.h
|
||||
covers/amazoncoverprovider.h
|
||||
covers/coverexportrunnable.h
|
||||
covers/coverprovider.h
|
||||
covers/coverproviders.h
|
||||
covers/coversearchstatisticsdialog.h
|
||||
|
@ -590,6 +595,7 @@ set(HEADERS
|
|||
ui/about.h
|
||||
ui/addstreamdialog.h
|
||||
ui/albumcoverchoicecontroller.h
|
||||
ui/albumcoverexport.h
|
||||
ui/albumcovermanager.h
|
||||
ui/albumcovermanagerlist.h
|
||||
ui/albumcoversearcher.h
|
||||
|
@ -711,6 +717,7 @@ set(UI
|
|||
|
||||
ui/about.ui
|
||||
ui/addstreamdialog.ui
|
||||
ui/albumcoverexport.ui
|
||||
ui/albumcovermanager.ui
|
||||
ui/albumcoversearcher.ui
|
||||
ui/appearancesettingspage.ui
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* 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 "albumcoverexporter.h"
|
||||
#include "coverexportrunnable.h"
|
||||
#include "core/song.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QThreadPool>
|
||||
|
||||
const int AlbumCoverExporter::kMaxConcurrentRequests = 3;
|
||||
|
||||
AlbumCoverExporter::AlbumCoverExporter(QObject* parent)
|
||||
: QObject(parent),
|
||||
thread_pool_(new QThreadPool(this)),
|
||||
exported_(0),
|
||||
skipped_(0),
|
||||
all_(0)
|
||||
{
|
||||
thread_pool_->setMaxThreadCount(kMaxConcurrentRequests);
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::SetDialogResult(const AlbumCoverExport::DialogResult &dialog_result) {
|
||||
dialog_result_ = dialog_result;
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::AddExportRequest(Song song) {
|
||||
requests_.append(new CoverExportRunnable(dialog_result_, song));
|
||||
all_ = requests_.count();
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::Cancel() {
|
||||
requests_.clear();
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::StartExporting() {
|
||||
exported_ = 0;
|
||||
skipped_ = 0;
|
||||
AddJobsToPool();
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::AddJobsToPool() {
|
||||
while (!requests_.isEmpty()
|
||||
&& thread_pool_->activeThreadCount() < thread_pool_->maxThreadCount()) {
|
||||
CoverExportRunnable* runnable = requests_.dequeue();
|
||||
|
||||
connect(runnable, SIGNAL(CoverExported()), SLOT(CoverExported()));
|
||||
connect(runnable, SIGNAL(CoverSkipped()), SLOT(CoverSkipped()));
|
||||
|
||||
thread_pool_->start(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::CoverExported() {
|
||||
exported_++;
|
||||
emit AlbumCoversExportUpdate(exported_, skipped_, all_);
|
||||
AddJobsToPool();
|
||||
}
|
||||
|
||||
void AlbumCoverExporter::CoverSkipped() {
|
||||
skipped_++;
|
||||
emit AlbumCoversExportUpdate(exported_, skipped_, all_);
|
||||
AddJobsToPool();
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* 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 ALBUMCOVEREXPORTER_H
|
||||
#define ALBUMCOVEREXPORTER_H
|
||||
|
||||
#include "coverexportrunnable.h"
|
||||
#include "core/song.h"
|
||||
#include "ui/albumcoverexport.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
|
||||
class QThreadPool;
|
||||
|
||||
class AlbumCoverExporter : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AlbumCoverExporter(QObject* parent = 0);
|
||||
virtual ~AlbumCoverExporter() {}
|
||||
|
||||
static const int kMaxConcurrentRequests;
|
||||
|
||||
void SetDialogResult(const AlbumCoverExport::DialogResult& dialog_result);
|
||||
void AddExportRequest(Song song);
|
||||
void StartExporting();
|
||||
void Cancel();
|
||||
|
||||
int request_count() { return requests_.size(); }
|
||||
|
||||
signals:
|
||||
void AlbumCoversExportUpdate(int exported, int skipped, int all);
|
||||
|
||||
private slots:
|
||||
void CoverExported();
|
||||
void CoverSkipped();
|
||||
|
||||
private:
|
||||
void AddJobsToPool();
|
||||
AlbumCoverExport::DialogResult dialog_result_;
|
||||
|
||||
QQueue<CoverExportRunnable*> requests_;
|
||||
QThreadPool* thread_pool_;
|
||||
|
||||
int exported_;
|
||||
int skipped_;
|
||||
int all_;
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVEREXPORTER_H
|
|
@ -0,0 +1,202 @@
|
|||
/* 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 "albumcoverexporter.h"
|
||||
#include "core/song.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
|
||||
CoverExportRunnable::CoverExportRunnable(const AlbumCoverExport::DialogResult& dialog_result,
|
||||
const Song& song)
|
||||
: dialog_result_(dialog_result),
|
||||
song_(song)
|
||||
{
|
||||
}
|
||||
|
||||
void CoverExportRunnable::run() {
|
||||
QString cover_path = GetCoverPath();
|
||||
|
||||
// manually unset?
|
||||
if(cover_path.isEmpty()) {
|
||||
EmitCoverSkipped();
|
||||
} else {
|
||||
if(dialog_result_.RequiresCoverProcessing()) {
|
||||
ProcessAndExportCover();
|
||||
} else {
|
||||
ExportCover();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
QString CoverExportRunnable::GetCoverPath() {
|
||||
if(song_.has_manually_unset_cover()) {
|
||||
return QString();
|
||||
// Export downloaded covers?
|
||||
} else if(!song_.art_manual().isEmpty() && dialog_result_.export_downloaded_) {
|
||||
return song_.art_manual();
|
||||
// Export embedded covers?
|
||||
} else if(!song_.art_automatic().isEmpty()
|
||||
&& song_.art_automatic() == Song::kEmbeddedCover
|
||||
&& dialog_result_.export_embedded_) {
|
||||
return song_.art_automatic();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
// Exports a single album cover using a "save QImage to file" approach.
|
||||
// For performance reasons this method will be invoked only if loading
|
||||
// and in memory processing of images is necessary for current settings
|
||||
// which means that:
|
||||
// - either the force size flag is being used
|
||||
// - or the "overwrite smaller" mode is used
|
||||
// In all other cases, the faster ExportCover() method will be used.
|
||||
void CoverExportRunnable::ProcessAndExportCover() {
|
||||
QString cover_path = GetCoverPath();
|
||||
|
||||
// either embedded or disk - the one we'll export for the current album
|
||||
QImage cover;
|
||||
|
||||
QImage embedded_cover;
|
||||
QImage disk_cover;
|
||||
|
||||
// load embedded cover if any
|
||||
if(song_.has_embedded_cover()) {
|
||||
embedded_cover = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(song_.url().toLocalFile());
|
||||
|
||||
if(embedded_cover.isNull()) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
cover = embedded_cover;
|
||||
}
|
||||
|
||||
// load a file cover which iss mandatory if there's no embedded cover
|
||||
disk_cover.load(cover_path);
|
||||
|
||||
if(embedded_cover.isNull()) {
|
||||
if(disk_cover.isNull()) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
cover = disk_cover;
|
||||
}
|
||||
|
||||
// rescale if necessary
|
||||
if(dialog_result_.IsSizeForced()) {
|
||||
cover = cover.scaled(QSize(dialog_result_.width_, dialog_result_.height_), Qt::IgnoreAspectRatio);
|
||||
}
|
||||
|
||||
QString dir = song_.url().toLocalFile().section('/', 0, -2);
|
||||
QString extension = cover_path.section('.', -1);
|
||||
|
||||
QString new_file = dir + '/' + dialog_result_.fileName_ + '.' +
|
||||
(cover_path == Song::kEmbeddedCover
|
||||
? "jpg"
|
||||
: extension);
|
||||
|
||||
// If the file exists, do not override!
|
||||
if(dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode_None && QFile::exists(new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
|
||||
// we're handling overwrite as remove + copy so we need to delete the old file first
|
||||
if(QFile::exists(new_file) && dialog_result_.overwrite_ != AlbumCoverExport::OverwriteMode_None) {
|
||||
|
||||
// if the mode is "overwrite smaller" then skip the cover if a bigger one
|
||||
// is already available in the folder
|
||||
if(dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode_Smaller) {
|
||||
QImage existing;
|
||||
existing.load(new_file);
|
||||
|
||||
if(existing.isNull() || existing.size().height() >= cover.size().height()
|
||||
|| existing.size().width() >= cover.size().width()) {
|
||||
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!QFile::remove(new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(cover.save(new_file)) {
|
||||
EmitCoverExported();
|
||||
} else {
|
||||
EmitCoverSkipped();
|
||||
}
|
||||
}
|
||||
|
||||
// Exports a single album cover using a "copy file" approach.
|
||||
void CoverExportRunnable::ExportCover() {
|
||||
QString cover_path = GetCoverPath();
|
||||
|
||||
QString dir = song_.url().toLocalFile().section('/', 0, -2);
|
||||
QString extension = cover_path.section('.', -1);
|
||||
|
||||
QString new_file = dir + '/' + dialog_result_.fileName_ + '.' +
|
||||
(cover_path == Song::kEmbeddedCover
|
||||
? "jpg"
|
||||
: extension);
|
||||
|
||||
// If the file exists, do not override!
|
||||
if(dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode_None && QFile::exists(new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
|
||||
// we're handling overwrite as remove + copy so we need to delete the old file first
|
||||
if(dialog_result_.overwrite_ != AlbumCoverExport::OverwriteMode_None && QFile::exists(new_file)) {
|
||||
if(!QFile::remove(new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(cover_path == Song::kEmbeddedCover) {
|
||||
// an embedded cover
|
||||
QImage embedded = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(song_.url().toLocalFile());
|
||||
if(!embedded.save(new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// automatic or manual cover, available in an image file
|
||||
if(!QFile::copy(cover_path, new_file)) {
|
||||
EmitCoverSkipped();
|
||||
return;
|
||||
}
|
||||
}
|
||||
EmitCoverExported();
|
||||
}
|
||||
|
||||
void CoverExportRunnable::EmitCoverExported() {
|
||||
emit CoverExported();
|
||||
}
|
||||
|
||||
|
||||
void CoverExportRunnable::EmitCoverSkipped() {
|
||||
emit CoverSkipped();
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* 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 COVEREXPORTRUNNABLE_H
|
||||
#define COVEREXPORTRUNNABLE_H
|
||||
|
||||
#include "core/song.h"
|
||||
#include "ui/albumcoverexport.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
|
||||
class AlbumCoverExporter;
|
||||
|
||||
class CoverExportRunnable : public QObject, public QRunnable {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CoverExportRunnable(const AlbumCoverExport::DialogResult& dialog_result,
|
||||
const Song& song);
|
||||
virtual ~CoverExportRunnable() {}
|
||||
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void CoverExported();
|
||||
void CoverSkipped();
|
||||
|
||||
private:
|
||||
void EmitCoverExported();
|
||||
void EmitCoverSkipped();
|
||||
|
||||
void ProcessAndExportCover();
|
||||
void ExportCover();
|
||||
QString GetCoverPath();
|
||||
|
||||
AlbumCoverExport::DialogResult dialog_result_;
|
||||
Song song_;
|
||||
AlbumCoverExporter* album_cover_exporter_;
|
||||
};
|
||||
|
||||
#endif // COVEREXPORTRUNNABLE_H
|
|
@ -0,0 +1,95 @@
|
|||
/* 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 "albumcoverexport.h"
|
||||
#include "ui_albumcoverexport.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char* AlbumCoverExport::kSettingsGroup = "AlbumCoverExport";
|
||||
|
||||
AlbumCoverExport::AlbumCoverExport(QWidget* parent)
|
||||
: QDialog(parent),
|
||||
ui_(new Ui_AlbumCoverExport)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
|
||||
connect(ui_->forceSize, SIGNAL(stateChanged(int)), SLOT(ForceSizeToggled(int)));
|
||||
}
|
||||
|
||||
AlbumCoverExport::~AlbumCoverExport() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
AlbumCoverExport::DialogResult AlbumCoverExport::Exec() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
// restore last accepted settings
|
||||
ui_->fileName->setText(s.value("fileName", "cover").toString());
|
||||
ui_->doNotOverwrite->setChecked(s.value("overwrite", OverwriteMode_None).toInt() == OverwriteMode_None);
|
||||
ui_->overwriteAll->setChecked(s.value("overwrite", OverwriteMode_All).toInt() == OverwriteMode_All);
|
||||
ui_->overwriteSmaller->setChecked(s.value("overwrite", OverwriteMode_Smaller).toInt() == OverwriteMode_Smaller);
|
||||
ui_->forceSize->setChecked(s.value("forceSize", false).toBool());
|
||||
ui_->width->setText(s.value("width", "").toString());
|
||||
ui_->height->setText(s.value("height", "").toString());
|
||||
ui_->export_downloaded->setChecked(s.value("export_downloaded", true).toBool());
|
||||
ui_->export_embedded->setChecked(s.value("export_embedded", false).toBool());
|
||||
|
||||
ForceSizeToggled(ui_->forceSize->checkState());
|
||||
|
||||
DialogResult result = DialogResult();
|
||||
result.cancelled_ = (exec() == QDialog::Rejected);
|
||||
|
||||
if(!result.cancelled_) {
|
||||
QString fileName = ui_->fileName->text();
|
||||
if (fileName.isEmpty()) {
|
||||
fileName = "folder";
|
||||
}
|
||||
OverwriteMode overwrite = ui_->doNotOverwrite->isChecked()
|
||||
? OverwriteMode_None
|
||||
: (ui_->overwriteAll->isChecked()
|
||||
? OverwriteMode_All
|
||||
: OverwriteMode_Smaller);
|
||||
bool forceSize = ui_->forceSize->isChecked();
|
||||
QString width = ui_->width->text();
|
||||
QString height = ui_->height->text();
|
||||
|
||||
s.setValue("fileName", fileName);
|
||||
s.setValue("overwrite", overwrite);
|
||||
s.setValue("forceSize", forceSize);
|
||||
s.setValue("width", width);
|
||||
s.setValue("height", height);
|
||||
s.setValue("export_downloaded", ui_->export_downloaded->isChecked());
|
||||
s.setValue("export_embedded", ui_->export_embedded->isChecked());
|
||||
|
||||
result.fileName_ = fileName;
|
||||
result.overwrite_ = overwrite;
|
||||
result.forceSize_ = forceSize;
|
||||
result.width_ = width.toInt();
|
||||
result.height_ = height.toInt();
|
||||
result.export_downloaded_ = ui_->export_downloaded->isChecked();
|
||||
result.export_embedded_ = ui_->export_embedded->isChecked();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void AlbumCoverExport::ForceSizeToggled(int state) {
|
||||
ui_->width->setEnabled(state == Qt::Checked);
|
||||
ui_->height->setEnabled(state == Qt::Checked);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* 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 ALBUMCOVEREXPORT_H
|
||||
#define ALBUMCOVEREXPORT_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Ui_AlbumCoverExport;
|
||||
|
||||
// Controller for the "Export covers" dialog.
|
||||
class AlbumCoverExport : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AlbumCoverExport(QWidget* parent = 0);
|
||||
~AlbumCoverExport();
|
||||
|
||||
enum OverwriteMode {
|
||||
OverwriteMode_None = 0,
|
||||
OverwriteMode_All = 1,
|
||||
OverwriteMode_Smaller = 2
|
||||
};
|
||||
|
||||
struct DialogResult {
|
||||
bool cancelled_;
|
||||
|
||||
bool export_downloaded_;
|
||||
bool export_embedded_;
|
||||
|
||||
QString fileName_;
|
||||
OverwriteMode overwrite_;
|
||||
bool forceSize_;
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
bool IsSizeForced() const {
|
||||
return forceSize_ && width_ > 0 && height_ > 0;
|
||||
}
|
||||
|
||||
bool RequiresCoverProcessing() const {
|
||||
return IsSizeForced() || overwrite_ == OverwriteMode_Smaller;
|
||||
}
|
||||
};
|
||||
|
||||
DialogResult Exec();
|
||||
|
||||
private slots:
|
||||
void ForceSizeToggled(int state);
|
||||
|
||||
private:
|
||||
Ui_AlbumCoverExport* ui_;
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVEREXPORT_H
|
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AlbumCoverExport</class>
|
||||
<widget class="QDialog" name="AlbumCoverExport">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>391</width>
|
||||
<height>412</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export covers</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Output</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Enter a filename for exported covers (no extension):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="fileName">
|
||||
<property name="placeholderText">
|
||||
<string notr="true">folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="export_downloaded">
|
||||
<property name="text">
|
||||
<string>Export downloaded covers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="export_embedded">
|
||||
<property name="text">
|
||||
<string>Export embedded covers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Existing covers</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="doNotOverwrite">
|
||||
<property name="text">
|
||||
<string>Do not overwrite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="overwriteAll">
|
||||
<property name="text">
|
||||
<string>Overwrite all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="overwriteSmaller">
|
||||
<property name="text">
|
||||
<string>Overwrite smaller ones only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="forceSize">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Scale size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="width">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhDigitsOnly</set>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="height">
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhDigitsOnly</set>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Pixel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AlbumCoverExport</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>AlbumCoverExport</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>
|
|
@ -22,6 +22,7 @@
|
|||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/utilities.h"
|
||||
#include "covers/albumcoverexporter.h"
|
||||
#include "covers/albumcoverfetcher.h"
|
||||
#include "covers/albumcoverloader.h"
|
||||
#include "covers/coverproviders.h"
|
||||
|
@ -32,8 +33,10 @@
|
|||
#include "playlist/songmimedata.h"
|
||||
#include "widgets/forcescrollperpixel.h"
|
||||
#include "ui/albumcoverchoicecontroller.h"
|
||||
#include "ui/albumcoverexport.h"
|
||||
|
||||
#include <QActionGroup>
|
||||
#include <QPushButton>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QEvent>
|
||||
#include <QFileDialog>
|
||||
|
@ -60,10 +63,13 @@ AlbumCoverManager::AlbumCoverManager(Application* app,
|
|||
album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
|
||||
cover_fetcher_(new AlbumCoverFetcher(app_->cover_providers(), this, network)),
|
||||
cover_searcher_(NULL),
|
||||
cover_export_(NULL),
|
||||
cover_exporter_(new AlbumCoverExporter(this)),
|
||||
artist_icon_(IconLoader::Load("x-clementine-artist")),
|
||||
all_artists_icon_(IconLoader::Load("x-clementine-album")),
|
||||
context_menu_(new QMenu(this)),
|
||||
progress_bar_(new QProgressBar(this)),
|
||||
abort_progress_(new QPushButton(this)),
|
||||
jobs_(0),
|
||||
library_backend_(library_backend)
|
||||
{
|
||||
|
@ -72,6 +78,7 @@ AlbumCoverManager::AlbumCoverManager(Application* app,
|
|||
|
||||
// Icons
|
||||
ui_->action_fetch->setIcon(IconLoader::Load("download"));
|
||||
ui_->export_covers->setIcon(IconLoader::Load("document-save"));
|
||||
ui_->view->setIcon(IconLoader::Load("view-choose"));
|
||||
ui_->fetch->setIcon(IconLoader::Load("download"));
|
||||
ui_->action_add_to_playlist->setIcon(IconLoader::Load("media-playback-start"));
|
||||
|
@ -91,10 +98,15 @@ AlbumCoverManager::AlbumCoverManager(Application* app,
|
|||
no_cover_icon_ = QPixmap::fromImage(square_nocover);
|
||||
|
||||
cover_searcher_ = new AlbumCoverSearcher(no_cover_icon_, app_, this);
|
||||
cover_export_ = new AlbumCoverExport(this);
|
||||
|
||||
// Set up the status bar
|
||||
statusBar()->addPermanentWidget(progress_bar_);
|
||||
statusBar()->addPermanentWidget(abort_progress_);
|
||||
progress_bar_->hide();
|
||||
abort_progress_->hide();
|
||||
abort_progress_->setText(tr("Abort"));
|
||||
connect(abort_progress_, SIGNAL(clicked()), this, SLOT(CancelRequests()));
|
||||
|
||||
ui_->albums->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
ui_->artists->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
|
@ -102,7 +114,7 @@ AlbumCoverManager::AlbumCoverManager(Application* app,
|
|||
QShortcut* close = new QShortcut(QKeySequence::Close, this);
|
||||
connect(close, SIGNAL(activated()), SLOT(close()));
|
||||
|
||||
ResetFetchCoversButton();
|
||||
EnableCoversButtons();
|
||||
}
|
||||
|
||||
AlbumCoverManager::~AlbumCoverManager() {
|
||||
|
@ -149,6 +161,9 @@ void AlbumCoverManager::Init() {
|
|||
connect(album_cover_choice_controller_->show_cover_action(),
|
||||
SIGNAL(triggered()), this, SLOT(ShowCover()));
|
||||
|
||||
connect(cover_exporter_, SIGNAL(AlbumCoversExportUpdate(int, int, int)),
|
||||
SLOT(UpdateExportStatus(int, int, int)));
|
||||
|
||||
context_menu_->addActions(actions);
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addAction(ui_->action_load);
|
||||
|
@ -163,6 +178,7 @@ void AlbumCoverManager::Init() {
|
|||
connect(filter_group, SIGNAL(triggered(QAction*)), SLOT(UpdateFilter()));
|
||||
connect(ui_->view, SIGNAL(clicked()), ui_->view, SLOT(showMenu()));
|
||||
connect(ui_->fetch, SIGNAL(clicked()), SLOT(FetchAlbumCovers()));
|
||||
connect(ui_->export_covers, SIGNAL(clicked()), SLOT(ExportCovers()));
|
||||
connect(cover_fetcher_, SIGNAL(AlbumCoverFetched(quint64,QImage,CoverSearchStatistics)),
|
||||
SLOT(AlbumCoverFetched(quint64,QImage,CoverSearchStatistics)));
|
||||
connect(ui_->action_fetch, SIGNAL(triggered()), SLOT(FetchSingleCover()));
|
||||
|
@ -223,11 +239,14 @@ void AlbumCoverManager::CancelRequests() {
|
|||
QSet<quint64>::fromList(cover_loading_tasks_.keys()));
|
||||
cover_loading_tasks_.clear();
|
||||
|
||||
cover_exporter_->Cancel();
|
||||
|
||||
cover_fetching_tasks_.clear();
|
||||
cover_fetcher_->Clear();
|
||||
progress_bar_->hide();
|
||||
abort_progress_->hide();
|
||||
statusBar()->clearMessage();
|
||||
ResetFetchCoversButton();
|
||||
EnableCoversButtons();
|
||||
}
|
||||
|
||||
static bool CompareNocase(const QString& left, const QString& right) {
|
||||
|
@ -240,7 +259,7 @@ static bool CompareAlbumNameNocase(const LibraryBackend::Album& left,
|
|||
}
|
||||
|
||||
void AlbumCoverManager::Reset() {
|
||||
ResetFetchCoversButton();
|
||||
EnableCoversButtons();
|
||||
|
||||
ui_->artists->clear();
|
||||
new QListWidgetItem(all_artists_icon_, tr("All artists"), ui_->artists, All_Artists);
|
||||
|
@ -257,8 +276,14 @@ void AlbumCoverManager::Reset() {
|
|||
}
|
||||
}
|
||||
|
||||
void AlbumCoverManager::ResetFetchCoversButton() {
|
||||
void AlbumCoverManager::EnableCoversButtons() {
|
||||
ui_->fetch->setEnabled(app_->cover_providers()->HasAnyProviders());
|
||||
ui_->export_covers->setEnabled(true);
|
||||
}
|
||||
|
||||
void AlbumCoverManager::DisableCoversButtons() {
|
||||
ui_->fetch->setEnabled(false);
|
||||
ui_->export_covers->setEnabled(false);
|
||||
}
|
||||
|
||||
void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
|
||||
|
@ -338,10 +363,24 @@ void AlbumCoverManager::UpdateFilter() {
|
|||
hide = Hide_WithoutCovers;
|
||||
}
|
||||
|
||||
qint32 total_count = 0;
|
||||
qint32 without_cover = 0;
|
||||
|
||||
for (int i = 0; i < ui_->albums->count(); ++i) {
|
||||
QListWidgetItem* item = ui_->albums->item(i);
|
||||
item->setHidden(ShouldHide(*item, filter, hide));
|
||||
bool should_hide = ShouldHide(*item, filter, hide);
|
||||
item->setHidden(should_hide);
|
||||
|
||||
if (!should_hide) {
|
||||
total_count++;
|
||||
if (item->icon().cacheKey() == no_cover_icon_.cacheKey()) {
|
||||
without_cover++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_->total_albums->setText(QString::number(total_count));
|
||||
ui_->without_cover->setText(QString::number(without_cover));
|
||||
}
|
||||
|
||||
bool AlbumCoverManager::ShouldHide(
|
||||
|
@ -387,6 +426,7 @@ void AlbumCoverManager::FetchAlbumCovers() {
|
|||
|
||||
progress_bar_->setMaximum(jobs_);
|
||||
progress_bar_->show();
|
||||
abort_progress_->show();
|
||||
fetch_statistics_ = CoverSearchStatistics();
|
||||
UpdateStatusText();
|
||||
}
|
||||
|
@ -402,7 +442,7 @@ void AlbumCoverManager::AlbumCoverFetched(quint64 id, const QImage& image,
|
|||
}
|
||||
|
||||
if (cover_fetching_tasks_.isEmpty()) {
|
||||
ResetFetchCoversButton();
|
||||
EnableCoversButtons();
|
||||
}
|
||||
|
||||
fetch_statistics_ += statistics;
|
||||
|
@ -427,6 +467,7 @@ void AlbumCoverManager::UpdateStatusText() {
|
|||
if (cover_fetching_tasks_.isEmpty()) {
|
||||
QTimer::singleShot(2000, statusBar(), SLOT(clearMessage()));
|
||||
progress_bar_->hide();
|
||||
abort_progress_->hide();
|
||||
|
||||
CoverSearchStatisticsDialog* dialog = new CoverSearchStatisticsDialog(this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -516,6 +557,7 @@ void AlbumCoverManager::FetchSingleCover() {
|
|||
|
||||
progress_bar_->setMaximum(jobs_);
|
||||
progress_bar_->show();
|
||||
abort_progress_->show();
|
||||
UpdateStatusText();
|
||||
}
|
||||
|
||||
|
@ -701,3 +743,56 @@ void AlbumCoverManager::SaveAndSetCover(QListWidgetItem *item, const QImage &ima
|
|||
item->setData(Role_PathManual, path);
|
||||
cover_loading_tasks_[id] = item;
|
||||
}
|
||||
|
||||
void AlbumCoverManager::ExportCovers() {
|
||||
AlbumCoverExport::DialogResult result = cover_export_->Exec();
|
||||
|
||||
if(result.cancelled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisableCoversButtons();
|
||||
|
||||
cover_exporter_->SetDialogResult(result);
|
||||
|
||||
for (int i=0 ; i<ui_->albums->count() ; ++i) {
|
||||
QListWidgetItem* item = ui_->albums->item(i);
|
||||
|
||||
// skip hidden and coverless albums
|
||||
if (item->isHidden() || item->icon().cacheKey() == no_cover_icon_.cacheKey()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cover_exporter_->AddExportRequest(ItemAsSong(item));
|
||||
}
|
||||
|
||||
progress_bar_->setMaximum(cover_exporter_->request_count());
|
||||
progress_bar_->show();
|
||||
abort_progress_->show();
|
||||
|
||||
cover_exporter_->StartExporting();
|
||||
}
|
||||
|
||||
void AlbumCoverManager::UpdateExportStatus(int exported, int skipped, int max) {
|
||||
progress_bar_->setValue(exported);
|
||||
|
||||
QString message = tr("Exported %1 covers out of %2 (%3 skipped)")
|
||||
.arg(exported)
|
||||
.arg(max)
|
||||
.arg(skipped);
|
||||
statusBar()->showMessage(message);
|
||||
|
||||
// end of the current process
|
||||
if(exported + skipped >= max) {
|
||||
QTimer::singleShot(2000, statusBar(), SLOT(clearMessage()));
|
||||
|
||||
progress_bar_->hide();
|
||||
abort_progress_->hide();
|
||||
EnableCoversButtons();
|
||||
|
||||
QMessageBox msg;
|
||||
msg.setWindowTitle(tr("Export finished"));
|
||||
msg.setText(message);
|
||||
msg.exec();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "covers/coversearchstatistics.h"
|
||||
|
||||
class AlbumCoverChoiceController;
|
||||
class AlbumCoverExport;
|
||||
class AlbumCoverExporter;
|
||||
class AlbumCoverFetcher;
|
||||
class AlbumCoverSearcher;
|
||||
class Application;
|
||||
|
@ -39,6 +41,7 @@ class Ui_CoverManager;
|
|||
class QListWidgetItem;
|
||||
class QMenu;
|
||||
class QNetworkAccessManager;
|
||||
class QPushButton;
|
||||
class QProgressBar;
|
||||
|
||||
class AlbumCoverManager : public QMainWindow {
|
||||
|
@ -58,7 +61,8 @@ class AlbumCoverManager : public QMainWindow {
|
|||
void Reset();
|
||||
void Init();
|
||||
|
||||
void ResetFetchCoversButton();
|
||||
void EnableCoversButtons();
|
||||
void DisableCoversButtons();
|
||||
|
||||
SongList GetSongsInAlbum(const QModelIndex& index) const;
|
||||
SongList GetSongsInAlbums(const QModelIndexList& indexes) const;
|
||||
|
@ -79,8 +83,10 @@ class AlbumCoverManager : public QMainWindow {
|
|||
void CoverImageLoaded(quint64 id, const QImage& image);
|
||||
void UpdateFilter();
|
||||
void FetchAlbumCovers();
|
||||
void ExportCovers();
|
||||
void AlbumCoverFetched(quint64 id, const QImage& image,
|
||||
const CoverSearchStatistics& statistics);
|
||||
void CancelRequests();
|
||||
|
||||
// On the context menu
|
||||
void FetchSingleCover();
|
||||
|
@ -98,6 +104,7 @@ class AlbumCoverManager : public QMainWindow {
|
|||
void LoadSelectedToPlaylist();
|
||||
|
||||
void UpdateCoverInList(QListWidgetItem* item, const QString& cover);
|
||||
void UpdateExportStatus(int exported, int bad, int count);
|
||||
|
||||
private:
|
||||
enum ArtistItemType {
|
||||
|
@ -133,8 +140,6 @@ class AlbumCoverManager : public QMainWindow {
|
|||
|
||||
Song ItemAsSong(QListWidgetItem* item);
|
||||
|
||||
void CancelRequests();
|
||||
|
||||
void UpdateStatusText();
|
||||
bool ShouldHide(const QListWidgetItem& item, const QString& filter, HideCovers hide) const;
|
||||
void SaveAndSetCover(QListWidgetItem* item, const QImage& image);
|
||||
|
@ -157,6 +162,8 @@ class AlbumCoverManager : public QMainWindow {
|
|||
CoverSearchStatistics fetch_statistics_;
|
||||
|
||||
AlbumCoverSearcher* cover_searcher_;
|
||||
AlbumCoverExport* cover_export_;
|
||||
AlbumCoverExporter* cover_exporter_;
|
||||
|
||||
QIcon artist_icon_;
|
||||
QIcon all_artists_icon_;
|
||||
|
@ -167,6 +174,7 @@ class AlbumCoverManager : public QMainWindow {
|
|||
QList<QListWidgetItem*> context_menu_items_;
|
||||
|
||||
QProgressBar* progress_bar_;
|
||||
QPushButton* abort_progress_;
|
||||
int jobs_;
|
||||
|
||||
LibraryBackend* library_backend_;
|
||||
|
|
|
@ -53,12 +53,15 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSearchField" name="filter">
|
||||
<widget class="QSearchField" name="filter" native="true">
|
||||
<property name="placeholderText" stdset="0">
|
||||
<string>Enter search terms here</string>
|
||||
</property>
|
||||
|
@ -86,18 +89,109 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fetch">
|
||||
<property name="text">
|
||||
<string>Fetch Missing Covers</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0">
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Total albums:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Without cover:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="total_albums">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="without_cover">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fetch">
|
||||
<property name="text">
|
||||
<string>Fetch Missing Covers</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="export_covers">
|
||||
<property name="text">
|
||||
<string>Export Covers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
@ -181,9 +275,6 @@
|
|||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>artists</tabstop>
|
||||
<tabstop>filter</tabstop>
|
||||
<tabstop>view</tabstop>
|
||||
<tabstop>fetch</tabstop>
|
||||
<tabstop>albums</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
|
|
Loading…
Reference in New Issue