Added support for adding, editing and clearing cover artwork by the user.

This commit is contained in:
LoRd_MuldeR 2011-03-22 17:33:03 +01:00
parent cb34771fee
commit 1115a33264
23 changed files with 286 additions and 40 deletions

View File

@ -1247,6 +1247,14 @@
</context>
<context>
<name>MetaInfoDialog</name>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Meta Information</source>
<translation type="unfinished"></translation>
@ -1255,6 +1263,18 @@
<source>The following meta information have been extracted from the original file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1256,6 +1256,26 @@
<source>The following meta information have been extracted from the original file.</source>
<translation>Die folgenden Meta-Informationen wurden aus der Originaldatei extrahiert.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation>Artwork aus Datei laden</translation>
</message>
<message>
<source>Clear Artwork</source>
<translation>Artwork löschen</translation>
</message>
<message>
<source>Load Artwork</source>
<translation>Artwork laden</translation>
</message>
<message>
<source>Artwork Error</source>
<translation>Artwork Fehler</translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation>Artwork konnte nicht aus der Ausgewählten Datei geladen werden!</translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1255,6 +1255,26 @@
<source>The following meta information have been extracted from the original file.</source>
<translation>Los siguientes metadatos han sido extraídos del archivo original.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1264,6 +1264,26 @@ Sélection automatique (par défaut)</translation>
<source>The following meta information have been extracted from the original file.</source>
<translation>Les informations méta suivantes ont é extraites du fichier d&apos;origine.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1256,6 +1256,26 @@
<source>The following meta information have been extracted from the original file.</source>
<translation>Le seguenti meta informazioni sono state estratte dal file originale.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1258,6 +1258,26 @@
<source>The following meta information have been extracted from the original file.</source>
<translation>Эта метаинформация была получена из исходного файла.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -1255,6 +1255,26 @@
<source>The following meta information have been extracted from the original file.</source>
<translation type="unfinished">Дана метаінформація була витягнута з оригінального файла.</translation>
</message>
<message>
<source>Load Artwork From File</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Artwork</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Artwork Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sorry, failed to load artwork from selected file!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MetaInfoModel</name>

View File

@ -46,6 +46,7 @@
..\..\src\Global.cpp
..\..\src\LockedFile.cpp
..\..\src\Main.cpp
..\..\src\Model_Artwork.cpp
..\..\src\Model_AudioFile.cpp
..\..\src\Model_FileList.cpp
..\..\src\Model_FileSystem.cpp
@ -102,6 +103,7 @@
..\..\src\Genres.h
..\..\src\Global.h
..\..\src\LockedFile.h
..\..\src\Model_Artwork.h
..\..\src\Model_AudioFile.h
..\..\src\Model_FileList.h
..\..\src\Model_FileSystem.h

View File

@ -191,6 +191,9 @@
</item>
<item>
<widget class="QFrame" name="frameArtwork">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
@ -257,6 +260,9 @@
</property>
<item>
<widget class="QLabel" name="labelArtwork">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string notr="true">(ARTWORK)</string>
</property>
@ -488,6 +494,9 @@
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
</resources>
<connections>
<connection>
@ -538,22 +547,6 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonArtwork</sender>
<signal>clicked(bool)</signal>
<receiver>editButton</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>55</x>
<y>396</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>396</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonArtwork</sender>
<signal>clicked(bool)</signal>

View File

@ -2,6 +2,7 @@
<RCC version="1.0">
<qresource>
<file>images/Busy.gif</file>
<file>images/CD.png</file>
<file>images/DropBox.png</file>
<file>images/HeaderIcon_LogFile.png</file>
<file>images/HeaderIcon_MetaInfo.png</file>

BIN
res/images/CD.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

View File

@ -25,7 +25,7 @@
#define VER_LAMEXP_MAJOR 4
#define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 1
#define VER_LAMEXP_BUILD 394
#define VER_LAMEXP_BUILD 398
#define VER_LAMEXP_SUFFIX Beta-11
/*

View File

@ -2136,7 +2136,7 @@ void MainWindow::restoreCursor(void)
void MainWindow::sourceFilesContextMenu(const QPoint &pos)
{
QAbstractScrollArea *scrollArea = dynamic_cast<QAbstractScrollArea*>(QObject::sender());
QWidget *sender = scrollArea ? scrollArea->viewport() : dynamic_cast<QWidget*>(QObject::sender());
QWidget *sender = scrollArea ? scrollArea->viewport() : dynamic_cast<QWidget*>(QObject::sender());
if(sender)
{

View File

@ -27,9 +27,18 @@
#include <QFileInfo>
#include <QMessageBox>
#include <QTimer>
#include <QFileDialog>
#include <QMenu>
#define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
////////////////////////////////////////////////////////////
// Constructor & Destructor
////////////////////////////////////////////////////////////
MetaInfoDialog::MetaInfoDialog(QWidget *parent)
: QDialog(parent)
:
QDialog(parent)
{
//Init the dialog, from the .ui file
setupUi(this);
@ -52,14 +61,29 @@ MetaInfoDialog::MetaInfoDialog(QWidget *parent)
connect(downButton, SIGNAL(clicked()), this, SLOT(downButtonClicked()));
connect(editButton, SIGNAL(clicked()), this, SLOT(editButtonClicked()));
//Create context menu
m_contextMenu = new QMenu();
QAction *loadArtworkAction = m_contextMenu->addAction(QIcon(":/icons/folder_image.png"), tr("Load Artwork From File"));
QAction *clearArtworkAction = m_contextMenu->addAction(QIcon(":/icons/bin.png"), tr("Clear Artwork"));
SET_FONT_BOLD(loadArtworkAction, true);
connect(labelArtwork, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint)));
connect(frameArtwork, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint)));
connect(loadArtworkAction, SIGNAL(triggered(bool)), this, SLOT(editButtonClicked()));
connect(clearArtworkAction, SIGNAL(triggered(bool)), this, SLOT(clearArtworkActionTriggered()));
//Translate
labelHeaderText->setText(QString("<b>%1</b><br>%2").arg(tr("Meta Information"), tr("The following meta information have been extracted from the original file.")));
}
MetaInfoDialog::~MetaInfoDialog(void)
{
LAMEXP_DELETE(m_contextMenu);
}
////////////////////////////////////////////////////////////
// Slots
////////////////////////////////////////////////////////////
int MetaInfoDialog::exec(AudioFileModel &audioFile, bool allowUp, bool allowDown)
{
MetaInfoModel *model = new MetaInfoModel(&audioFile);
@ -71,25 +95,28 @@ int MetaInfoDialog::exec(AudioFileModel &audioFile, bool allowUp, bool allowDown
upButton->setEnabled(allowUp);
downButton->setEnabled(allowDown);
buttonArtwork->setChecked(false);
buttonArtwork->setEnabled(false);
if(!audioFile.fileCover().isEmpty())
{
QImage artwork;
if(artwork.load(audioFile.fileCover()))
{
if((artwork.width() > 320) || (artwork.height() > 240))
if((artwork.width() > 256) || (artwork.height() > 256))
{
artwork = artwork.scaled(320, 240, Qt::KeepAspectRatio, Qt::SmoothTransformation);
artwork = artwork.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
labelArtwork->setPixmap(QPixmap::fromImage(artwork));
buttonArtwork->setEnabled(true);
}
else
{
qWarning("Error: Failed to load cover art!");
labelArtwork->setPixmap(QPixmap::fromImage(QImage(":/images/CD.png")));
}
}
else
{
labelArtwork->setPixmap(QPixmap::fromImage(QImage(":/images/CD.png")));
}
int iResult = QDialog::exec();
@ -111,5 +138,50 @@ void MetaInfoDialog::downButtonClicked(void)
void MetaInfoDialog::editButtonClicked(void)
{
dynamic_cast<MetaInfoModel*>(tableView->model())->editItem(tableView->currentIndex(), this);
if(!buttonArtwork->isChecked())
{
dynamic_cast<MetaInfoModel*>(tableView->model())->editItem(tableView->currentIndex(), this);
return;
}
QString fileName = QFileDialog::getOpenFileName(this, tr("Load Artwork"), QString(), QString::fromLatin1("JPEG (*.jpg);;PNG (*.png);;GIF (*.gif)"));
if(!fileName.isEmpty())
{
QImage artwork;
if(artwork.load(fileName))
{
if((artwork.width() > 256) || (artwork.height() > 256))
{
artwork = artwork.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
dynamic_cast<MetaInfoModel*>(tableView->model())->editArtwork(fileName);
labelArtwork->setPixmap(QPixmap::fromImage(artwork));
}
else
{
qWarning("Error: Failed to load cover art!");
QMessageBox::warning(this, tr("Artwork Error"), QString("<nobr>%1</nobr><br><br><nobr>%2</nobr>").arg(tr("Sorry, failed to load artwork from selected file!"), QDir::toNativeSeparators(fileName)));
}
}
}
void MetaInfoDialog::contextMenuRequested(const QPoint &pos)
{
QAbstractScrollArea *scrollArea = dynamic_cast<QAbstractScrollArea*>(QObject::sender());
QWidget *sender = scrollArea ? scrollArea->viewport() : dynamic_cast<QWidget*>(QObject::sender());
if(sender)
{
if(pos.x() <= sender->width() && pos.y() <= sender->height() && pos.x() >= 0 && pos.y() >= 0)
{
m_contextMenu->popup(sender->mapToGlobal(pos));
}
}
}
void MetaInfoDialog::clearArtworkActionTriggered(void)
{
labelArtwork->setPixmap(QPixmap::fromImage(QImage(":/images/CD.png")));
dynamic_cast<MetaInfoModel*>(tableView->model())->editArtwork(QString());
}

View File

@ -40,5 +40,9 @@ private slots:
void upButtonClicked(void);
void downButtonClicked(void);
void editButtonClicked(void);
void contextMenuRequested(const QPoint &pos);
void clearArtworkActionTriggered(void);
private:
QMenu *m_contextMenu;
};

View File

@ -38,21 +38,24 @@ QMap<QString, QFile*> ArtworkModel::m_fileHandle;
ArtworkModel::ArtworkModel(void)
{
m_isOwner = false;
}
ArtworkModel::ArtworkModel(const QString &fileName)
ArtworkModel::ArtworkModel(const QString &fileName, bool isOwner)
{
setFilePath(fileName);
m_isOwner = false;
setFilePath(fileName, isOwner);
}
ArtworkModel::ArtworkModel(const ArtworkModel &model)
{
setFilePath(model.m_filePath);
m_isOwner = false;
setFilePath(model.m_filePath, model.m_isOwner);
}
ArtworkModel &ArtworkModel::operator=(const ArtworkModel &model)
{
setFilePath(model.m_filePath);
setFilePath(model.m_filePath, model.m_isOwner);
return (*this);
}
@ -71,7 +74,12 @@ const QString &ArtworkModel::filePath(void) const
return m_filePath;
}
void ArtworkModel::setFilePath(const QString &newPath)
bool ArtworkModel::isOwner(void) const
{
return m_isOwner;
}
void ArtworkModel::setFilePath(const QString &newPath, bool isOwner)
{
if(newPath.isEmpty() || m_filePath.isEmpty() || QString::compare(m_filePath, newPath,Qt::CaseInsensitive))
{
@ -92,6 +100,7 @@ void ArtworkModel::setFilePath(const QString &newPath)
}
m_filePath = newPath;
m_isOwner = isOwner;
}
}
@ -111,15 +120,25 @@ void ArtworkModel:: clear(void)
{
if(QFile *fileHandle = m_fileHandle.take(m_filePath))
{
fileHandle->remove();
if(m_isOwner)
{
fileHandle->remove();
}
else
{
fileHandle->close();
}
LAMEXP_DELETE(fileHandle);
}
}
QFile::remove(m_filePath);
if(m_isOwner)
{
QFile::remove(m_filePath);
}
}
}
m_filePath.clear();
}
}

View File

@ -31,17 +31,19 @@ class ArtworkModel
{
public:
ArtworkModel(void);
ArtworkModel(const QString &fileName);
ArtworkModel(const QString &fileName, bool isOwner = true);
ArtworkModel(const ArtworkModel &model);
ArtworkModel &operator=(const ArtworkModel &model);
~ArtworkModel(void);
const QString &filePath(void) const;
void setFilePath(const QString &newPath);
bool isOwner(void) const;
void setFilePath(const QString &newPath, bool isOwner = true);
void clear(void);
private:
QString m_filePath;
bool m_isOwner;
static QMutex m_mutex;
static QMap<QString, unsigned int> m_refCount;

View File

@ -60,7 +60,7 @@ AudioFileModel::AudioFileModel(const AudioFileModel &model, bool copyMetaInfo)
setFileAlbum(model.m_fileAlbum);
setFileGenre(model.m_fileGenre);
setFileComment(model.m_fileComment);
setFileCover(model.m_fileCover.filePath());
setFileCover(model.m_fileCover);
setFileYear(model.m_fileYear);
setFilePosition(model.m_filePosition);
}
@ -74,7 +74,7 @@ AudioFileModel &AudioFileModel::operator=(const AudioFileModel &model)
setFileAlbum(model.m_fileAlbum);
setFileGenre(model.m_fileGenre);
setFileComment(model.m_fileComment);
setFileCover(model.m_fileCover.filePath());
setFileCover(model.m_fileCover);
setFileYear(model.m_fileYear);
setFilePosition(model.m_filePosition);
setFileDuration(model.m_fileDuration);
@ -337,9 +337,14 @@ void AudioFileModel::setFileComment(const QString &comment)
m_fileComment = comment;
}
void AudioFileModel::setFileCover(const QString &coverFile)
void AudioFileModel::setFileCover(const QString &coverFile, bool owner)
{
m_fileCover = ArtworkModel(coverFile);
m_fileCover.setFilePath(coverFile, owner);
}
void AudioFileModel::setFileCover(const ArtworkModel &model)
{
m_fileCover = model;
}
void AudioFileModel::setFileYear(unsigned int year)

View File

@ -77,7 +77,8 @@ public:
void setFileAlbum(const QString &album);
void setFileGenre(const QString &genre);
void setFileComment(const QString &comment);
void setFileCover(const QString &coverFile);
void setFileCover(const QString &coverFile, bool owner);
void setFileCover(const ArtworkModel &model);
void setFileYear(unsigned int year);
void setFilePosition(unsigned int position);
void setFileDuration(unsigned int duration);

View File

@ -430,6 +430,11 @@ void MetaInfoModel::editItem(const QModelIndex &index, QWidget *parent)
}
}
void MetaInfoModel::editArtwork(const QString &imagePath)
{
m_audioFile->setFileCover(imagePath, false);
}
void MetaInfoModel::clearData(void)
{
beginResetModel();
@ -443,6 +448,7 @@ void MetaInfoModel::clearData(void)
m_audioFile->setFileAlbum(QString());
m_audioFile->setFileGenre(QString());
m_audioFile->setFileComment(tr("Encoded with LameXP"));
m_audioFile->setFileCover(QString(), false);
m_audioFile->setFileYear(0);
m_audioFile->setFilePosition(UINT_MAX);
m_audioFile->setFileDuration(0);

View File

@ -42,6 +42,7 @@ public:
bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
void editItem(const QModelIndex &index, QWidget *parent);
void editArtwork(const QString &imagePath);
void clearData(void);
private:

View File

@ -473,7 +473,7 @@ void FileAnalyzer::retrieveCover(AudioFileModel &audioFile, const QString &fileP
{
coverFile.write(coverData);
coverFile.close();
audioFile.setFileCover(coverFile.fileName());
audioFile.setFileCover(coverFile.fileName(), true);
}
break;
}