Allow querying LyricsWikia for metadata

Querying lyrics has not been implemented yet
This commit is contained in:
Martchus 2016-10-09 19:44:06 +02:00
parent 8d6d60d939
commit 958cd9960c
20 changed files with 902 additions and 546 deletions

View File

@ -59,6 +59,8 @@ set(WIDGETS_HEADER_FILES
gui/tageditorwidget.h
gui/fileinfomodel.h
dbquery/dbquery.h
dbquery/musicbrainz.h
dbquery/lyricswikia.h
gui/dbquerywidget.h
misc/networkaccessmanager.h
renamingutility/filesystemitem.h
@ -89,6 +91,8 @@ set(WIDGETS_SRC_FILES
gui/tageditorwidget.cpp
gui/fileinfomodel.cpp
dbquery/dbquery.cpp
dbquery/musicbrainz.cpp
dbquery/lyricswikia.cpp
gui/dbquerywidget.cpp
misc/networkaccessmanager.cpp
renamingutility/filesystemitem.cpp

View File

@ -74,8 +74,9 @@ There is also a tool to rename files using the tag information stored in the fil
by a small JavaScript which can be customized. An example script is provided. Before any actual changes are made,
you will see a preview with the generated file names.
#### MusicBrainz search
The tag editor also features a MusicBrainz and Cover Art Archive search which can be opened with *F10*. However, this feature is still experimental.
#### MusicBrainz, Cover Art Archive and LyricaWiki search
The tag editor also features a MusicBrainz, Cover Art Archive and LyricaWiki search which can be opened with *F10*.
However, this feature is still experimental.
### CLI
#### Usage
@ -194,3 +195,4 @@ To build without GUI, add the following parameters to the CMake call:
- Large file information is not shown when using Qt WebEngine
- It is recommend you to create backups before editing because I can not test whether the library works with all kind of files (when forcing rewrite a backup is always created)
- underlying library: Matroska files composed of more than one segment aren't tested yet and might not work.
- Also note the issue tracker on GitHub

View File

@ -281,6 +281,12 @@ QString &coverArtArchiveUrl()
return v;
}
QString &lyricsWikiaUrl()
{
static QString v;
return v;
}
// renaming files dialog
int &scriptSource()
{

View File

@ -110,6 +110,7 @@ bool &dbQueryOverride();
KnownFieldModel &dbQueryFields();
QString &musicBrainzUrl();
QString &coverArtArchiveUrl();
QString &lyricsWikiaUrl();
// rename files dialog
int &scriptSource();

View File

@ -2,20 +2,14 @@
#include "../misc/utility.h"
#include "../misc/networkaccessmanager.h"
#include "../application/settings.h"
#include <tagparser/tagvalue.h>
#include <tagparser/tag.h>
#include <tagparser/signature.h>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
#include <QStringBuilder>
#include <QXmlStreamReader>
#include <QMessageBox>
#include <map>
#ifdef DEBUG_BUILD
# include <iostream>
#endif
@ -215,40 +209,37 @@ bool QueryResultsModel::fetchCover(const QModelIndex &)
return false;
}
class HttpResultsModel : public QueryResultsModel
{
Q_OBJECT
public:
~HttpResultsModel();
void addReply(QNetworkReply *reply);
void abort();
protected:
HttpResultsModel(QNetworkReply *reply);
virtual void parseResults(QNetworkReply *reply, const QByteArray &data) = 0;
private slots:
void handleReplyFinished();
protected:
QList<QNetworkReply *> m_replies;
};
HttpResultsModel::HttpResultsModel(QNetworkReply *reply)
/*!
* \brief Constructs a new HttpResultsModel for the specified \a reply.
* \remarks The model takes ownership over the specified \a reply.
*/
HttpResultsModel::HttpResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply) :
m_initialDescription(initialSongDescription)
{
addReply(reply);
}
/*!
* \brief Deletes all associated replies.
*/
HttpResultsModel::~HttpResultsModel()
{
qDeleteAll(m_replies);
}
/*!
* \brief Helper to copy a property from one QObject to another.
* \remarks Used to transfer reply properties to new reply in case a second reply is required.
*/
void copyProperty(const char *property, const QObject *from, QObject *to)
{
to->setProperty(property, from->property(property));
}
/*!
* \brief Evaluates request results.
* \remarks Calls parseResults() if the requested data is available. Handles errors/redirections otherwise.
*/
void HttpResultsModel::handleReplyFinished()
{
auto *reply = static_cast<QNetworkReply *>(sender());
@ -296,6 +287,10 @@ void HttpResultsModel::handleReplyFinished()
setResultsAvailable(true);
}
/*!
* \brief Adds a reply.
* \remarks Called within c'tor and handleReplyFinished() in case of redirection. Might be called when subclassing to do further requests.
*/
void HttpResultsModel::addReply(QNetworkReply *reply)
{
m_replies << reply;
@ -305,6 +300,9 @@ void HttpResultsModel::addReply(QNetworkReply *reply)
connect(reply, &QNetworkReply::finished, this, &HttpResultsModel::handleReplyFinished);
}
/*!
* \brief Aborts all ongoing requests and causes error "Aborted by user" if requests where ongoing.
*/
void HttpResultsModel::abort()
{
if(!m_replies.isEmpty()) {
@ -316,222 +314,6 @@ void HttpResultsModel::abort()
}
}
class MusicBrainzResultsModel : public HttpResultsModel
{
Q_OBJECT
private:
enum What {
MusicBrainzMetaData,
CoverArt
};
public:
MusicBrainzResultsModel(QNetworkReply *reply);
bool fetchCover(const QModelIndex &index);
static QNetworkRequest coverRequest(const QString &albumId);
protected:
void parseResults(QNetworkReply *reply, const QByteArray &data);
private:
static map<QString, QByteArray> m_coverData;
QXmlStreamReader m_reader;
What m_what;
};
map<QString, QByteArray> MusicBrainzResultsModel::m_coverData = map<QString, QByteArray>();
MusicBrainzResultsModel::MusicBrainzResultsModel(QNetworkReply *reply) :
HttpResultsModel(reply)
{}
bool MusicBrainzResultsModel::fetchCover(const QModelIndex &index)
{
if(!index.parent().isValid() && index.row() < m_results.size()) {
SongDescription &desc = m_results[index.row()];
if(!desc.cover.isEmpty()) {
// cover is already available -> nothing to do
} else if(!desc.albumId.isEmpty()) {
try {
// the item belongs to an album which cover has already been fetched
desc.cover = m_coverData.at(desc.albumId);
} catch(const out_of_range &) {
// request the cover art
QNetworkReply *reply = queryCoverArtArchive(desc.albumId);
addReply(reply);
reply->setProperty("coverArt", true);
reply->setProperty("albumId", desc.albumId);
reply->setProperty("row", index.row());
setFetchingCover(true);
return false;
}
} else {
m_errorList << tr("Unable to fetch cover: Album ID is unknown.");
emit resultsAvailable();
}
}
return true;
}
void MusicBrainzResultsModel::parseResults(QNetworkReply *reply, const QByteArray &data)
{
if(reply->property("coverArt").toBool()) {
// add cover -> determine album ID and row
bool ok;
QString albumId = reply->property("albumId").toString();
int row = reply->property("row").toInt(&ok);
if(!albumId.isEmpty() && ok && row < m_results.size()) {
m_coverData[albumId] = data;
m_results[row].cover = data;
emit coverAvailable(index(row, 0));
} else {
m_errorList << tr("Cover reply is invalid (internal error).");
}
setFetchingCover(false);
} else {
// prepare parsing MusicBrainz meta data
beginResetModel();
m_results.clear();
m_reader.addData(data);
// parse XML tree
#define xmlReader m_reader
#include <qtutilities/misc/xmlparsermacros.h>
children {
iftag("metadata") {
children {
iftag("recording-list") {
children {
iftag("recording") {
SongDescription currentDescription;
children {
iftag("title") {
currentDescription.title = text;
} eliftag("artist-credit") {
children {
iftag("name-credit") {
children {
iftag("artist") {
children {
iftag("name") {
currentDescription.artist = text;
} else_skip
}
} else_skip
}
} else_skip
}
} eliftag("release-list") {
children {
iftag("release") {
if(currentDescription.albumId.isEmpty()) {
currentDescription.albumId = attribute("id").toString();
}
children {
iftag("title") {
currentDescription.album = text;
} eliftag("date") {
currentDescription.year = text;
} eliftag("medium-list") {
children {
iftag("medium") {
children {
iftag("position") {
currentDescription.disk = text.toUInt();
} eliftag("track-list") {
currentDescription.totalTracks = attribute("count").toUInt();
children {
iftag("track") {
children {
iftag("number") {
currentDescription.track = text.toUInt();
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} eliftag("tag-list") {
children {
iftag("tag") {
children {
iftag("name") {
if(!currentDescription.genre.isEmpty()) {
currentDescription.genre.append(QLatin1Char(' '));
}
currentDescription.genre.append(text);
} else_skip
}
} else_skip
}
} else_skip
}
m_results << currentDescription;
} else_skip
}
} else_skip
}
} else_skip
}
#include <qtutilities/misc/undefxmlparsermacros.h>
// check for parsing errors
switch(m_reader.error()) {
case QXmlStreamReader::NoError:
case QXmlStreamReader::PrematureEndOfDocumentError:
break;
default:
m_errorList << m_reader.errorString();
}
// promote changes
endResetModel();
}
}
QueryResultsModel *queryMusicBrainz(const SongDescription &songDescription)
{
static QString defaultMusicBrainzUrl(QStringLiteral("https://musicbrainz.org/ws/2/recording/"));
// compose parts
QStringList parts;
parts.reserve(4);
if(!songDescription.title.isEmpty()) {
parts << QChar('\"') % songDescription.title % QChar('\"');
}
if(!songDescription.artist.isEmpty()) {
parts << QStringLiteral("artist:\"") % songDescription.artist % QChar('\"');
}
if(!songDescription.album.isEmpty()) {
parts << QStringLiteral("release:\"") % songDescription.album % QChar('\"');
}
if(songDescription.track) {
parts << QStringLiteral("number:") + QString::number(songDescription.track);
}
// compose URL
QUrl url(Settings::musicBrainzUrl().isEmpty() ? defaultMusicBrainzUrl : (Settings::musicBrainzUrl() + QStringLiteral("/recording/")));
QUrlQuery query;
query.addQueryItem(QStringLiteral("query"), parts.join(QStringLiteral(" AND ")));
url.setQuery(query);
// make request
return new MusicBrainzResultsModel(Utility::networkAccessManager().get(QNetworkRequest(url)));
}
QNetworkReply *queryCoverArtArchive(const QString &albumId)
{
static QString defaultArchiveUrl(QStringLiteral("https://coverartarchive.org"));
return networkAccessManager().get(QNetworkRequest(QUrl((Settings::coverArtArchiveUrl().isEmpty() ? defaultArchiveUrl : Settings::coverArtArchiveUrl()) % QStringLiteral("/release/") % albumId % QStringLiteral("/front"))));
}
}
#include "dbquery.moc"

View File

@ -95,7 +95,28 @@ inline bool QueryResultsModel::isFetchingCover() const
return m_fetchingCover;
}
QueryResultsModel *queryMusicBrainz(const SongDescription &songDescription);
class HttpResultsModel : public QueryResultsModel
{
Q_OBJECT
public:
~HttpResultsModel();
void abort();
protected:
HttpResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply);
void addReply(QNetworkReply *reply);
virtual void parseResults(QNetworkReply *reply, const QByteArray &data) = 0;
private slots:
void handleReplyFinished();
protected:
QList<QNetworkReply *> m_replies;
const SongDescription m_initialDescription;
};
QueryResultsModel *queryMusicBrainz(SongDescription &&songDescription);
QueryResultsModel *queryLyricsWikia(SongDescription &&songDescription);
QNetworkReply *queryCoverArtArchive(const QString &albumId);
}

115
dbquery/lyricswikia.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "./lyricswikia.h"
#include "../misc/networkaccessmanager.h"
#include "../application/settings.h"
#include <QUrlQuery>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
using namespace std;
using namespace Utility;
namespace QtGui {
LyricsWikiaResultsModel::LyricsWikiaResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply) :
HttpResultsModel(move(initialSongDescription), reply)
{}
void LyricsWikiaResultsModel::parseResults(QNetworkReply *reply, const QByteArray &data)
{
Q_UNUSED(reply)
// prepare parsing MusicBrainz meta data
beginResetModel();
m_results.clear();
m_reader.addData(data);
// parse XML tree
#define xmlReader m_reader
#include <qtutilities/misc/xmlparsermacros.h>
children {
iftag("getArtistResponse") {
QString artist;
children {
iftag("artist") {
artist = text;
} eliftag("albums") {
children {
iftag("albumResult") {
QString album, year;
QList<SongDescription> songs;
children {
iftag("album") {
album = text;
} eliftag("year") {
year = text;
} eliftag("songs") {
children {
iftag("item") {
songs << SongDescription();
songs.back().title = text;
songs.back().track = static_cast<unsigned int>(songs.size());
} else_skip
}
} else_skip
// need to filter results manually because the filtering provided by Lyrica Wiki API doesn't work
if((m_initialDescription.album.isEmpty() || m_initialDescription.album == album)
&& (m_initialDescription.year.isEmpty() || m_initialDescription.year == year)
&& (!m_initialDescription.totalTracks || m_initialDescription.totalTracks == static_cast<unsigned int>(songs.size()))) {
for(SongDescription &song : songs) {
if((m_initialDescription.title.isEmpty() || m_initialDescription.title == song.title)
&& (!m_initialDescription.track || m_initialDescription.track == static_cast<unsigned int>(songs.size()))) {
song.album = album;
song.year = year;
song.totalTracks = static_cast<unsigned int>(songs.size());
m_results << move(song);
}
}
}
}
} else_skip
}
} else_skip
}
for(SongDescription &song : m_results) {
song.artist = artist;
}
} else_skip
}
#include <qtutilities/misc/undefxmlparsermacros.h>
// check for parsing errors
switch(m_reader.error()) {
case QXmlStreamReader::NoError:
case QXmlStreamReader::PrematureEndOfDocumentError:
break;
default:
m_errorList << m_reader.errorString();
}
// promote changes
endResetModel();
}
QueryResultsModel *queryLyricsWikia(SongDescription &&songDescription)
{
static QString defaultUrl(QStringLiteral("https://lyrics.wikia.com/api.php"));
// compose URL
QUrl url(Settings::lyricsWikiaUrl().isEmpty() ? defaultUrl : Settings::lyricsWikiaUrl());
QUrlQuery query;
query.addQueryItem(QStringLiteral("func"), QStringLiteral("getArtist"));
query.addQueryItem(QStringLiteral("fmt"), QStringLiteral("xml"));
query.addQueryItem(QStringLiteral("fixXML"), QString());
query.addQueryItem(QStringLiteral("artist"), songDescription.artist);
url.setQuery(query);
// NOTE: Only getArtist seems to work, so artist must be specified and filtering must
// be done manually when parsing results.
// make request
return new LyricsWikiaResultsModel(move(songDescription), Utility::networkAccessManager().get(QNetworkRequest(url)));
}
} // namespace QtGui

27
dbquery/lyricswikia.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef QTGUI_LYRICSWIKIA_H
#define QTGUI_LYRICSWIKIA_H
#include "./dbquery.h"
#include <QXmlStreamReader>
namespace QtGui {
class LyricsWikiaResultsModel : public HttpResultsModel
{
Q_OBJECT
public:
LyricsWikiaResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply);
protected:
void parseResults(QNetworkReply *reply, const QByteArray &data);
private:
QXmlStreamReader m_reader;
};
} // namespace QtGui
#endif // QTGUI_LYRICSWIKIA_H

209
dbquery/musicbrainz.cpp Normal file
View File

@ -0,0 +1,209 @@
#include "./musicbrainz.h"
#include "../misc/utility.h"
#include "../misc/networkaccessmanager.h"
#include "../application/settings.h"
#include <QStringBuilder>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
using namespace std;
using namespace Utility;
namespace QtGui {
map<QString, QByteArray> MusicBrainzResultsModel::m_coverData = map<QString, QByteArray>();
MusicBrainzResultsModel::MusicBrainzResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply) :
HttpResultsModel(move(initialSongDescription), reply)
{}
bool MusicBrainzResultsModel::fetchCover(const QModelIndex &index)
{
if(!index.parent().isValid() && index.row() < m_results.size()) {
SongDescription &desc = m_results[index.row()];
if(!desc.cover.isEmpty()) {
// cover is already available -> nothing to do
} else if(!desc.albumId.isEmpty()) {
try {
// the item belongs to an album which cover has already been fetched
desc.cover = m_coverData.at(desc.albumId);
} catch(const out_of_range &) {
// request the cover art
QNetworkReply *reply = queryCoverArtArchive(desc.albumId);
addReply(reply);
reply->setProperty("coverArt", true);
reply->setProperty("albumId", desc.albumId);
reply->setProperty("row", index.row());
setFetchingCover(true);
return false;
}
} else {
m_errorList << tr("Unable to fetch cover: Album ID is unknown.");
emit resultsAvailable();
}
}
return true;
}
void MusicBrainzResultsModel::parseResults(QNetworkReply *reply, const QByteArray &data)
{
if(reply->property("coverArt").toBool()) {
// add cover -> determine album ID and row
bool ok;
QString albumId = reply->property("albumId").toString();
int row = reply->property("row").toInt(&ok);
if(!albumId.isEmpty() && ok && row < m_results.size()) {
m_coverData[albumId] = data;
m_results[row].cover = data;
emit coverAvailable(index(row, 0));
} else {
m_errorList << tr("Cover reply is invalid (internal error).");
}
setFetchingCover(false);
} else {
// prepare parsing MusicBrainz meta data
beginResetModel();
m_results.clear();
m_reader.addData(data);
// parse XML tree
#define xmlReader m_reader
#include <qtutilities/misc/xmlparsermacros.h>
children {
iftag("metadata") {
children {
iftag("recording-list") {
children {
iftag("recording") {
SongDescription currentDescription;
children {
iftag("title") {
currentDescription.title = text;
} eliftag("artist-credit") {
children {
iftag("name-credit") {
children {
iftag("artist") {
children {
iftag("name") {
currentDescription.artist = text;
} else_skip
}
} else_skip
}
} else_skip
}
} eliftag("release-list") {
children {
iftag("release") {
if(currentDescription.albumId.isEmpty()) {
currentDescription.albumId = attribute("id").toString();
}
children {
iftag("title") {
currentDescription.album = text;
} eliftag("date") {
currentDescription.year = text;
} eliftag("medium-list") {
children {
iftag("medium") {
children {
iftag("position") {
currentDescription.disk = text.toUInt();
} eliftag("track-list") {
currentDescription.totalTracks = attribute("count").toUInt();
children {
iftag("track") {
children {
iftag("number") {
currentDescription.track = text.toUInt();
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} else_skip
}
} eliftag("tag-list") {
children {
iftag("tag") {
children {
iftag("name") {
if(!currentDescription.genre.isEmpty()) {
currentDescription.genre.append(QLatin1Char(' '));
}
currentDescription.genre.append(text);
} else_skip
}
} else_skip
}
} else_skip
}
m_results << currentDescription;
} else_skip
}
} else_skip
}
} else_skip
}
#include <qtutilities/misc/undefxmlparsermacros.h>
// check for parsing errors
switch(m_reader.error()) {
case QXmlStreamReader::NoError:
case QXmlStreamReader::PrematureEndOfDocumentError:
break;
default:
m_errorList << m_reader.errorString();
}
// promote changes
endResetModel();
}
}
QueryResultsModel *queryMusicBrainz(SongDescription &&songDescription)
{
static QString defaultMusicBrainzUrl(QStringLiteral("https://musicbrainz.org/ws/2/recording/"));
// compose parts
QStringList parts;
parts.reserve(4);
if(!songDescription.title.isEmpty()) {
parts << QChar('\"') % songDescription.title % QChar('\"');
}
if(!songDescription.artist.isEmpty()) {
parts << QStringLiteral("artist:\"") % songDescription.artist % QChar('\"');
}
if(!songDescription.album.isEmpty()) {
parts << QStringLiteral("release:\"") % songDescription.album % QChar('\"');
}
if(songDescription.track) {
parts << QStringLiteral("number:") + QString::number(songDescription.track);
}
// compose URL
QUrl url(Settings::musicBrainzUrl().isEmpty() ? defaultMusicBrainzUrl : (Settings::musicBrainzUrl() + QStringLiteral("/recording/")));
QUrlQuery query;
query.addQueryItem(QStringLiteral("query"), parts.join(QStringLiteral(" AND ")));
url.setQuery(query);
// make request
return new MusicBrainzResultsModel(move(songDescription), Utility::networkAccessManager().get(QNetworkRequest(url)));
}
QNetworkReply *queryCoverArtArchive(const QString &albumId)
{
static QString defaultArchiveUrl(QStringLiteral("https://coverartarchive.org"));
return networkAccessManager().get(QNetworkRequest(QUrl((Settings::coverArtArchiveUrl().isEmpty() ? defaultArchiveUrl : Settings::coverArtArchiveUrl()) % QStringLiteral("/release/") % albumId % QStringLiteral("/front"))));
}
} // namespace QtGui

39
dbquery/musicbrainz.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef QTGUI_MUSICBRAINZ_H
#define QTGUI_MUSICBRAINZ_H
#include "./dbquery.h"
#include <QXmlStreamReader>
#include <map>
QT_FORWARD_DECLARE_CLASS(QNetworkRequest)
namespace QtGui {
class MusicBrainzResultsModel : public HttpResultsModel
{
Q_OBJECT
private:
enum What {
MusicBrainzMetaData,
CoverArt
};
public:
MusicBrainzResultsModel(SongDescription &&initialSongDescription, QNetworkReply *reply);
bool fetchCover(const QModelIndex &index);
static QNetworkRequest coverRequest(const QString &albumId);
protected:
void parseResults(QNetworkReply *reply, const QByteArray &data);
private:
static std::map<QString, QByteArray> m_coverData;
QXmlStreamReader m_reader;
What m_what;
};
} // namespace QtGui
#endif // QTGUI_MUSICBRAINZ_H

View File

@ -45,7 +45,7 @@ DbQueryWidget::DbQueryWidget(TagEditorWidget *tagEditorWidget, QWidget *parent)
setStyleSheet(QStringLiteral("QGroupBox { color: palette(text); background-color: palette(base); }"));
#endif
m_ui->notificationLabel->setText(tr("Search hasn't been started."));
m_ui->notificationLabel->setText(tr("Search hasn't been started"));
m_ui->searchGroupBox->installEventFilter(this);
// initialize buttons
@ -74,7 +74,8 @@ DbQueryWidget::DbQueryWidget(TagEditorWidget *tagEditorWidget, QWidget *parent)
// connect signals and slots
connect(m_ui->abortPushButton, &QPushButton::clicked, this, &DbQueryWidget::abortSearch);
connect(m_ui->startPushButton, &QPushButton::clicked, this, &DbQueryWidget::startSearch);
connect(m_ui->searchMusicBrainzPushButton, &QPushButton::clicked, this, &DbQueryWidget::searchMusicBrainz);
connect(m_ui->searchLyricsWikiaPushButton, &QPushButton::clicked, this, &DbQueryWidget::searchLyricsWikia);
connect(m_ui->applyPushButton, &QPushButton::clicked, this, &DbQueryWidget::applyResults);
connect(m_tagEditorWidget, &TagEditorWidget::fileStatusChanged, this, &DbQueryWidget::fileStatusChanged);
connect(m_ui->resultsTreeView, &QTreeView::customContextMenuRequested, this, &DbQueryWidget::showResultsContextMenu);
@ -116,9 +117,9 @@ void DbQueryWidget::insertSearchTermsFromTagEdit(TagEdit *tagEdit)
}
}
void DbQueryWidget::startSearch()
void DbQueryWidget::searchMusicBrainz()
{
// check whether enought search terms are supplied
// check whether enough search terms are supplied
if(m_ui->titleLineEdit->text().isEmpty() && m_ui->albumLineEdit->text().isEmpty() && m_ui->artistLineEdit->text().isEmpty()) {
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
m_ui->notificationLabel->setText(tr("Insufficient search criteria supplied"));
@ -142,7 +143,38 @@ void DbQueryWidget::startSearch()
desc.track = m_ui->trackSpinBox->value();
// do actual query
m_ui->resultsTreeView->setModel(m_model = queryMusicBrainz(desc));
m_ui->resultsTreeView->setModel(m_model = queryMusicBrainz(std::move(desc)));
connect(m_model, &QueryResultsModel::resultsAvailable, this, &DbQueryWidget::showResults);
connect(m_model, &QueryResultsModel::coverAvailable, this, &DbQueryWidget::showCoverFromIndex);
}
void DbQueryWidget::searchLyricsWikia()
{
// check whether enough search terms are supplied
if(m_ui->artistLineEdit->text().isEmpty()) {
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
m_ui->notificationLabel->setText(tr("Insufficient search criteria supplied"));
return;
}
// delete current model
m_ui->resultsTreeView->setModel(nullptr);
delete m_model;
// show status
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
m_ui->notificationLabel->setText(tr("Retrieving meta data ..."));
setStatus(false);
// get song description
SongDescription desc;
desc.title = m_ui->titleLineEdit->text();
desc.album = m_ui->albumLineEdit->text();
desc.artist = m_ui->artistLineEdit->text();
desc.track = static_cast<unsigned int>(m_ui->trackSpinBox->value());
// do actual query
m_ui->resultsTreeView->setModel(m_model = queryLyricsWikia(std::move(desc)));
connect(m_model, &QueryResultsModel::resultsAvailable, this, &DbQueryWidget::showResults);
connect(m_model, &QueryResultsModel::coverAvailable, this, &DbQueryWidget::showCoverFromIndex);
}
@ -197,7 +229,8 @@ void DbQueryWidget::showResults()
void DbQueryWidget::setStatus(bool aborted)
{
m_ui->abortPushButton->setVisible(!aborted);
m_ui->startPushButton->setVisible(aborted);
m_ui->searchMusicBrainzPushButton->setVisible(aborted);
m_ui->searchLyricsWikiaPushButton->setVisible(aborted);
m_ui->applyPushButton->setVisible(aborted);
}
@ -271,7 +304,7 @@ void DbQueryWidget::showResultsContextMenu()
if(!selection.isEmpty()) {
QMenu contextMenu;
if(m_ui->applyPushButton->isEnabled()) {
contextMenu.addAction(m_ui->applyPushButton->icon(), m_ui->applyPushButton->text(), this, SLOT(applyResults()));
contextMenu.addAction(m_ui->applyPushButton->icon(), tr("Use selected row"), this, SLOT(applyResults()));
}
if(m_model && m_model->areResultsAvailable()) {
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("view-preview")), tr("Show cover"), this, SLOT(fetchAndShowCoverForSelection()));
@ -353,7 +386,7 @@ bool DbQueryWidget::eventFilter(QObject *obj, QEvent *event)
case QEvent::KeyRelease:
switch(static_cast<QKeyEvent *>(event)->key()) {
case Qt::Key_Return:
startSearch();
searchMusicBrainz();
break;
default:
;

View File

@ -34,7 +34,8 @@ public:
void insertSearchTermsFromTagEdit(TagEdit *tagEdit);
public slots:
void startSearch();
void searchMusicBrainz();
void searchLyricsWikia();
void abortSearch();
void applyResults();
void insertSearchTermsFromActiveTagEdit();

View File

@ -7,11 +7,11 @@
<x>0</x>
<y>0</y>
<width>731</width>
<height>603</height>
<height>619</height>
</rect>
</property>
<property name="windowTitle">
<string>MusicBrainz search</string>
<string>MusicBrainz/LyricsWikia search</string>
</property>
<layout class="QVBoxLayout" name="dialogLayout">
<property name="spacing">
@ -31,6 +31,12 @@
</property>
<item>
<widget class="QWidget" name="mainWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>1</number>
@ -142,12 +148,6 @@
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeView" name="resultsTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
@ -237,29 +237,22 @@
<layout class="QHBoxLayout" name="bottomLayout">
<item>
<widget class="NotificationLabel" name="notificationLabel" native="true">
<property name="maximumSize">
<size>
<width>325</width>
<height>16777215</height>
</size>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>433</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="menuPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>23</width>
@ -276,15 +269,46 @@
</item>
<item>
<widget class="QPushButton" name="abortPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Abort</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="startPushButton">
<widget class="QPushButton" name="searchMusicBrainzPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Search</string>
<string>Search
MusicBrainz</string>
</property>
<property name="icon">
<iconset theme="edit-find">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="searchLyricsWikiaPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Search
LyricWikia</string>
</property>
<property name="icon">
<iconset theme="edit-find">
@ -297,11 +321,18 @@
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Inserts the selected result into the current tag (doesn't save anything)</string>
</property>
<property name="text">
<string>Apply results</string>
<string>Use selected
row</string>
</property>
</widget>
</item>

View File

@ -110,7 +110,7 @@ MainWindow::MainWindow(QWidget *parent) :
// dbquery dock widget
if(Settings::dbQueryWidgetShown()) {
showDbQueryWidget();
toggleDbQueryWidget();
} else {
// ensure the dock widget is invisible
m_ui->dbQueryDockWidget->setVisible(false);
@ -122,7 +122,7 @@ MainWindow::MainWindow(QWidget *parent) :
// connect signals and slots, install event filter
// menu: application
connect(m_ui->actionSettings, &QAction::triggered, this, &MainWindow::showSettingsDlg);
connect(m_ui->actionOpen_MusicBrainz_search, &QAction::triggered, this, &MainWindow::showDbQueryWidget);
connect(m_ui->actionOpen_MusicBrainz_search, &QAction::triggered, this, &MainWindow::toggleDbQueryWidget);
connect(m_ui->lockLayout, &QAction::triggered, this, &MainWindow::toggleLayoutLocked);
connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close);
// menu: file
@ -337,14 +337,14 @@ void MainWindow::spawnExternalPlayer()
}
/*!
* \brief Shows the database query widget.
* \brief Toggles visibility of the database query widget.
*/
void MainWindow::showDbQueryWidget()
void MainWindow::toggleDbQueryWidget()
{
if(!m_dbQueryWidget) {
m_ui->dbQueryDockWidget->setWidget(m_dbQueryWidget = new DbQueryWidget(m_ui->tagEditorWidget, this));
}
m_ui->dbQueryDockWidget->setVisible(true);
m_ui->dbQueryDockWidget->setVisible(m_ui->dbQueryDockWidget->isHidden());
}
/*!

View File

@ -77,7 +77,7 @@ private slots:
void showAboutDlg();
void showRenameFilesDlg();
void spawnExternalPlayer();
void showDbQueryWidget();
void toggleDbQueryWidget();
private:
QMutex &fileOperationMutex();

View File

@ -102,12 +102,12 @@
<set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
</property>
<property name="windowTitle">
<string>F&amp;ile selection</string>
<string>File sele&amp;ction</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<widget class="QWidget" name="fileSelectionDockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
@ -152,12 +152,12 @@
<bool>false</bool>
</property>
<property name="windowTitle">
<string>&amp;MusicBrains search (beta)</string>
<string>&amp;MusicBrains/LyricsWikia search</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2"/>
<widget class="QWidget" name="dbQueryDockWidgetContents"/>
</widget>
<action name="actionSave">
<property name="enabled">
@ -333,7 +333,7 @@
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Open MusicBrainz search</string>
<string>&amp;Toggle MusicBrainz/LyricsWikia search</string>
</property>
<property name="shortcut">
<string>F10</string>
@ -356,10 +356,11 @@
</action>
<action name="lockLayout">
<property name="icon">
<iconset theme="lock"/>
<iconset theme="lock">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Lock layout</string>
<string>&amp;Lock layout</string>
</property>
</action>
</widget>

View File

@ -156,30 +156,36 @@ void NotificationLabel::drawProgressIndicator(QPainter &painter, QRect rect, con
QSize NotificationLabel::sizeHint() const
{
return minimumSizeHint();
}
QSize NotificationLabel::minimumSizeHint() const
{
QFontMetrics fm(font());
const QFontMetrics fm(fontMetrics());
QSize size = fm.size(0, m_text);
if(size.height() < m_minIconSize) {
size.setHeight(m_minIconSize);
}
int iconSize = size.height() > m_maxIconSize ? m_maxIconSize : size.height();
const int iconSize = size.height() > m_maxIconSize ? m_maxIconSize : size.height();
size.setWidth(iconSize + 5 + size.width());
return size;
}
QSize NotificationLabel::minimumSizeHint() const
{
return QSize(m_minIconSize, m_minIconSize);
}
void NotificationLabel::setText(const QString &text)
{
m_text = text;
updateGeometry();
update(textRect());
if(toolTip().isEmpty()) {
setToolTip(text);
}
}
void NotificationLabel::clearText()
{
if(toolTip() == m_text) {
toolTip().clear();
}
m_text.clear();
updateGeometry();
update(textRect());
@ -187,17 +193,21 @@ void NotificationLabel::clearText()
void NotificationLabel::appendLine(const QString &line)
{
const bool updateTooltip = toolTip().isEmpty() || toolTip() == m_text;
if(m_text.isEmpty()) {
m_text = line;
} else {
if(!m_text.startsWith("")) {
m_text.insert(0, "");
if(!m_text.startsWith(QStringLiteral(""))) {
m_text.insert(0, QStringLiteral(""));
}
m_text.append("\n");
m_text.append(QStringLiteral("\n"));
m_text.append(line);
}
updateGeometry();
update(textRect());
if(updateTooltip) {
setToolTip(m_text);
}
}
void NotificationLabel::setNotificationSubject(NotificationSubject value)

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>634</width>
<width>702</width>
<height>203</height>
</rect>
</property>
@ -34,7 +34,14 @@
</widget>
</item>
<item>
<widget class="NotificationLabel" name="parsingNotificationWidget" native="true"/>
<widget class="NotificationLabel" name="parsingNotificationWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="tagSplitter">
@ -195,7 +202,14 @@ the file reverting all unsaved changings.</string>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="NotificationLabel" name="makingNotificationWidget" native="true"/>
<widget class="NotificationLabel" name="makingNotificationWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="abortButton">

View File

@ -649,34 +649,34 @@
<name>QtGui::DbQueryWidget</name>
<message>
<location filename="../gui/dbquerywidget.ui" line="14"/>
<source>MusicBrainz search</source>
<source>MusicBrainz/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="53"/>
<location filename="../gui/dbquerywidget.ui" line="59"/>
<source>Search &amp;criteria</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="77"/>
<location filename="../gui/dbquerywidget.ui" line="83"/>
<source>Song</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="95"/>
<location filename="../gui/dbquerywidget.ui" line="102"/>
<location filename="../gui/dbquerywidget.ui" line="118"/>
<location filename="../gui/dbquerywidget.ui" line="132"/>
<location filename="../gui/dbquerywidget.ui" line="101"/>
<location filename="../gui/dbquerywidget.ui" line="108"/>
<location filename="../gui/dbquerywidget.ui" line="124"/>
<location filename="../gui/dbquerywidget.ui" line="138"/>
<source>?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="111"/>
<location filename="../gui/dbquerywidget.ui" line="117"/>
<source>Album</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="125"/>
<location filename="../gui/dbquerywidget.ui" line="131"/>
<source>Artist</source>
<translation type="unfinished"></translation>
</message>
@ -691,28 +691,36 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="280"/>
<location filename="../gui/dbquerywidget.ui" line="279"/>
<source>Abort</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="287"/>
<source>Search</source>
<location filename="../gui/dbquerywidget.ui" line="292"/>
<source>Search
MusicBrainz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="301"/>
<location filename="../gui/dbquerywidget.ui" line="310"/>
<source>Search
LyricWikia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="331"/>
<source>Inserts the selected result into the current tag (doesn&apos;t save anything)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="304"/>
<source>Apply results</source>
<location filename="../gui/dbquerywidget.ui" line="334"/>
<source>Use selected
row</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="48"/>
<source>Search hasn&apos;t been started.</source>
<source>Search hasn&apos;t been started</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -726,27 +734,29 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="124"/>
<location filename="../gui/dbquerywidget.cpp" line="125"/>
<location filename="../gui/dbquerywidget.cpp" line="156"/>
<source>Insufficient search criteria supplied</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="134"/>
<location filename="../gui/dbquerywidget.cpp" line="135"/>
<location filename="../gui/dbquerywidget.cpp" line="166"/>
<source>Retrieving meta data ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="164"/>
<location filename="../gui/dbquerywidget.cpp" line="196"/>
<source>Aborted</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="176"/>
<location filename="../gui/dbquerywidget.cpp" line="208"/>
<source>No results available</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="../gui/dbquerywidget.cpp" line="178"/>
<location filename="../gui/dbquerywidget.cpp" line="210"/>
<source>%1 result(s) available</source>
<translation type="unfinished">
<numerusform></numerusform>
@ -754,22 +764,27 @@
</translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="240"/>
<location filename="../gui/dbquerywidget.cpp" line="273"/>
<source>Retrieving cover art to be applied ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="277"/>
<location filename="../gui/dbquerywidget.cpp" line="307"/>
<source>Use selected row</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="310"/>
<source>Show cover</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="306"/>
<location filename="../gui/dbquerywidget.cpp" line="339"/>
<source>Retrieving cover art ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="320"/>
<location filename="../gui/dbquerywidget.cpp" line="353"/>
<source>Cover - %1</source>
<translation type="unfinished"></translation>
</message>
@ -953,7 +968,7 @@ Remarks
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="137"/>
<location filename="../gui/settingsdialog.cpp" line="150"/>
<source>To avoid unnecessary copying this directory should be on the same partition as the files you want to edit.</source>
<translation type="unfinished"></translation>
</message>
@ -1550,12 +1565,12 @@ another position would prevent rewriting the entire file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="499"/>
<location filename="../gui/settingsdialog.cpp" line="512"/>
<source>Minimum padding must be less or equal than maximum padding.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="564"/>
<location filename="../gui/settingsdialog.cpp" line="577"/>
<source>These options might be ignored if not supported by either the format or the implementation.</source>
<translation type="unfinished"></translation>
</message>
@ -1563,22 +1578,22 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::HttpResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="264"/>
<location filename="../dbquery/dbquery.cpp" line="255"/>
<source>&lt;p&gt;Do you want to redirect form &lt;i&gt;%1&lt;/i&gt; to &lt;i&gt;%2&lt;/i&gt;?&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="266"/>
<location filename="../dbquery/dbquery.cpp" line="257"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="277"/>
<location filename="../dbquery/dbquery.cpp" line="268"/>
<source>Redirection to: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="314"/>
<location filename="../dbquery/dbquery.cpp" line="312"/>
<source>Aborted by user.</source>
<translation type="unfinished"></translation>
</message>
@ -1731,112 +1746,112 @@ another position would prevent rewriting the entire file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="104"/>
<source>F&amp;ile selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="154"/>
<source>&amp;MusicBrains search (beta)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="170"/>
<location filename="../gui/mainwindow.ui" line="171"/>
<source>Save &amp;entered tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="185"/>
<location filename="../gui/mainwindow.ui" line="186"/>
<source>&amp;Delete all tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="188"/>
<location filename="../gui/mainwindow.ui" line="189"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="200"/>
<location filename="../gui/mainwindow.ui" line="201"/>
<source>&amp;Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="212"/>
<location filename="../gui/mainwindow.ui" line="213"/>
<source>&amp;Select next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="224"/>
<location filename="../gui/mainwindow.ui" line="225"/>
<source>&amp;Rename files using tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="236"/>
<location filename="../gui/mainwindow.ui" line="237"/>
<source>&amp;Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="251"/>
<location filename="../gui/mainwindow.ui" line="252"/>
<source>&amp;Save file information as HTML document</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="254"/>
<location filename="../gui/mainwindow.ui" line="255"/>
<source>Ctrl+H</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="263"/>
<location filename="../gui/mainwindow.ui" line="264"/>
<source>Select &amp;next file and save current</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="266"/>
<location filename="../gui/mainwindow.ui" line="267"/>
<source>F3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="275"/>
<location filename="../gui/mainwindow.ui" line="276"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="284"/>
<location filename="../gui/mainwindow.ui" line="285"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="293"/>
<location filename="../gui/mainwindow.ui" line="294"/>
<source>&amp;Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="323"/>
<location filename="../gui/mainwindow.ui" line="324"/>
<source>&amp;Play (external player)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="326"/>
<location filename="../gui/mainwindow.ui" line="327"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="335"/>
<source>&amp;Open MusicBrainz search</source>
<location filename="../gui/mainwindow.ui" line="363"/>
<source>&amp;Lock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="338"/>
<location filename="../gui/mainwindow.ui" line="339"/>
<source>F10</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="349"/>
<source>Save (entered tags) as ...</source>
<location filename="../gui/mainwindow.ui" line="336"/>
<source>&amp;Toggle MusicBrainz/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="352"/>
<location filename="../gui/mainwindow.ui" line="351"/>
<source>Save (entered tags) &amp;as ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="202"/>
<source>Lock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="354"/>
<source>Ctrl+Shift+S</source>
<translation type="unfinished"></translation>
</message>
@ -1846,47 +1861,57 @@ another position would prevent rewriting the entire file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="173"/>
<location filename="../gui/mainwindow.ui" line="174"/>
<source>Ctrl+S</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="239"/>
<location filename="../gui/mainwindow.ui" line="240"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="296"/>
<location filename="../gui/mainwindow.ui" line="297"/>
<source>F8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="203"/>
<location filename="../gui/mainwindow.ui" line="204"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="142"/>
<location filename="../gui/mainwindow.ui" line="105"/>
<source>File sele&amp;ction</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="143"/>
<source>Select next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="215"/>
<location filename="../gui/mainwindow.ui" line="155"/>
<source>&amp;MusicBrains/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="216"/>
<source>F6</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="227"/>
<location filename="../gui/mainwindow.ui" line="228"/>
<source>F2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="308"/>
<location filename="../gui/mainwindow.ui" line="309"/>
<source>&amp;Reload (reverts all changes!)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="311"/>
<location filename="../gui/mainwindow.ui" line="312"/>
<source>F5</source>
<translation type="unfinished"></translation>
</message>
@ -1897,58 +1922,63 @@ another position would prevent rewriting the entire file</source>
<translation></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="297"/>
<location filename="../gui/mainwindow.cpp" line="335"/>
<source>No file opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="318"/>
<location filename="../gui/mainwindow.cpp" line="356"/>
<source>A tag editing utility supporting ID3, MP4 (iTunes style), Vorbis and Matroska tags.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="435"/>
<location filename="../gui/mainwindow.cpp" line="473"/>
<source>Unable to show the next file because it can&apos;t be found anymore.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="445"/>
<location filename="../gui/mainwindow.cpp" line="483"/>
<source>Open file - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="456"/>
<location filename="../gui/mainwindow.cpp" line="494"/>
<source>Save changes as - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="478"/>
<location filename="../gui/mainwindow.cpp" line="516"/>
<source>Save file information - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="497"/>
<location filename="../gui/mainwindow.cpp" line="535"/>
<source>No file is opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="500"/>
<location filename="../gui/mainwindow.cpp" line="538"/>
<source>Unable to save file information because the current process hasn&apos;t been finished yet.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="487"/>
<location filename="../gui/mainwindow.cpp" line="525"/>
<source>Unable to write to file.
%1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="490"/>
<location filename="../gui/mainwindow.cpp" line="197"/>
<source>Unlock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="528"/>
<source>Unable to open file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="494"/>
<location filename="../gui/mainwindow.cpp" line="532"/>
<source>No file information available.</source>
<translation type="unfinished"></translation>
</message>
@ -1956,12 +1986,12 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::MusicBrainzResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="370"/>
<location filename="../dbquery/musicbrainz.cpp" line="44"/>
<source>Unable to fetch cover: Album ID is unknown.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="389"/>
<location filename="../dbquery/musicbrainz.cpp" line="63"/>
<source>Cover reply is invalid (internal error).</source>
<translation type="unfinished"></translation>
</message>
@ -2285,42 +2315,42 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::QueryResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="154"/>
<location filename="../dbquery/dbquery.cpp" line="148"/>
<source>Song title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="156"/>
<location filename="../dbquery/dbquery.cpp" line="150"/>
<source>Album</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="158"/>
<location filename="../dbquery/dbquery.cpp" line="152"/>
<source>Artist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="160"/>
<location filename="../dbquery/dbquery.cpp" line="154"/>
<source>Year</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="162"/>
<location filename="../dbquery/dbquery.cpp" line="156"/>
<source>Track</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="164"/>
<location filename="../dbquery/dbquery.cpp" line="158"/>
<source>Total tracks</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="166"/>
<location filename="../dbquery/dbquery.cpp" line="160"/>
<source>Genre</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="213"/>
<location filename="../dbquery/dbquery.cpp" line="207"/>
<source>Fetching the cover is not implemented for the selected provider.</source>
<translation type="unfinished"></translation>
</message>
@ -2571,17 +2601,17 @@ Error in line %1: %3</source>
<translation></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="585"/>
<location filename="../gui/settingsdialog.cpp" line="598"/>
<source>Tag processing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="593"/>
<location filename="../gui/settingsdialog.cpp" line="606"/>
<source>Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="601"/>
<location filename="../gui/settingsdialog.cpp" line="614"/>
<source>File browser</source>
<translation type="unfinished"></translation>
</message>
@ -2613,12 +2643,12 @@ Error in line %1: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="67"/>
<location filename="../gui/tageditorwidget.ui" line="74"/>
<source>Document title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="95"/>
<location filename="../gui/tageditorwidget.ui" line="102"/>
<source>Let you choose whether the values of the
previously opened file should be cleared when
opening the next file.
@ -2627,12 +2657,12 @@ tagging multiple files of the same album.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="102"/>
<location filename="../gui/tageditorwidget.ui" line="109"/>
<source>Keep previous values</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="115"/>
<location filename="../gui/tageditorwidget.ui" line="122"/>
<source>Let you enable or disable the automatic
creation or removal of tags (according to
the settings) when loading a file.
@ -2641,99 +2671,99 @@ You can also create or remove tags manually.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="122"/>
<location filename="../gui/tageditorwidget.ui" line="129"/>
<source>Tag management</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="135"/>
<location filename="../gui/tageditorwidget.ui" line="142"/>
<source>Restores the original values read from
the file reverting all unsaved changings.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="139"/>
<location filename="../gui/tageditorwidget.ui" line="146"/>
<source>Restore</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="162"/>
<location filename="../gui/tageditorwidget.ui" line="169"/>
<source>Clears all values.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="165"/>
<location filename="../gui/tageditorwidget.ui" line="172"/>
<source>Clear</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="209"/>
<location filename="../gui/tageditorwidget.ui" line="223"/>
<source>Aborts the saving process. The tageditor will try to restore the original file from the backup.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="212"/>
<location filename="../gui/tageditorwidget.ui" line="226"/>
<location filename="../gui/tageditorwidget.cpp" line="1193"/>
<source>Abort</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="243"/>
<location filename="../gui/tageditorwidget.ui" line="257"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="246"/>
<location filename="../gui/tageditorwidget.ui" line="260"/>
<source>all entered values</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="253"/>
<location filename="../gui/tageditorwidget.ui" line="267"/>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="256"/>
<location filename="../gui/tageditorwidget.ui" line="270"/>
<source>all tags from the file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="263"/>
<location filename="../gui/tageditorwidget.ui" line="277"/>
<source>Open next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="266"/>
<location filename="../gui/tageditorwidget.ui" line="280"/>
<source>and save current before</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="273"/>
<location filename="../gui/tageditorwidget.ui" line="287"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="276"/>
<location filename="../gui/tageditorwidget.ui" line="290"/>
<source>the file and discard changings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="289"/>
<location filename="../gui/tageditorwidget.ui" line="303"/>
<source>No, disable this feature</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="297"/>
<location filename="../gui/tageditorwidget.ui" line="311"/>
<source>Yes, but only if both files are in the same directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="305"/>
<location filename="../gui/tageditorwidget.ui" line="319"/>
<source>Yes, regardless where the files are stored</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="317"/>
<location filename="../gui/tageditorwidget.ui" line="331"/>
<source>Manage tags automatically when loading file</source>
<translation type="unfinished"></translation>
</message>

View File

@ -649,7 +649,7 @@
<name>QtGui::DbQueryWidget</name>
<message>
<location filename="../gui/dbquerywidget.cpp" line="48"/>
<source>Search hasn&apos;t been started.</source>
<source>Search hasn&apos;t been started</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -663,27 +663,29 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="124"/>
<location filename="../gui/dbquerywidget.cpp" line="125"/>
<location filename="../gui/dbquerywidget.cpp" line="156"/>
<source>Insufficient search criteria supplied</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="134"/>
<location filename="../gui/dbquerywidget.cpp" line="135"/>
<location filename="../gui/dbquerywidget.cpp" line="166"/>
<source>Retrieving meta data ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="164"/>
<location filename="../gui/dbquerywidget.cpp" line="196"/>
<source>Aborted</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="176"/>
<location filename="../gui/dbquerywidget.cpp" line="208"/>
<source>No results available</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="../gui/dbquerywidget.cpp" line="178"/>
<location filename="../gui/dbquerywidget.cpp" line="210"/>
<source>%1 result(s) available</source>
<translation type="unfinished">
<numerusform>%1 result available</numerusform>
@ -691,55 +693,60 @@
</translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="240"/>
<location filename="../gui/dbquerywidget.cpp" line="273"/>
<source>Retrieving cover art to be applied ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="277"/>
<location filename="../gui/dbquerywidget.cpp" line="307"/>
<source>Use selected row</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="310"/>
<source>Show cover</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="306"/>
<location filename="../gui/dbquerywidget.cpp" line="339"/>
<source>Retrieving cover art ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.cpp" line="320"/>
<location filename="../gui/dbquerywidget.cpp" line="353"/>
<source>Cover - %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="14"/>
<source>MusicBrainz search</source>
<source>MusicBrainz/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="53"/>
<location filename="../gui/dbquerywidget.ui" line="59"/>
<source>Search &amp;criteria</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="77"/>
<location filename="../gui/dbquerywidget.ui" line="83"/>
<source>Song</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="95"/>
<location filename="../gui/dbquerywidget.ui" line="102"/>
<location filename="../gui/dbquerywidget.ui" line="118"/>
<location filename="../gui/dbquerywidget.ui" line="132"/>
<location filename="../gui/dbquerywidget.ui" line="101"/>
<location filename="../gui/dbquerywidget.ui" line="108"/>
<location filename="../gui/dbquerywidget.ui" line="124"/>
<location filename="../gui/dbquerywidget.ui" line="138"/>
<source>?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="111"/>
<location filename="../gui/dbquerywidget.ui" line="117"/>
<source>Album</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="125"/>
<location filename="../gui/dbquerywidget.ui" line="131"/>
<source>Artist</source>
<translation type="unfinished"></translation>
</message>
@ -754,23 +761,31 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="280"/>
<location filename="../gui/dbquerywidget.ui" line="279"/>
<source>Abort</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="287"/>
<source>Search</source>
<location filename="../gui/dbquerywidget.ui" line="292"/>
<source>Search
MusicBrainz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="301"/>
<location filename="../gui/dbquerywidget.ui" line="310"/>
<source>Search
LyricWikia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="331"/>
<source>Inserts the selected result into the current tag (doesn&apos;t save anything)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dbquerywidget.ui" line="304"/>
<source>Apply results</source>
<location filename="../gui/dbquerywidget.ui" line="334"/>
<source>Use selected
row</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -953,7 +968,7 @@ Remarks
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="137"/>
<location filename="../gui/settingsdialog.cpp" line="150"/>
<source>To avoid unnecessary copying this directory should be on the same partition as the files you want to edit.</source>
<translation type="unfinished"></translation>
</message>
@ -1550,12 +1565,12 @@ another position would prevent rewriting the entire file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="499"/>
<location filename="../gui/settingsdialog.cpp" line="512"/>
<source>Minimum padding must be less or equal than maximum padding.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="564"/>
<location filename="../gui/settingsdialog.cpp" line="577"/>
<source>These options might be ignored if not supported by either the format or the implementation.</source>
<translation type="unfinished"></translation>
</message>
@ -1563,22 +1578,22 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::HttpResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="264"/>
<location filename="../dbquery/dbquery.cpp" line="255"/>
<source>&lt;p&gt;Do you want to redirect form &lt;i&gt;%1&lt;/i&gt; to &lt;i&gt;%2&lt;/i&gt;?&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="266"/>
<location filename="../dbquery/dbquery.cpp" line="257"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="277"/>
<location filename="../dbquery/dbquery.cpp" line="268"/>
<source>Redirection to: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="314"/>
<location filename="../dbquery/dbquery.cpp" line="312"/>
<source>Aborted by user.</source>
<translation type="unfinished"></translation>
</message>
@ -1742,213 +1757,228 @@ another position would prevent rewriting the entire file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="142"/>
<location filename="../gui/mainwindow.ui" line="105"/>
<source>File sele&amp;ction</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="143"/>
<source>Select next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="104"/>
<source>F&amp;ile selection</source>
<location filename="../gui/mainwindow.ui" line="155"/>
<source>&amp;MusicBrains/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="154"/>
<source>&amp;MusicBrains search (beta)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="170"/>
<location filename="../gui/mainwindow.ui" line="171"/>
<source>Save &amp;entered tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="173"/>
<location filename="../gui/mainwindow.ui" line="174"/>
<source>Ctrl+S</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="185"/>
<location filename="../gui/mainwindow.ui" line="186"/>
<source>&amp;Delete all tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="188"/>
<location filename="../gui/mainwindow.ui" line="189"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="200"/>
<location filename="../gui/mainwindow.ui" line="201"/>
<source>&amp;Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="203"/>
<location filename="../gui/mainwindow.ui" line="204"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="212"/>
<location filename="../gui/mainwindow.ui" line="213"/>
<source>&amp;Select next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="215"/>
<location filename="../gui/mainwindow.ui" line="216"/>
<source>F6</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="224"/>
<location filename="../gui/mainwindow.ui" line="225"/>
<source>&amp;Rename files using tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="227"/>
<location filename="../gui/mainwindow.ui" line="228"/>
<source>F2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="236"/>
<location filename="../gui/mainwindow.ui" line="237"/>
<source>&amp;Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="239"/>
<location filename="../gui/mainwindow.ui" line="240"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="251"/>
<location filename="../gui/mainwindow.ui" line="252"/>
<source>&amp;Save file information as HTML document</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="254"/>
<location filename="../gui/mainwindow.ui" line="255"/>
<source>Ctrl+H</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="263"/>
<location filename="../gui/mainwindow.ui" line="264"/>
<source>Select &amp;next file and save current</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="266"/>
<location filename="../gui/mainwindow.ui" line="267"/>
<source>F3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="275"/>
<location filename="../gui/mainwindow.ui" line="276"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="284"/>
<location filename="../gui/mainwindow.ui" line="285"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="293"/>
<location filename="../gui/mainwindow.ui" line="294"/>
<source>&amp;Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="296"/>
<location filename="../gui/mainwindow.ui" line="297"/>
<source>F8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="308"/>
<location filename="../gui/mainwindow.ui" line="309"/>
<source>&amp;Reload (reverts all changes!)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="311"/>
<location filename="../gui/mainwindow.ui" line="312"/>
<source>F5</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="323"/>
<location filename="../gui/mainwindow.ui" line="324"/>
<source>&amp;Play (external player)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="326"/>
<location filename="../gui/mainwindow.ui" line="327"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="335"/>
<source>&amp;Open MusicBrainz search</source>
<location filename="../gui/mainwindow.ui" line="363"/>
<source>&amp;Lock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="338"/>
<location filename="../gui/mainwindow.ui" line="339"/>
<source>F10</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="349"/>
<source>Save (entered tags) as ...</source>
<location filename="../gui/mainwindow.ui" line="336"/>
<source>&amp;Toggle MusicBrainz/LyricsWikia search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="352"/>
<location filename="../gui/mainwindow.ui" line="351"/>
<source>Save (entered tags) &amp;as ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="202"/>
<source>Lock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.ui" line="354"/>
<source>Ctrl+Shift+S</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="297"/>
<location filename="../gui/mainwindow.cpp" line="197"/>
<source>Unlock layout</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="335"/>
<source>No file opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="318"/>
<location filename="../gui/mainwindow.cpp" line="356"/>
<source>A tag editing utility supporting ID3, MP4 (iTunes style), Vorbis and Matroska tags.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="435"/>
<location filename="../gui/mainwindow.cpp" line="473"/>
<source>Unable to show the next file because it can&apos;t be found anymore.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="445"/>
<location filename="../gui/mainwindow.cpp" line="483"/>
<source>Open file - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="456"/>
<location filename="../gui/mainwindow.cpp" line="494"/>
<source>Save changes as - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="478"/>
<location filename="../gui/mainwindow.cpp" line="516"/>
<source>Save file information - </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="487"/>
<location filename="../gui/mainwindow.cpp" line="525"/>
<source>Unable to write to file.
%1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="490"/>
<location filename="../gui/mainwindow.cpp" line="528"/>
<source>Unable to open file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="494"/>
<location filename="../gui/mainwindow.cpp" line="532"/>
<source>No file information available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="497"/>
<location filename="../gui/mainwindow.cpp" line="535"/>
<source>No file is opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/mainwindow.cpp" line="500"/>
<location filename="../gui/mainwindow.cpp" line="538"/>
<source>Unable to save file information because the current process hasn&apos;t been finished yet.</source>
<translation type="unfinished"></translation>
</message>
@ -1956,12 +1986,12 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::MusicBrainzResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="370"/>
<location filename="../dbquery/musicbrainz.cpp" line="44"/>
<source>Unable to fetch cover: Album ID is unknown.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="389"/>
<location filename="../dbquery/musicbrainz.cpp" line="63"/>
<source>Cover reply is invalid (internal error).</source>
<translation type="unfinished"></translation>
</message>
@ -2285,42 +2315,42 @@ another position would prevent rewriting the entire file</source>
<context>
<name>QtGui::QueryResultsModel</name>
<message>
<location filename="../dbquery/dbquery.cpp" line="154"/>
<location filename="../dbquery/dbquery.cpp" line="148"/>
<source>Song title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="156"/>
<location filename="../dbquery/dbquery.cpp" line="150"/>
<source>Album</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="158"/>
<location filename="../dbquery/dbquery.cpp" line="152"/>
<source>Artist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="160"/>
<location filename="../dbquery/dbquery.cpp" line="154"/>
<source>Year</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="162"/>
<location filename="../dbquery/dbquery.cpp" line="156"/>
<source>Track</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="164"/>
<location filename="../dbquery/dbquery.cpp" line="158"/>
<source>Total tracks</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="166"/>
<location filename="../dbquery/dbquery.cpp" line="160"/>
<source>Genre</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../dbquery/dbquery.cpp" line="213"/>
<location filename="../dbquery/dbquery.cpp" line="207"/>
<source>Fetching the cover is not implemented for the selected provider.</source>
<translation type="unfinished"></translation>
</message>
@ -2571,17 +2601,17 @@ Error in line %1: %3</source>
<translation></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="585"/>
<location filename="../gui/settingsdialog.cpp" line="598"/>
<source>Tag processing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="593"/>
<location filename="../gui/settingsdialog.cpp" line="606"/>
<source>Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="601"/>
<location filename="../gui/settingsdialog.cpp" line="614"/>
<source>File browser</source>
<translation type="unfinished"></translation>
</message>
@ -2914,12 +2944,12 @@ Error in line %1: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="67"/>
<location filename="../gui/tageditorwidget.ui" line="74"/>
<source>Document title</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="95"/>
<location filename="../gui/tageditorwidget.ui" line="102"/>
<source>Let you choose whether the values of the
previously opened file should be cleared when
opening the next file.
@ -2928,12 +2958,12 @@ tagging multiple files of the same album.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="102"/>
<location filename="../gui/tageditorwidget.ui" line="109"/>
<source>Keep previous values</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="115"/>
<location filename="../gui/tageditorwidget.ui" line="122"/>
<source>Let you enable or disable the automatic
creation or removal of tags (according to
the settings) when loading a file.
@ -2942,99 +2972,99 @@ You can also create or remove tags manually.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="122"/>
<location filename="../gui/tageditorwidget.ui" line="129"/>
<source>Tag management</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="135"/>
<location filename="../gui/tageditorwidget.ui" line="142"/>
<source>Restores the original values read from
the file reverting all unsaved changings.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="139"/>
<location filename="../gui/tageditorwidget.ui" line="146"/>
<source>Restore</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="162"/>
<location filename="../gui/tageditorwidget.ui" line="169"/>
<source>Clears all values.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="165"/>
<location filename="../gui/tageditorwidget.ui" line="172"/>
<source>Clear</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="209"/>
<location filename="../gui/tageditorwidget.ui" line="223"/>
<source>Aborts the saving process. The tageditor will try to restore the original file from the backup.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="212"/>
<location filename="../gui/tageditorwidget.ui" line="226"/>
<location filename="../gui/tageditorwidget.cpp" line="1193"/>
<source>Abort</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="243"/>
<location filename="../gui/tageditorwidget.ui" line="257"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="246"/>
<location filename="../gui/tageditorwidget.ui" line="260"/>
<source>all entered values</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="253"/>
<location filename="../gui/tageditorwidget.ui" line="267"/>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="256"/>
<location filename="../gui/tageditorwidget.ui" line="270"/>
<source>all tags from the file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="263"/>
<location filename="../gui/tageditorwidget.ui" line="277"/>
<source>Open next file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="266"/>
<location filename="../gui/tageditorwidget.ui" line="280"/>
<source>and save current before</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="273"/>
<location filename="../gui/tageditorwidget.ui" line="287"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="276"/>
<location filename="../gui/tageditorwidget.ui" line="290"/>
<source>the file and discard changings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="289"/>
<location filename="../gui/tageditorwidget.ui" line="303"/>
<source>No, disable this feature</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="297"/>
<location filename="../gui/tageditorwidget.ui" line="311"/>
<source>Yes, but only if both files are in the same directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="305"/>
<location filename="../gui/tageditorwidget.ui" line="319"/>
<source>Yes, regardless where the files are stored</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tageditorwidget.ui" line="317"/>
<location filename="../gui/tageditorwidget.ui" line="331"/>
<source>Manage tags automatically when loading file</source>
<translation type="unfinished"></translation>
</message>