Move organise files, add option to strip all non-fat characters
This commit is contained in:
parent
2e1b601508
commit
2a54cb17e7
@ -771,11 +771,10 @@ optional_source(HAVE_LIBPULSE
|
||||
# MusicBrainz, Organise and transcode require GStreamer
|
||||
optional_source(HAVE_GSTREAMER
|
||||
SOURCES
|
||||
core/organise.cpp
|
||||
core/organiseformat.cpp
|
||||
settings/transcodersettingspage.cpp
|
||||
dialogs/organisedialog.cpp
|
||||
dialogs/organiseerrordialog.cpp
|
||||
organise/organise.cpp
|
||||
organise/organiseformat.cpp
|
||||
organise/organisedialog.cpp
|
||||
organise/organiseerrordialog.cpp
|
||||
transcoder/transcoder.cpp
|
||||
transcoder/transcodedialog.cpp
|
||||
transcoder/transcoderoptionsaac.cpp
|
||||
@ -786,19 +785,19 @@ SOURCES
|
||||
transcoder/transcoderoptionsspeex.cpp
|
||||
transcoder/transcoderoptionsvorbis.cpp
|
||||
transcoder/transcoderoptionswma.cpp
|
||||
settings/transcodersettingspage.cpp
|
||||
HEADERS
|
||||
core/organise.h
|
||||
settings/transcodersettingspage.h
|
||||
dialogs/organisedialog.h
|
||||
dialogs/organiseerrordialog.h
|
||||
organise/organise.h
|
||||
organise/organisedialog.h
|
||||
organise/organiseerrordialog.h
|
||||
transcoder/transcoder.h
|
||||
transcoder/transcodedialog.h
|
||||
transcoder/transcoderoptionsdialog.h
|
||||
transcoder/transcoderoptionsmp3.h
|
||||
settings/transcodersettingspage.h
|
||||
UI
|
||||
settings/transcodersettingspage.ui
|
||||
dialogs/organisedialog.ui
|
||||
dialogs/organiseerrordialog.ui
|
||||
organise/organisedialog.ui
|
||||
organise/organiseerrordialog.ui
|
||||
transcoder/transcodedialog.ui
|
||||
transcoder/transcodelogdialog.ui
|
||||
transcoder/transcoderoptionsaac.ui
|
||||
@ -809,6 +808,7 @@ UI
|
||||
transcoder/transcoderoptionsspeex.ui
|
||||
transcoder/transcoderoptionsvorbis.ui
|
||||
transcoder/transcoderoptionswma.ui
|
||||
settings/transcodersettingspage.ui
|
||||
)
|
||||
|
||||
# CDIO backend and device
|
||||
|
@ -74,7 +74,7 @@
|
||||
#endif
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include "dialogs/organisedialog.h"
|
||||
#include "organise/organisedialog.h"
|
||||
#endif
|
||||
#include "settings/collectionsettingspage.h"
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
||||
#endif
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include "dialogs/organisedialog.h"
|
||||
#include "organise/organisedialog.h"
|
||||
#endif
|
||||
#include "settings/collectionsettingspage.h"
|
||||
|
||||
|
@ -85,7 +85,7 @@
|
||||
#include "dialogs/trackselectiondialog.h"
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include "dialogs/organisedialog.h"
|
||||
# include "organise/organisedialog.h"
|
||||
#endif
|
||||
#include "widgets/fancytabwidget.h"
|
||||
#include "widgets/playingwidget.h"
|
||||
|
@ -84,6 +84,7 @@ class Song {
|
||||
static const QString kEmbeddedCover;
|
||||
|
||||
static const QRegExp kCoverRemoveDisc;
|
||||
static const QRegExp kFilenameRemoveNonFatChars;
|
||||
|
||||
static QString JoinSpec(const QString &table);
|
||||
|
||||
|
@ -57,8 +57,8 @@
|
||||
#include "core/mergedproxymodel.h"
|
||||
#include "core/mimedata.h"
|
||||
#include "core/musicstorage.h"
|
||||
#include "dialogs/organisedialog.h"
|
||||
#include "dialogs/organiseerrordialog.h"
|
||||
#include "organise/organisedialog.h"
|
||||
#include "organise/organiseerrordialog.h"
|
||||
#include "collection/collectiondirectorymodel.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#include "collection/collectionview.h"
|
||||
|
@ -31,9 +31,9 @@
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "utilities.h"
|
||||
#include "taskmanager.h"
|
||||
#include "musicstorage.h"
|
||||
#include "core/utilities.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/musicstorage.h"
|
||||
#include "organise.h"
|
||||
#include "transcoder/transcoder.h"
|
||||
|
@ -55,11 +55,11 @@
|
||||
#include "core/closure.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/musicstorage.h"
|
||||
#include "core/organise.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/utilities.h"
|
||||
#include "widgets/freespacebar.h"
|
||||
#include "widgets/linetextedit.h"
|
||||
#include "organise.h"
|
||||
#include "organisedialog.h"
|
||||
#include "organiseerrordialog.h"
|
||||
#include "ui_organisedialog.h"
|
||||
@ -109,8 +109,8 @@ OrganiseDialog::OrganiseDialog(TaskManager *task_manager, QWidget *parent)
|
||||
|
||||
connect(ui_->destination, SIGNAL(currentIndexChanged(int)), SLOT(UpdatePreviews()));
|
||||
connect(ui_->naming, SIGNAL(textChanged()), SLOT(UpdatePreviews()));
|
||||
connect(ui_->replace_ascii, SIGNAL(toggled(bool)), SLOT(UpdatePreviews()));
|
||||
connect(ui_->replace_the, SIGNAL(toggled(bool)), SLOT(UpdatePreviews()));
|
||||
connect(ui_->remove_non_fat, SIGNAL(toggled(bool)), SLOT(UpdatePreviews()));
|
||||
connect(ui_->remove_non_ascii, SIGNAL(toggled(bool)), SLOT(UpdatePreviews()));
|
||||
connect(ui_->replace_spaces, SIGNAL(toggled(bool)), SLOT(UpdatePreviews()));
|
||||
|
||||
// Get the titles of the tags to put in the insert menu
|
||||
@ -293,9 +293,9 @@ void OrganiseDialog::UpdatePreviews() {
|
||||
|
||||
// Update the format object
|
||||
format_.set_format(ui_->naming->toPlainText());
|
||||
format_.set_replace_non_ascii(ui_->replace_ascii->isChecked());
|
||||
format_.set_remove_non_fat(ui_->remove_non_fat->isChecked());
|
||||
format_.set_remove_non_ascii(ui_->remove_non_ascii->isChecked());
|
||||
format_.set_replace_spaces(ui_->replace_spaces->isChecked());
|
||||
format_.set_replace_the(ui_->replace_the->isChecked());
|
||||
|
||||
const bool format_valid = !has_local_destination || format_.IsValid();
|
||||
|
||||
@ -310,8 +310,8 @@ void OrganiseDialog::UpdatePreviews() {
|
||||
|
||||
// Update the previews
|
||||
ui_->preview->clear();
|
||||
ui_->preview_group->setVisible(has_local_destination);
|
||||
ui_->naming_group->setVisible(has_local_destination);
|
||||
ui_->groupbox_preview->setVisible(has_local_destination);
|
||||
ui_->groupbox_naming->setVisible(has_local_destination);
|
||||
if (has_local_destination) {
|
||||
for (const Organise::NewSongInfo &song_info : new_songs_info_) {
|
||||
QString filename = storage->LocalPath() + "/" + song_info.new_filename_;
|
||||
@ -330,9 +330,9 @@ QSize OrganiseDialog::sizeHint() const { return QSize(650, 0); }
|
||||
void OrganiseDialog::Reset() {
|
||||
|
||||
ui_->naming->setPlainText(kDefaultFormat);
|
||||
ui_->replace_ascii->setChecked(false);
|
||||
ui_->replace_spaces->setChecked(false);
|
||||
ui_->replace_the->setChecked(false);
|
||||
ui_->remove_non_fat->setChecked(false);
|
||||
ui_->remove_non_ascii->setChecked(false);
|
||||
ui_->replace_spaces->setChecked(true);
|
||||
ui_->overwrite->setChecked(false);
|
||||
ui_->mark_as_listened->setChecked(false);
|
||||
ui_->eject_after->setChecked(false);
|
||||
@ -346,9 +346,9 @@ void OrganiseDialog::showEvent(QShowEvent*) {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
ui_->naming->setPlainText(s.value("format", kDefaultFormat).toString());
|
||||
ui_->replace_ascii->setChecked(s.value("replace_ascii", false).toBool());
|
||||
ui_->replace_spaces->setChecked(s.value("replace_spaces", false).toBool());
|
||||
ui_->replace_the->setChecked(s.value("replace_the", false).toBool());
|
||||
ui_->remove_non_fat->setChecked(s.value("remove_non_fat", false).toBool());
|
||||
ui_->remove_non_ascii->setChecked(s.value("remove_non_ascii", false).toBool());
|
||||
ui_->replace_spaces->setChecked(s.value("replace_spaces", true).toBool());
|
||||
ui_->overwrite->setChecked(s.value("overwrite", false).toBool());
|
||||
ui_->mark_as_listened->setChecked(s.value("mark_as_listened", false).toBool());
|
||||
ui_->eject_after->setChecked(s.value("eject_after", false).toBool());
|
||||
@ -367,9 +367,9 @@ void OrganiseDialog::accept() {
|
||||
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("format", ui_->naming->toPlainText());
|
||||
s.setValue("replace_ascii", ui_->replace_ascii->isChecked());
|
||||
s.setValue("remove_non_fat", ui_->remove_non_fat->isChecked());
|
||||
s.setValue("remove_non_ascii", ui_->remove_non_ascii->isChecked());
|
||||
s.setValue("replace_spaces", ui_->replace_spaces->isChecked());
|
||||
s.setValue("replace_the", ui_->replace_the->isChecked());
|
||||
s.setValue("overwrite", ui_->overwrite->isChecked());
|
||||
s.setValue("mark_as_listened", ui_->overwrite->isChecked());
|
||||
s.setValue("destination", ui_->destination->currentText());
|
@ -40,8 +40,8 @@
|
||||
#include <QtEvents>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/organise.h"
|
||||
#include "core/organiseformat.h"
|
||||
#include "organise.h"
|
||||
#include "organiseformat.h"
|
||||
|
||||
class QResizeEvent;
|
||||
class QShowEvent;
|
@ -19,9 +19,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<layout class="QFormLayout" name="layout_copying">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="label_destination">
|
||||
<property name="text">
|
||||
<string>Destination</string>
|
||||
</property>
|
||||
@ -31,7 +31,7 @@
|
||||
<widget class="QComboBox" name="destination"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="label_after_copying">
|
||||
<property name="text">
|
||||
<string>After copying...</string>
|
||||
</property>
|
||||
@ -57,14 +57,7 @@
|
||||
<widget class="FreeSpaceBar" name="free_space" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="eject_after">
|
||||
<property name="text">
|
||||
<string>Safely remove the device after copying</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="naming_group">
|
||||
<widget class="QGroupBox" name="groupbox_naming">
|
||||
<property name="title">
|
||||
<string>Naming options</string>
|
||||
</property>
|
||||
@ -99,23 +92,23 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="replace_the">
|
||||
<widget class="QCheckBox" name="remove_non_fat">
|
||||
<property name="text">
|
||||
<string>Ignore "The" in artist names</string>
|
||||
<string>Restrict to characters allowed on FAT filesystems</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="remove_non_ascii">
|
||||
<property name="text">
|
||||
<string>Restrict characters to ASCII</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="replace_spaces">
|
||||
<property name="text">
|
||||
<string>Replaces spaces with underscores</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="replace_ascii">
|
||||
<property name="text">
|
||||
<string>Restrict to ASCII characters</string>
|
||||
<string>Replace spaces with underscores</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -137,7 +130,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="preview_group">
|
||||
<widget class="QGroupBox" name="groupbox_preview">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
@ -145,7 +138,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="preview_stack">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="preview_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
@ -187,7 +180,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<spacer name="spacer_preview_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -207,7 +200,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<spacer name="spacer_preview_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -226,6 +219,13 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="eject_after">
|
||||
<property name="text">
|
||||
<string>Safely remove the device after copying</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="orientation">
|
||||
@ -260,12 +260,10 @@
|
||||
<tabstops>
|
||||
<tabstop>destination</tabstop>
|
||||
<tabstop>aftercopying</tabstop>
|
||||
<tabstop>eject_after</tabstop>
|
||||
<tabstop>naming</tabstop>
|
||||
<tabstop>insert</tabstop>
|
||||
<tabstop>replace_the</tabstop>
|
||||
<tabstop>remove_non_fat</tabstop>
|
||||
<tabstop>replace_spaces</tabstop>
|
||||
<tabstop>replace_ascii</tabstop>
|
||||
<tabstop>overwrite</tabstop>
|
||||
<tabstop>button_box</tabstop>
|
||||
</tabstops>
|
@ -37,10 +37,10 @@
|
||||
#include <QTextFormat>
|
||||
|
||||
#include "core/arraysize.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/utilities.h"
|
||||
#include "core/song.h"
|
||||
|
||||
#include "timeconstants.h"
|
||||
#include "utilities.h"
|
||||
#include "song.h"
|
||||
#include "organiseformat.h"
|
||||
|
||||
class QTextDocument;
|
||||
@ -56,6 +56,7 @@ const QStringList OrganiseFormat::kKnownTags = QStringList() << "title"
|
||||
<< "track"
|
||||
<< "disc"
|
||||
<< "year"
|
||||
<< "originalyear"
|
||||
<< "genre"
|
||||
<< "comment"
|
||||
<< "length"
|
||||
@ -65,12 +66,11 @@ const QStringList OrganiseFormat::kKnownTags = QStringList() << "title"
|
||||
<< "extension"
|
||||
<< "performer"
|
||||
<< "grouping"
|
||||
<< "lyrics"
|
||||
<< "originalyear";
|
||||
<< "lyrics";
|
||||
|
||||
// From http://en.wikipedia.org/wiki/8.3_filename#Directory_table
|
||||
const char OrganiseFormat::kInvalidFatCharacters[] = "\"*/\\:<>?|";
|
||||
const int OrganiseFormat::kInvalidFatCharactersCount = arraysize(OrganiseFormat::kInvalidFatCharacters) - 1;
|
||||
const QRegExp OrganiseFormat::kValidFatCharacters("[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]");
|
||||
const QRegExp OrganiseFormat::kInvalidFatCharacters("[\"*\\:<>?|/]");
|
||||
|
||||
const char OrganiseFormat::kInvalidPrefixCharacters[] = ".";
|
||||
const int OrganiseFormat::kInvalidPrefixCharactersCount = arraysize(OrganiseFormat::kInvalidPrefixCharacters) - 1;
|
||||
@ -85,9 +85,9 @@ const QRgb OrganiseFormat::SyntaxHighlighter::kBlockColorDark = qRgb(64, 64, 64)
|
||||
|
||||
OrganiseFormat::OrganiseFormat(const QString &format)
|
||||
: format_(format),
|
||||
replace_non_ascii_(false),
|
||||
replace_spaces_(false),
|
||||
replace_the_(false) {}
|
||||
remove_non_fat_(false),
|
||||
remove_non_ascii_(false),
|
||||
replace_spaces_(true) {}
|
||||
|
||||
void OrganiseFormat::set_format(const QString &v) {
|
||||
format_ = v;
|
||||
@ -111,13 +111,16 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
|
||||
if (QFileInfo(filename).completeBaseName().isEmpty()) {
|
||||
// Avoid having empty filenames, or filenames with extension only: in this case, keep the original filename.
|
||||
// We remove the extension from "filename" if it exists, as song.basefilename() also contains the extension.
|
||||
filename =
|
||||
Utilities::PathWithoutFilenameExtension(filename) + song.basefilename();
|
||||
filename = Utilities::PathWithoutFilenameExtension(filename) + song.basefilename();
|
||||
}
|
||||
|
||||
if (remove_non_fat_) {
|
||||
filename.remove(kValidFatCharacters);
|
||||
}
|
||||
|
||||
if (replace_spaces_) filename.replace(QRegExp("\\s"), "_");
|
||||
|
||||
if (replace_non_ascii_) {
|
||||
if (remove_non_ascii_) {
|
||||
QString stripped;
|
||||
for (int i = 0; i < filename.length(); ++i) {
|
||||
const QCharRef c = filename[i];
|
||||
@ -225,27 +228,25 @@ QString OrganiseFormat::TagValue(const QString &tag, const Song &song) const {
|
||||
value = QFileInfo(song.url().toLocalFile()).suffix();
|
||||
else if (tag == "artistinitial") {
|
||||
value = song.effective_albumartist().trimmed();
|
||||
if (replace_the_ && !value.isEmpty()) value.replace(QRegExp("^the\\s+", Qt::CaseInsensitive), "");
|
||||
if (!value.isEmpty()) value = value[0].toUpper();
|
||||
if (!value.isEmpty()) {
|
||||
value.replace(QRegExp("^the\\s+", Qt::CaseInsensitive), "");
|
||||
value = value[0].toUpper();
|
||||
}
|
||||
}
|
||||
else if (tag == "albumartist") {
|
||||
value = song.is_compilation() ? "Various Artists" : song.effective_albumartist();
|
||||
}
|
||||
|
||||
if (replace_the_ && (tag == "artist" || tag == "albumartist"))
|
||||
value.replace(QRegExp("^the\\s+", Qt::CaseInsensitive), "");
|
||||
|
||||
if (value == "0" || value == "-1") value = "";
|
||||
|
||||
// Prepend a 0 to single-digit track numbers
|
||||
if (tag == "track" && value.length() == 1) value.prepend('0');
|
||||
|
||||
// Replace characters that really shouldn't be in paths
|
||||
for (int i = 0; i < kInvalidFatCharactersCount; ++i) {
|
||||
value.replace(kInvalidFatCharacters[i], '_');
|
||||
}
|
||||
value.remove(kInvalidFatCharacters);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
OrganiseFormat::Validator::Validator(QObject *parent) : QValidator(parent) {}
|
@ -44,20 +44,21 @@ class OrganiseFormat {
|
||||
static const char *kTagPattern;
|
||||
static const char *kBlockPattern;
|
||||
static const QStringList kKnownTags;
|
||||
static const char kInvalidFatCharacters[];
|
||||
static const int kInvalidFatCharactersCount;
|
||||
static const QRegExp kValidFatCharacters;
|
||||
static const QRegExp kInvalidFatCharacters;
|
||||
|
||||
static const char kInvalidPrefixCharacters[];
|
||||
static const int kInvalidPrefixCharactersCount;
|
||||
|
||||
QString format() const { return format_; }
|
||||
bool replace_non_ascii() const { return replace_non_ascii_; }
|
||||
bool remove_non_fat() const { return remove_non_fat_; }
|
||||
bool remove_non_ascii() const { return remove_non_ascii_; }
|
||||
bool replace_spaces() const { return replace_spaces_; }
|
||||
bool replace_the() const { return replace_the_; }
|
||||
|
||||
void set_format(const QString &v);
|
||||
void set_replace_non_ascii(bool v) { replace_non_ascii_ = v; }
|
||||
void set_remove_non_fat(bool v) { remove_non_fat_ = v; }
|
||||
void set_remove_non_ascii(bool v) { remove_non_ascii_ = v; }
|
||||
void set_replace_spaces(bool v) { replace_spaces_ = v; }
|
||||
void set_replace_the(bool v) { replace_the_ = v; }
|
||||
|
||||
bool IsValid() const;
|
||||
QString GetFilenameForSong(const Song &song) const;
|
||||
@ -88,9 +89,9 @@ class OrganiseFormat {
|
||||
QString TagValue(const QString &tag, const Song &song) const;
|
||||
|
||||
QString format_;
|
||||
bool replace_non_ascii_;
|
||||
bool remove_non_fat_;
|
||||
bool remove_non_ascii_;
|
||||
bool replace_spaces_;
|
||||
bool replace_the_;
|
||||
|
||||
};
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "fileviewlist.h"
|
||||
#include "ui_fileview.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include "dialogs/organiseerrordialog.h"
|
||||
# include "organise/organiseerrordialog.h"
|
||||
#endif
|
||||
|
||||
const char *FileView::kFileFilter =
|
||||
|
Loading…
x
Reference in New Issue
Block a user