Allow all characters except slash and backslash when organising music

Fixes #404
This commit is contained in:
Jonas Kvinge
2020-04-09 18:14:02 +02:00
parent 7b40c33892
commit 8f4056faa6
4 changed files with 40 additions and 22 deletions

View File

@@ -164,7 +164,7 @@ void AlbumCoverChoiceController::SaveCoverToFileManual(const Song &song, const Q
initial_file_name = initial_file_name + "-" + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + ".jpg"; initial_file_name = initial_file_name + "-" + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + ".jpg";
initial_file_name = initial_file_name.toLower(); initial_file_name = initial_file_name.toLower();
initial_file_name.replace(QRegExp("\\s"), "-"); initial_file_name.replace(QRegExp("\\s"), "-");
initial_file_name.remove(OrganiseFormat::kValidFatCharacters); initial_file_name.remove(OrganiseFormat::kInvalidFatCharacters);
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter)); QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter));

View File

@@ -145,7 +145,7 @@ QString AlbumCoverLoader::CoverFilePath(const Song::Source source, const QString
QString filename; QString filename;
if (source == Song::Source_Collection && cover_album_dir_ && cover_filename_ == CollectionSettingsPage::SaveCover_Pattern && !cover_pattern_.isEmpty()) { if (source == Song::Source_Collection && cover_album_dir_ && cover_filename_ == CollectionSettingsPage::SaveCover_Pattern && !cover_pattern_.isEmpty()) {
filename = CreateCoverFilename(artist, album) + ".jpg"; filename = CreateCoverFilename(artist, album) + ".jpg";
filename.remove(OrganiseFormat::kValidFatCharacters); filename.remove(OrganiseFormat::kInvalidFatCharacters);
if (cover_lowercase_) filename = filename.toLower(); if (cover_lowercase_) filename = filename.toLower();
if (cover_replace_spaces_) filename.replace(QRegExp("\\s"), "-"); if (cover_replace_spaces_) filename.replace(QRegExp("\\s"), "-");
} }
@@ -186,7 +186,7 @@ QString AlbumCoverLoader::AlbumCoverFileName(QString artist, QString album) {
filename = Utilities::UnicodeToAscii(filename.toLower()); filename = Utilities::UnicodeToAscii(filename.toLower());
filename.replace(' ', '-'); filename.replace(' ', '-');
filename.replace("--", "-"); filename.replace("--", "-");
filename.remove(OrganiseFormat::kValidFatCharacters); filename.remove(OrganiseFormat::kInvalidFatCharacters);
return filename; return filename;

View File

@@ -22,7 +22,6 @@
#include <QObject> #include <QObject>
#include <QApplication> #include <QApplication>
#include <QFileInfo>
#include <QList> #include <QList>
#include <QChar> #include <QChar>
#include <QString> #include <QString>
@@ -30,6 +29,8 @@
#include <QStringList> #include <QStringList>
#include <QRegExp> #include <QRegExp>
#include <QUrl> #include <QUrl>
#include <QFileInfo>
#include <QDir>
#include <QColor> #include <QColor>
#include <QPalette> #include <QPalette>
#include <QValidator> #include <QValidator>
@@ -68,9 +69,9 @@ const QStringList OrganiseFormat::kKnownTags = QStringList() << "title"
<< "grouping" << "grouping"
<< "lyrics"; << "lyrics";
const QRegExp OrganiseFormat::kInvalidDirCharacters("[/\\\\]");
// From http://en.wikipedia.org/wiki/8.3_filename#Directory_table // From http://en.wikipedia.org/wiki/8.3_filename#Directory_table
const QRegExp OrganiseFormat::kValidFatCharacters("[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]"); const QRegExp OrganiseFormat::kInvalidFatCharacters("[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]");
const QRegExp OrganiseFormat::kInvalidFatCharacters("[\"*\\:<>?|/.]");
const char OrganiseFormat::kInvalidPrefixCharacters[] = "."; const char OrganiseFormat::kInvalidPrefixCharacters[] = ".";
const int OrganiseFormat::kInvalidPrefixCharactersCount = arraysize(OrganiseFormat::kInvalidPrefixCharacters) - 1; const int OrganiseFormat::kInvalidPrefixCharactersCount = arraysize(OrganiseFormat::kInvalidPrefixCharacters) - 1;
@@ -116,14 +117,13 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
} }
if (remove_non_fat_ || (remove_non_ascii_ && !allow_ascii_ext_)) filename = Utilities::UnicodeToAscii(filename); if (remove_non_fat_ || (remove_non_ascii_ && !allow_ascii_ext_)) filename = Utilities::UnicodeToAscii(filename);
if (remove_non_fat_) filename.remove(kValidFatCharacters); if (remove_non_fat_) filename.remove(kInvalidFatCharacters);
if (replace_spaces_) filename.replace(QRegExp("\\s"), "_");
if (remove_non_ascii_) { if (remove_non_ascii_) {
int ascii = 128; int ascii = 128;
if (allow_ascii_ext_) ascii = 255; if (allow_ascii_ext_) ascii = 255;
QString stripped; QString stripped;
for (int i = 0; i < filename.length(); ++i) { for (int i = 0 ; i < filename.length() ; ++i) {
const QCharRef c = filename[i]; const QCharRef c = filename[i];
if (c < ascii) { if (c < ascii) {
stripped.append(c); stripped.append(c);
@@ -132,26 +132,41 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
const QString decomposition = c.decomposition(); const QString decomposition = c.decomposition();
if (!decomposition.isEmpty() && decomposition[0] < ascii) if (!decomposition.isEmpty() && decomposition[0] < ascii)
stripped.append(decomposition[0]); stripped.append(decomposition[0]);
else
stripped.append("_");
} }
} }
filename = stripped; filename = stripped;
} }
// Remove repeated whitespaces in the filename.
filename = filename.simplified();
QFileInfo info(filename);
QString extension = info.suffix();
QString filepath = info.path() + QDir::separator() + info.completeBaseName();
// Fix any parts of the path that start with dots. // Fix any parts of the path that start with dots.
QStringList parts = filename.split("/"); QStringList parts_old = filepath.split("/");
for (int i = 0; i < parts.count(); ++i) { QStringList parts_new;
QString *part = &parts[i]; for (int i = 0 ; i < parts_old.count() ; ++i) {
for (int j = 0; j < kInvalidPrefixCharactersCount; ++j) { QString part = parts_old[i];
if (part->startsWith(kInvalidPrefixCharacters[j])) { for (int j = 0 ; j < kInvalidPrefixCharactersCount ; ++j) {
part->replace(0, 1, '_'); if (part.startsWith(kInvalidPrefixCharacters[j])) {
part.remove(0, 1);
break; break;
} }
} }
part = part.trimmed();
parts_new.append(part);
}
filename = parts_new.join("/");
if (replace_spaces_) filename.replace(QRegExp("\\s"), "_");
if (!extension.isEmpty()) {
filename.append(QString(".%1").arg(extension));
} }
return parts.join("/"); return filename;
} }
@@ -223,8 +238,10 @@ QString OrganiseFormat::TagValue(const QString &tag, const Song &song) const {
value = QString::number(song.length_nanosec() / kNsecPerSec); value = QString::number(song.length_nanosec() / kNsecPerSec);
else if (tag == "bitrate") else if (tag == "bitrate")
value = QString::number(song.bitrate()); value = QString::number(song.bitrate());
else if (tag == "samplerate") value = QString::number(song.samplerate()); else if (tag == "samplerate")
else if (tag == "bitdepth") value = QString::number(song.bitdepth()); value = QString::number(song.samplerate());
else if (tag == "bitdepth")
value = QString::number(song.bitdepth());
else if (tag == "extension") else if (tag == "extension")
value = QFileInfo(song.url().toLocalFile()).suffix(); value = QFileInfo(song.url().toLocalFile()).suffix();
else if (tag == "artistinitial") { else if (tag == "artistinitial") {
@@ -244,7 +261,8 @@ QString OrganiseFormat::TagValue(const QString &tag, const Song &song) const {
if (tag == "track" && value.length() == 1) value.prepend('0'); if (tag == "track" && value.length() == 1) value.prepend('0');
// Replace characters that really shouldn't be in paths // Replace characters that really shouldn't be in paths
value.remove(kInvalidFatCharacters); value = value.remove(kInvalidDirCharacters);
value = value.trimmed();
return value; return value;

View File

@@ -43,7 +43,7 @@ class OrganiseFormat {
static const char *kTagPattern; static const char *kTagPattern;
static const char *kBlockPattern; static const char *kBlockPattern;
static const QStringList kKnownTags; static const QStringList kKnownTags;
static const QRegExp kValidFatCharacters; static const QRegExp kInvalidDirCharacters;
static const QRegExp kInvalidFatCharacters; static const QRegExp kInvalidFatCharacters;
static const char kInvalidPrefixCharacters[]; static const char kInvalidPrefixCharacters[];