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.toLower();
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));

View File

@ -145,7 +145,7 @@ QString AlbumCoverLoader::CoverFilePath(const Song::Source source, const QString
QString filename;
if (source == Song::Source_Collection && cover_album_dir_ && cover_filename_ == CollectionSettingsPage::SaveCover_Pattern && !cover_pattern_.isEmpty()) {
filename = CreateCoverFilename(artist, album) + ".jpg";
filename.remove(OrganiseFormat::kValidFatCharacters);
filename.remove(OrganiseFormat::kInvalidFatCharacters);
if (cover_lowercase_) filename = filename.toLower();
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.replace(' ', '-');
filename.replace("--", "-");
filename.remove(OrganiseFormat::kValidFatCharacters);
filename.remove(OrganiseFormat::kInvalidFatCharacters);
return filename;

View File

@ -22,7 +22,6 @@
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QList>
#include <QChar>
#include <QString>
@ -30,6 +29,8 @@
#include <QStringList>
#include <QRegExp>
#include <QUrl>
#include <QFileInfo>
#include <QDir>
#include <QColor>
#include <QPalette>
#include <QValidator>
@ -68,9 +69,9 @@ const QStringList OrganiseFormat::kKnownTags = QStringList() << "title"
<< "grouping"
<< "lyrics";
const QRegExp OrganiseFormat::kInvalidDirCharacters("[/\\\\]");
// From http://en.wikipedia.org/wiki/8.3_filename#Directory_table
const QRegExp OrganiseFormat::kValidFatCharacters("[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]");
const QRegExp OrganiseFormat::kInvalidFatCharacters("[\"*\\:<>?|/.]");
const QRegExp OrganiseFormat::kInvalidFatCharacters("[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]");
const char OrganiseFormat::kInvalidPrefixCharacters[] = ".";
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_) filename.remove(kValidFatCharacters);
if (replace_spaces_) filename.replace(QRegExp("\\s"), "_");
if (remove_non_fat_) filename.remove(kInvalidFatCharacters);
if (remove_non_ascii_) {
int ascii = 128;
if (allow_ascii_ext_) ascii = 255;
QString stripped;
for (int i = 0; i < filename.length(); ++i) {
for (int i = 0 ; i < filename.length() ; ++i) {
const QCharRef c = filename[i];
if (c < ascii) {
stripped.append(c);
@ -132,26 +132,41 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
const QString decomposition = c.decomposition();
if (!decomposition.isEmpty() && decomposition[0] < ascii)
stripped.append(decomposition[0]);
else
stripped.append("_");
}
}
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.
QStringList parts = filename.split("/");
for (int i = 0; i < parts.count(); ++i) {
QString *part = &parts[i];
for (int j = 0; j < kInvalidPrefixCharactersCount; ++j) {
if (part->startsWith(kInvalidPrefixCharacters[j])) {
part->replace(0, 1, '_');
QStringList parts_old = filepath.split("/");
QStringList parts_new;
for (int i = 0 ; i < parts_old.count() ; ++i) {
QString part = parts_old[i];
for (int j = 0 ; j < kInvalidPrefixCharactersCount ; ++j) {
if (part.startsWith(kInvalidPrefixCharacters[j])) {
part.remove(0, 1);
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);
else if (tag == "bitrate")
value = QString::number(song.bitrate());
else if (tag == "samplerate") value = QString::number(song.samplerate());
else if (tag == "bitdepth") value = QString::number(song.bitdepth());
else if (tag == "samplerate")
value = QString::number(song.samplerate());
else if (tag == "bitdepth")
value = QString::number(song.bitdepth());
else if (tag == "extension")
value = QFileInfo(song.url().toLocalFile()).suffix();
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');
// Replace characters that really shouldn't be in paths
value.remove(kInvalidFatCharacters);
value = value.remove(kInvalidDirCharacters);
value = value.trimmed();
return value;

View File

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