diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index a3e0967a..402ebf8f 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -2190,7 +2190,7 @@ void MainWindow::AddFile() { PlaylistParser parser(app_->collection_backend()); // Show dialog - QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(), tr(kAllFilesFilterSpec))); + QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(PlaylistParser::Type_Load), tr(kAllFilesFilterSpec))); if (file_names.isEmpty()) return; diff --git a/src/core/songloader.cpp b/src/core/songloader.cpp index 292d2bd8..803261a6 100644 --- a/src/core/songloader.cpp +++ b/src/core/songloader.cpp @@ -290,7 +290,7 @@ SongLoader::Result SongLoader::LoadLocalAsync(const QString &filename) { ParserBase *parser = playlist_parser_->ParserForMagic(data); if (!parser) { // Check the file extension as well, maybe the magic failed, or it was a basic M3U file which is just a plain list of filenames. - parser = playlist_parser_->ParserForExtension(fileinfo.suffix().toLower()); + parser = playlist_parser_->ParserForExtension(PlaylistParser::Type_Load, fileinfo.suffix().toLower()); } if (parser) { // It's a playlist! diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index e8cebc27..17884961 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -111,9 +111,6 @@ const QRgb Playlist::kDynamicHistoryColor = qRgb(0x80, 0x80, 0x80); const char *Playlist::kSettingsGroup = "Playlist"; -const char *Playlist::kPathType = "path_type"; -const char *Playlist::kWriteMetadata = "write_metadata"; - const int Playlist::kUndoStackSize = 20; const int Playlist::kUndoItemLimit = 500; diff --git a/src/playlist/playlist.h b/src/playlist/playlist.h index 68bc15d5..7accd83f 100644 --- a/src/playlist/playlist.h +++ b/src/playlist/playlist.h @@ -143,13 +143,6 @@ class Playlist : public QAbstractListModel { Role_CanSetRating, }; - enum Path { - Path_Automatic = 0, // Automatically select path type - Path_Absolute, // Always use absolute paths - Path_Relative, // Always use relative paths - Path_Ask_User, // Only used in preferences: to ask user which of the previous values he wants to use. - }; - enum AutoScroll { AutoScroll_Never, AutoScroll_Maybe, @@ -168,9 +161,6 @@ class Playlist : public QAbstractListModel { static const char *kSettingsGroup; - static const char *kPathType; - static const char *kWriteMetadata; - static const int kUndoStackSize; static const int kUndoItemLimit; diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp index f2541c19..1a3c0c35 100644 --- a/src/playlist/playlistcontainer.cpp +++ b/src/playlist/playlistcontainer.cpp @@ -345,7 +345,7 @@ void PlaylistContainer::NewPlaylist() { manager_->New(tr("Playlist")); } void PlaylistContainer::LoadPlaylist() { QString filename = settings_.value("last_load_playlist").toString(); - filename = QFileDialog::getOpenFileName(this, tr("Load playlist"), filename, manager_->parser()->filters()); + filename = QFileDialog::getOpenFileName(this, tr("Load playlist"), filename, manager_->parser()->filters(PlaylistParser::Type_Load)); if (filename.isNull()) return; diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp index 1fc6d93d..35318d7c 100644 --- a/src/playlist/playlistmanager.cpp +++ b/src/playlist/playlistmanager.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "core/application.h" #include "core/logging.h" @@ -55,6 +56,7 @@ #include "covermanager/albumcoverloaderresult.h" #include "covermanager/currentalbumcoverloader.h" #include "organize/organizeformat.h" +#include "settings/playlistsettingspage.h" #include "playlist.h" #include "playlistbackend.h" #include "playlistcontainer.h" @@ -200,22 +202,22 @@ void PlaylistManager::New(const QString &name, const SongList &songs, const QStr void PlaylistManager::Load(const QString &filename) { - QFileInfo info(filename); + QFileInfo fileinfo(filename); - int id = playlist_backend_->CreatePlaylist(info.completeBaseName(), QString()); + int id = playlist_backend_->CreatePlaylist(fileinfo.completeBaseName(), QString()); if (id == -1) { emit Error(tr("Couldn't create playlist")); return; } - Playlist *playlist = AddPlaylist(id, info.completeBaseName(), QString(), QString(), false); + Playlist *playlist = AddPlaylist(id, fileinfo.completeBaseName(), QString(), QString(), false); playlist->InsertUrls(QList() << QUrl::fromLocalFile(filename)); } -void PlaylistManager::Save(const int id, const QString &filename, const Playlist::Path path_type) { +void PlaylistManager::Save(const int id, const QString &filename, const PlaylistSettingsPage::PathType path_type) { if (playlists_.contains(id)) { parser_->Save(playlist(id)->GetAllSongs(), filename, path_type); @@ -237,7 +239,7 @@ void PlaylistManager::Save(const int id, const QString &filename, const Playlist } -void PlaylistManager::ItemsLoadedForSavePlaylist(const SongList &songs, const QString &filename, const Playlist::Path path_type) { +void PlaylistManager::ItemsLoadedForSavePlaylist(const SongList &songs, const QString &filename, const PlaylistSettingsPage::PathType path_type) { parser_->Save(songs, filename, path_type); @@ -245,67 +247,43 @@ void PlaylistManager::ItemsLoadedForSavePlaylist(const SongList &songs, const QS void PlaylistManager::SaveWithUI(const int id, const QString &playlist_name) { - QSettings settings; - settings.beginGroup(Playlist::kSettingsGroup); - QString filename = settings.value("last_save_playlist").toString(); - QString extension = settings.value("last_save_extension", parser()->default_extension()).toString(); - QString filter = settings.value("last_save_filter", parser()->default_filter()).toString(); + QSettings s; + s.beginGroup(Playlist::kSettingsGroup); + QString last_save_filter = s.value("last_save_filter", parser()->default_filter()).toString(); + QString last_save_path = s.value("last_save_path", QDir::homePath()).toString(); + QString last_save_extension = s.value("last_save_extension", parser()->default_extension()).toString(); + s.endGroup(); QString suggested_filename = playlist_name; - suggested_filename = suggested_filename.remove(OrganizeFormat::kProblematicCharacters); + QString filename = last_save_path + "/" + suggested_filename.remove(OrganizeFormat::kProblematicCharacters) + "." + last_save_extension; - qLog(Debug) << "Using extension:" << extension; - - // We want to use the playlist tab name (with disallowed characters removed) - // as a default filename, but in the same directory as the last saved file. - - // Strip off filename components until we find something that's a folder + QFileInfo fileinfo; forever { - QFileInfo fileinfo(filename); - if (filename.isEmpty() || fileinfo.isDir()) break; - - filename = filename.section('/', 0, -2); + filename = QFileDialog::getSaveFileName(nullptr, tr("Save playlist", "Title of the playlist save dialog."), filename, parser()->filters(PlaylistParser::Type_Save), &last_save_filter); + if (filename.isEmpty()) return; + fileinfo.setFile(filename); + ParserBase *parser = parser_->ParserForExtension(PlaylistParser::Type_Save, fileinfo.suffix()); + if (parser) break; + QMessageBox::warning(nullptr, tr("Unknown playlist extension"), tr("Unknown file extension for playlist.")); } - // Use the home directory as a fallback in case the path is empty. - if (filename.isEmpty()) filename = QDir::homePath(); - - // Add the suggested filename - filename += "/" + suggested_filename + "." + extension; - qLog(Debug) << "Suggested filename:" << filename; - - filename = QFileDialog::getSaveFileName(nullptr, tr("Save playlist", "Title of the playlist save dialog."), filename, parser()->filters(), &filter); - - if (filename.isNull()) { - return; + s.beginGroup(PlaylistSettingsPage::kSettingsGroup); + PlaylistSettingsPage::PathType path_type = static_cast(s.value("path_type", PlaylistSettingsPage::PathType_Automatic).toInt()); + s.endGroup(); + if (path_type == PlaylistSettingsPage::PathType_Ask_User) { + PlaylistSaveOptionsDialog optionsdialog(nullptr); + optionsdialog.setModal(true); + if (optionsdialog.exec() != QDialog::Accepted) return; + path_type = optionsdialog.path_type(); } - // Check if the file extension is valid. Fallback to the default if not. - QFileInfo info(filename); - ParserBase *parser = parser_->ParserForExtension(info.suffix()); - if (!parser) { - qLog(Warning) << "Unknown file extension:" << info.suffix(); - filename = info.absolutePath() + "/" + info.fileName() + "." + parser_->default_extension(); - info.setFile(filename); - filter = info.suffix(); - } + s.beginGroup(Playlist::kSettingsGroup); + s.setValue("last_save_filter", last_save_filter); + s.setValue("last_save_path", fileinfo.path()); + s.setValue("last_save_extension", fileinfo.suffix()); + s.endGroup(); - int p = settings.value(Playlist::kPathType, Playlist::Path_Automatic).toInt(); - Playlist::Path path = static_cast(p); - if (path == Playlist::Path_Ask_User) { - PlaylistSaveOptionsDialog optionsDialog(nullptr); - optionsDialog.setModal(true); - if (optionsDialog.exec() != QDialog::Accepted) { - return; - } - path = optionsDialog.path_type(); - } - - settings.setValue("last_save_playlist", filename); - settings.setValue("last_save_filter", filter); - settings.setValue("last_save_extension", info.suffix()); - - Save(id == -1 ? current_id() : id, filename, path); + Save(id == -1 ? current_id() : id, filename, path_type); } @@ -658,7 +636,7 @@ void PlaylistManager::SaveAllPlaylists() { for (QMap::const_iterator it = playlists_.constBegin(); it != playlists_.constEnd(); ++it) { const Data &data = *it; const QString filepath = path + "/" + data.name + ".m3u"; - Save(it.key(), filepath, Playlist::Path_Absolute); + Save(it.key(), filepath, PlaylistSettingsPage::PathType_Absolute); } } diff --git a/src/playlist/playlistmanager.h b/src/playlist/playlistmanager.h index 6c696224..bb027138 100644 --- a/src/playlist/playlistmanager.h +++ b/src/playlist/playlistmanager.h @@ -34,6 +34,7 @@ #include #include "core/song.h" +#include "settings/playlistsettingspage.h" #include "playlist.h" #include "smartplaylists/playlistgenerator.h" @@ -83,7 +84,7 @@ class PlaylistManagerInterface : public QObject { public slots: virtual void New(const QString &name, const SongList &songs = SongList(), const QString &special_type = QString()) = 0; virtual void Load(const QString &filename) = 0; - virtual void Save(const int id, const QString &filename, const Playlist::Path path_type) = 0; + virtual void Save(const int id, const QString &filename, const PlaylistSettingsPage::PathType path_type) = 0; virtual void Rename(const int id, const QString &new_name) = 0; virtual void Delete(const int id) = 0; virtual bool Close(const int id) = 0; @@ -181,7 +182,7 @@ class PlaylistManager : public PlaylistManagerInterface { public slots: void New(const QString &name, const SongList &songs = SongList(), const QString &special_type = QString()) override; void Load(const QString &filename) override; - void Save(const int id, const QString &filename, const Playlist::Path path_type) override; + void Save(const int id, const QString &filename, const PlaylistSettingsPage::PathType path_type) override; // Display a file dialog to let user choose a file before saving the file void SaveWithUI(const int id, const QString &playlist_name); void Rename(const int id, const QString &new_name) override; @@ -232,7 +233,7 @@ class PlaylistManager : public PlaylistManagerInterface { void OneOfPlaylistsChanged(); void UpdateSummaryText(); void SongsDiscovered(const SongList &songs); - void ItemsLoadedForSavePlaylist(const SongList &songs, const QString &filename, const Playlist::Path path_type); + void ItemsLoadedForSavePlaylist(const SongList &songs, const QString &filename, const PlaylistSettingsPage::PathType path_type); void PlaylistLoaded(); private: diff --git a/src/playlist/playlistsaveoptionsdialog.cpp b/src/playlist/playlistsaveoptionsdialog.cpp index fe0dc2df..e9dfef3f 100644 --- a/src/playlist/playlistsaveoptionsdialog.cpp +++ b/src/playlist/playlistsaveoptionsdialog.cpp @@ -27,7 +27,7 @@ #include #include -#include "playlist.h" +#include "settings/playlistsettingspage.h" #include "playlistsaveoptionsdialog.h" #include "ui_playlistsaveoptionsdialog.h" @@ -37,9 +37,10 @@ PlaylistSaveOptionsDialog::PlaylistSaveOptionsDialog(QWidget *parent) : QDialog( ui->setupUi(this); - ui->filePaths->addItem(tr("Automatic"), Playlist::Path_Automatic); - ui->filePaths->addItem(tr("Relative"), Playlist::Path_Relative); - ui->filePaths->addItem(tr("Absolute"), Playlist::Path_Absolute); + ui->filePaths->addItem(tr("Automatic"), PlaylistSettingsPage::PathType_Automatic); + ui->filePaths->addItem(tr("Relative"), PlaylistSettingsPage::PathType_Relative); + ui->filePaths->addItem(tr("Absolute"), PlaylistSettingsPage::PathType_Absolute); + } PlaylistSaveOptionsDialog::~PlaylistSaveOptionsDialog() { delete ui; } @@ -48,14 +49,15 @@ void PlaylistSaveOptionsDialog::accept() { if (ui->remember_user_choice->isChecked()) { QSettings s; - s.beginGroup(Playlist::kSettingsGroup); - s.setValue(Playlist::kPathType, ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt()); + s.beginGroup(PlaylistSettingsPage::kSettingsGroup); + s.setValue("path_type", ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt()); + s.endGroup(); } QDialog::accept(); } -Playlist::Path PlaylistSaveOptionsDialog::path_type() const { - return static_cast(ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt()); +PlaylistSettingsPage::PathType PlaylistSaveOptionsDialog::path_type() const { + return static_cast(ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt()); } diff --git a/src/playlist/playlistsaveoptionsdialog.h b/src/playlist/playlistsaveoptionsdialog.h index 384d8fe9..825ee0e2 100644 --- a/src/playlist/playlistsaveoptionsdialog.h +++ b/src/playlist/playlistsaveoptionsdialog.h @@ -27,7 +27,7 @@ #include #include -#include "playlist.h" +#include "settings/playlistsettingspage.h" class QWidget; @@ -43,7 +43,7 @@ class PlaylistSaveOptionsDialog : public QDialog { ~PlaylistSaveOptionsDialog() override; void accept() override; - Playlist::Path path_type() const; + PlaylistSettingsPage::PathType path_type() const; private: static const char *kSettingsGroup; diff --git a/src/playlistparsers/asxiniparser.cpp b/src/playlistparsers/asxiniparser.cpp index 570376a2..1ecb6208 100644 --- a/src/playlistparsers/asxiniparser.cpp +++ b/src/playlistparsers/asxiniparser.cpp @@ -26,8 +26,9 @@ #include #include +#include "settings/playlistsettingspage.h" +#include "parserbase.h" #include "asxiniparser.h" -#include "playlistparsers/parserbase.h" class CollectionBackendInterface; @@ -68,7 +69,7 @@ SongList AsxIniParser::Load(QIODevice *device, const QString &playlist_path, con } -void AsxIniParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void AsxIniParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { QTextStream s(device); s << "[Reference]" << qt_endl; diff --git a/src/playlistparsers/asxiniparser.h b/src/playlistparsers/asxiniparser.h index c14b7440..485574c7 100644 --- a/src/playlistparsers/asxiniparser.h +++ b/src/playlistparsers/asxiniparser.h @@ -29,8 +29,8 @@ #include "config.h" #include "core/song.h" +#include "settings/playlistsettingspage.h" #include "parserbase.h" -#include "playlist/playlist.h" class QIODevice; class CollectionBackendInterface; @@ -43,11 +43,13 @@ class AsxIniParser : public ParserBase { QString name() const override { return "ASX/INI"; } QStringList file_extensions() const override { return QStringList() << "asxini"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; }; #endif // ASXINIPARSER_H diff --git a/src/playlistparsers/asxparser.cpp b/src/playlistparsers/asxparser.cpp index ec8fe415..a4d3b014 100644 --- a/src/playlistparsers/asxparser.cpp +++ b/src/playlistparsers/asxparser.cpp @@ -32,9 +32,10 @@ #include #include -#include "asxparser.h" #include "core/utilities.h" -#include "playlistparsers/xmlparser.h" +#include "settings/playlistsettingspage.h" +#include "xmlparser.h" +#include "asxparser.h" class CollectionBackendInterface; @@ -131,7 +132,7 @@ return_song: } -void ASXParser::Save(const SongList &songs, QIODevice *device, const QDir&, Playlist::Path) const { +void ASXParser::Save(const SongList &songs, QIODevice *device, const QDir&, const PlaylistSettingsPage::PathType) const { QXmlStreamWriter writer(device); writer.setAutoFormatting(true); diff --git a/src/playlistparsers/asxparser.h b/src/playlistparsers/asxparser.h index f0270fdc..c928e0dd 100644 --- a/src/playlistparsers/asxparser.h +++ b/src/playlistparsers/asxparser.h @@ -29,7 +29,7 @@ #include "config.h" #include "core/song.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" #include "xmlparser.h" class QIODevice; @@ -45,11 +45,13 @@ class ASXParser : public XMLParser { QString name() const override { return "ASX"; } QStringList file_extensions() const override { return QStringList() << "asx"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; private: Song ParseTrack(QXmlStreamReader *reader, const QDir &dir, const bool collection_search) const; diff --git a/src/playlistparsers/cueparser.cpp b/src/playlistparsers/cueparser.cpp index e8bc3276..e49ef46c 100644 --- a/src/playlistparsers/cueparser.cpp +++ b/src/playlistparsers/cueparser.cpp @@ -35,8 +35,9 @@ #include "core/logging.h" #include "core/timeconstants.h" +#include "settings/playlistsettingspage.h" +#include "parserbase.h" #include "cueparser.h" -#include "playlistparsers/parserbase.h" class CollectionBackendInterface; @@ -350,7 +351,7 @@ qint64 CueParser::IndexToMarker(const QString &index) { } -void CueParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void CueParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { Q_UNUSED(songs); Q_UNUSED(device); diff --git a/src/playlistparsers/cueparser.h b/src/playlistparsers/cueparser.h index b1f7b29f..4824a502 100644 --- a/src/playlistparsers/cueparser.h +++ b/src/playlistparsers/cueparser.h @@ -32,8 +32,8 @@ #include #include "core/song.h" +#include "settings/playlistsettingspage.h" #include "parserbase.h" -#include "playlist/playlist.h" class QIODevice; class CollectionBackendInterface; @@ -64,11 +64,13 @@ class CueParser : public ParserBase { QString name() const override { return "CUE"; } QStringList file_extensions() const override { return QStringList() << "cue"; } QString mime_type() const override { return "application/x-cue"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return false; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; static QString FindCueFilename(const QString &filename); diff --git a/src/playlistparsers/m3uparser.cpp b/src/playlistparsers/m3uparser.cpp index 9e2f8454..81d8138e 100644 --- a/src/playlistparsers/m3uparser.cpp +++ b/src/playlistparsers/m3uparser.cpp @@ -33,9 +33,9 @@ #include "core/logging.h" #include "core/timeconstants.h" +#include "settings/playlistsettingspage.h" +#include "parserbase.h" #include "m3uparser.h" -#include "playlist/playlist.h" -#include "playlistparsers/parserbase.h" class CollectionBackendInterface; @@ -125,13 +125,13 @@ bool M3UParser::ParseMetadata(const QString &line, M3UParser::Metadata *metadata } -void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { device->write("#EXTM3U\n"); QSettings s; - s.beginGroup(Playlist::kSettingsGroup); - bool write_metadata = s.value(Playlist::kWriteMetadata, true).toBool(); + s.beginGroup(PlaylistSettingsPage::kSettingsGroup); + bool write_metadata = s.value("write_metadata", true).toBool(); s.endGroup(); for (const Song &song : songs) { diff --git a/src/playlistparsers/m3uparser.h b/src/playlistparsers/m3uparser.h index 28d9cd73..3a6030f8 100644 --- a/src/playlistparsers/m3uparser.h +++ b/src/playlistparsers/m3uparser.h @@ -31,8 +31,8 @@ #include #include "core/song.h" +#include "settings/playlistsettingspage.h" #include "parserbase.h" -#include "playlist/playlist.h" class QIODevice; class CollectionBackendInterface; @@ -46,11 +46,13 @@ class M3UParser : public ParserBase { QString name() const override { return "M3U"; } QStringList file_extensions() const override { return QStringList() << "m3u" << "m3u8"; } QString mime_type() const override { return "text/uri-list"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; private: enum M3UType { diff --git a/src/playlistparsers/parserbase.cpp b/src/playlistparsers/parserbase.cpp index 024fdf6d..a90b9aba 100644 --- a/src/playlistparsers/parserbase.cpp +++ b/src/playlistparsers/parserbase.cpp @@ -30,7 +30,7 @@ #include "core/logging.h" #include "core/tagreaderclient.h" #include "collection/collectionbackend.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" #include "parserbase.h" ParserBase::ParserBase(CollectionBackendInterface *collection, QObject *parent) @@ -101,19 +101,20 @@ Song ParserBase::LoadSong(const QString &filename_or_url, const qint64 beginning } -QString ParserBase::URLOrFilename(const QUrl &url, const QDir &dir, Playlist::Path path_type) { +QString ParserBase::URLOrFilename(const QUrl &url, const QDir &dir, const PlaylistSettingsPage::PathType path_type) { if (!url.isLocalFile()) return url.toString(); const QString filename = url.toLocalFile(); - if (path_type != Playlist::Path_Absolute && QDir::isAbsolutePath(filename)) { + if (path_type != PlaylistSettingsPage::PathType_Absolute && QDir::isAbsolutePath(filename)) { const QString relative = dir.relativeFilePath(filename); - if (!relative.startsWith("../") || path_type == Playlist::Path_Relative) { + if (!relative.startsWith("../") || path_type == PlaylistSettingsPage::PathType_Relative) { return relative; } } + return filename; } diff --git a/src/playlistparsers/parserbase.h b/src/playlistparsers/parserbase.h index 8d41ade2..bbebb505 100644 --- a/src/playlistparsers/parserbase.h +++ b/src/playlistparsers/parserbase.h @@ -32,7 +32,7 @@ #include "config.h" #include "core/song.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" class QIODevice; class CollectionBackendInterface; @@ -45,6 +45,8 @@ class ParserBase : public QObject { virtual QString name() const = 0; virtual QStringList file_extensions() const = 0; + virtual bool load_supported() const = 0; + virtual bool save_supported() const = 0; virtual QString mime_type() const { return QString(); } virtual bool TryMagic(const QByteArray &data) const = 0; @@ -55,7 +57,7 @@ class ParserBase : public QObject { // Any playlist parser may decide to leave out some entries if it finds them incomplete or invalid. // This means that the final resulting SongList should be considered valid (at least from the parser's point of view). virtual SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_lookup = true) const = 0; - virtual void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const = 0; + virtual void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const = 0; protected: // Loads a song. If filename_or_url is a URL (with a scheme other than "file") then it is set on the song and the song marked as a stream. @@ -67,7 +69,7 @@ class ParserBase : public QObject { // If the URL is a file:// URL then returns its path, absolute or relative to the directory depending on the path_type option. // Otherwise returns the URL as is. This function should always be used when saving a playlist. - static QString URLOrFilename(const QUrl &url, const QDir &dir, Playlist::Path path_type); + static QString URLOrFilename(const QUrl &url, const QDir &dir, const PlaylistSettingsPage::PathType path_type); private: CollectionBackendInterface *collection_; diff --git a/src/playlistparsers/playlistparser.cpp b/src/playlistparsers/playlistparser.cpp index 54379d10..fcf82f2f 100644 --- a/src/playlistparsers/playlistparser.cpp +++ b/src/playlistparsers/playlistparser.cpp @@ -31,13 +31,14 @@ #include #include +#include "core/logging.h" +#include "settings/playlistsettingspage.h" +#include "playlistparser.h" +#include "parserbase.h" #include "asxiniparser.h" #include "asxparser.h" -#include "core/logging.h" #include "cueparser.h" #include "m3uparser.h" -#include "playlistparser.h" -#include "playlistparsers/parserbase.h" #include "plsparser.h" #include "wplparser.h" #include "xspfparser.h" @@ -47,8 +48,8 @@ const int PlaylistParser::kMagicSize = 512; PlaylistParser::PlaylistParser(CollectionBackendInterface *collection, QObject *parent) : QObject(parent) { default_parser_ = new XSPFParser(collection, this); - parsers_ << new M3UParser(collection, this); parsers_ << default_parser_; + parsers_ << new M3UParser(collection, this); parsers_ << new PLSParser(collection, this); parsers_ << new ASXParser(collection, this); parsers_ << new AsxIniParser(collection, this); @@ -57,12 +58,14 @@ PlaylistParser::PlaylistParser(CollectionBackendInterface *collection, QObject * } -QStringList PlaylistParser::file_extensions() const { +QStringList PlaylistParser::file_extensions(const Type type) const { QStringList ret; for (ParserBase *parser : parsers_) { - ret << parser->file_extensions(); + if (ParserIsSupported(type, parser)) { + ret << parser->file_extensions(); + } } std::stable_sort(ret.begin(), ret.end()); @@ -70,29 +73,36 @@ QStringList PlaylistParser::file_extensions() const { } -QStringList PlaylistParser::mime_types() const { +QStringList PlaylistParser::mime_types(const Type type) const { QStringList ret; for (ParserBase *parser : parsers_) { - if (!parser->mime_type().isEmpty()) ret << parser->mime_type(); + if (ParserIsSupported(type, parser) && !parser->mime_type().isEmpty()) { + ret << parser->mime_type(); + } } std::stable_sort(ret.begin(), ret.end()); + return ret; } -QString PlaylistParser::filters() const { +QString PlaylistParser::filters(const Type type) const { QStringList filters; filters.reserve(parsers_.count() + 1); QStringList all_extensions; for (ParserBase *parser : parsers_) { - filters << FilterForParser(parser, &all_extensions); + if (ParserIsSupported(type, parser)) { + filters << FilterForParser(parser, &all_extensions); + } } - filters.prepend(tr("All playlists (%1)").arg(all_extensions.join(" "))); + if (type == Type_Load) { + filters.prepend(tr("All playlists (%1)").arg(all_extensions.join(" "))); + } return filters.join(";;"); @@ -122,20 +132,22 @@ QString PlaylistParser::default_filter() const { return FilterForParser(default_parser_); } -ParserBase *PlaylistParser::ParserForExtension(const QString &suffix) const { +ParserBase *PlaylistParser::ParserForExtension(const Type type, const QString &suffix) const { - for (ParserBase *p : parsers_) { - if (p->file_extensions().contains(suffix)) return p; + for (ParserBase *parser : parsers_) { + if (ParserIsSupported(type, parser) && parser->file_extensions().contains(suffix)) { + return parser; + } } return nullptr; } -ParserBase *PlaylistParser::ParserForMimeType(const QString &mime_type) const { +ParserBase *PlaylistParser::ParserForMimeType(const Type type, const QString &mime_type) const { - for (ParserBase *p : parsers_) { - if (!p->mime_type().isEmpty() && (QString::compare(p->mime_type(), mime_type, Qt::CaseInsensitive) == 0)) { - return p; + for (ParserBase *parser : parsers_) { + if (ParserIsSupported(type, parser) && !parser->mime_type().isEmpty() && QString::compare(parser->mime_type(), mime_type, Qt::CaseInsensitive) == 0) { + return parser; } } return nullptr; @@ -144,9 +156,9 @@ ParserBase *PlaylistParser::ParserForMimeType(const QString &mime_type) const { ParserBase *PlaylistParser::ParserForMagic(const QByteArray &data, const QString &mime_type) const { - for (ParserBase *p : parsers_) { - if ((!mime_type.isEmpty() && mime_type == p->mime_type()) || p->TryMagic(data)) { - return p; + for (ParserBase *parser : parsers_) { + if ((!mime_type.isEmpty() && mime_type == parser->mime_type()) || parser->TryMagic(data)) { + return parser; } } return nullptr; @@ -155,10 +167,10 @@ ParserBase *PlaylistParser::ParserForMagic(const QByteArray &data, const QString SongList PlaylistParser::LoadFromFile(const QString &filename) const { - QFileInfo info(filename); + QFileInfo fileinfo(filename); // Find a parser that supports this file extension - ParserBase *parser = ParserForExtension(info.suffix()); + ParserBase *parser = ParserForExtension(Type_Load, fileinfo.suffix()); if (!parser) { qLog(Warning) << "Unknown filetype:" << filename; return SongList(); @@ -168,7 +180,7 @@ SongList PlaylistParser::LoadFromFile(const QString &filename) const { QFile file(filename); if (!file.open(QIODevice::ReadOnly)) return SongList(); - SongList ret = parser->Load(&file, filename, info.absolutePath()); + SongList ret = parser->Load(&file, filename, fileinfo.absolutePath()); file.close(); return ret; @@ -187,12 +199,12 @@ SongList PlaylistParser::LoadFromDevice(QIODevice *device, const QString &path_h } -void PlaylistParser::Save(const SongList &songs, const QString &filename, const Playlist::Path path_type) const { +void PlaylistParser::Save(const SongList &songs, const QString &filename, const PlaylistSettingsPage::PathType path_type) const { - QFileInfo info(filename); + QFileInfo fileinfo(filename); // Find a parser that supports this file extension - ParserBase *parser = ParserForExtension(info.suffix()); + ParserBase *parser = ParserForExtension(Type_Save, fileinfo.suffix()); if (!parser) { qLog(Warning) << "Unknown filetype:" << filename; return; @@ -202,8 +214,14 @@ void PlaylistParser::Save(const SongList &songs, const QString &filename, const QFile file(filename); if (!file.open(QIODevice::WriteOnly)) return; - parser->Save(songs, &file, info.absolutePath(), path_type); + parser->Save(songs, &file, fileinfo.absolutePath(), path_type); file.close(); } + +bool PlaylistParser::ParserIsSupported(const Type type, ParserBase *parser) const { + + return ((type == Type_Load && parser->load_supported()) || (type == Type_Save && parser->save_supported())); + +} diff --git a/src/playlistparsers/playlistparser.h b/src/playlistparsers/playlistparser.h index 5e4534b6..37310607 100644 --- a/src/playlistparsers/playlistparser.h +++ b/src/playlistparsers/playlistparser.h @@ -21,6 +21,8 @@ #ifndef PLAYLISTPARSER_H #define PLAYLISTPARSER_H +#include "config.h" + #include #include #include @@ -28,9 +30,8 @@ #include #include -#include "config.h" #include "core/song.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" class QIODevice; class CollectionBackendInterface; @@ -42,28 +43,34 @@ class PlaylistParser : public QObject { public: explicit PlaylistParser(CollectionBackendInterface *collection = nullptr, QObject *parent = nullptr); + enum Type { + Type_Load, + Type_Save, + }; + static const int kMagicSize; - QStringList file_extensions() const; - QString filters() const; + QStringList file_extensions(const Type type) const; + QString filters(const Type type) const; - QStringList mime_types() const; + QStringList mime_types(const Type type) const; QString default_extension() const; QString default_filter() const; ParserBase *ParserForMagic(const QByteArray &data, const QString &mime_type = QString()) const; - ParserBase *ParserForExtension(const QString &suffix) const; - ParserBase *ParserForMimeType(const QString &mime) const; + ParserBase *ParserForExtension(const Type type, const QString &suffix) const; + ParserBase *ParserForMimeType(const Type type, const QString &mime) const; SongList LoadFromFile(const QString &filename) const; SongList LoadFromDevice(QIODevice *device, const QString &path_hint = QString(), const QDir &dir_hint = QDir()) const; - void Save(const SongList &songs, const QString &filename, const Playlist::Path) const; + void Save(const SongList &songs, const QString &filename, const PlaylistSettingsPage::PathType) const; -private: + private: + bool ParserIsSupported(const Type type, ParserBase *parser) const; static QString FilterForParser(const ParserBase *parser, QStringList *all_extensions = nullptr); -private: + private: QList parsers_; ParserBase *default_parser_; }; diff --git a/src/playlistparsers/plsparser.cpp b/src/playlistparsers/plsparser.cpp index a350d246..e76b0a52 100644 --- a/src/playlistparsers/plsparser.cpp +++ b/src/playlistparsers/plsparser.cpp @@ -30,7 +30,8 @@ #include #include "core/timeconstants.h" -#include "playlistparsers/parserbase.h" +#include "settings/playlistsettingspage.h" +#include "parserbase.h" #include "plsparser.h" class CollectionBackendInterface; @@ -86,7 +87,7 @@ SongList PLSParser::Load(QIODevice *device, const QString &playlist_path, const } -void PLSParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void PLSParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { QTextStream s(device); s << "[playlist]" << qt_endl; diff --git a/src/playlistparsers/plsparser.h b/src/playlistparsers/plsparser.h index 21241af4..db7856ba 100644 --- a/src/playlistparsers/plsparser.h +++ b/src/playlistparsers/plsparser.h @@ -21,16 +21,17 @@ #ifndef PLSPARSER_H #define PLSPARSER_H +#include "config.h" + #include #include #include #include #include -#include "config.h" #include "core/song.h" +#include "settings/playlistsettingspage.h" #include "parserbase.h" -#include "playlist/playlist.h" class QIODevice; class CollectionBackendInterface; @@ -44,11 +45,13 @@ class PLSParser : public ParserBase { QString name() const override { return "PLS"; } QStringList file_extensions() const override { return QStringList() << "pls"; } QString mime_type() const override { return "audio/x-scpls"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; }; #endif // PLSPARSER_H diff --git a/src/playlistparsers/wplparser.cpp b/src/playlistparsers/wplparser.cpp index 66379dde..9e15d733 100644 --- a/src/playlistparsers/wplparser.cpp +++ b/src/playlistparsers/wplparser.cpp @@ -18,6 +18,8 @@ * */ +#include "version.h" + #include #include #include @@ -28,8 +30,8 @@ #include #include "core/utilities.h" -#include "playlistparsers/xmlparser.h" -#include "version.h" +#include "settings/playlistsettingspage.h" +#include "xmlparser.h" #include "wplparser.h" class CollectionBackendInterface; @@ -93,7 +95,7 @@ void WplParser::ParseSeq(const QDir &dir, QXmlStreamReader *reader, SongList *so } -void WplParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void WplParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { QXmlStreamWriter writer(device); writer.setAutoFormatting(true); diff --git a/src/playlistparsers/wplparser.h b/src/playlistparsers/wplparser.h index d42db40e..222aba41 100644 --- a/src/playlistparsers/wplparser.h +++ b/src/playlistparsers/wplparser.h @@ -21,15 +21,16 @@ #ifndef WPLPARSER_H #define WPLPARSER_H +#include "config.h" + #include #include #include #include #include -#include "config.h" #include "core/song.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" #include "xmlparser.h" class QIODevice; @@ -47,11 +48,13 @@ class WplParser : public XMLParser { QString name() const override { return "WPL"; } QStringList file_extensions() const override { return QStringList() << "wpl"; } QString mime_type() const override { return "application/vnd.ms-wpl"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path, const QDir &dir, const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; private: void ParseSeq(const QDir &dir, QXmlStreamReader *reader, SongList *songs, const bool collection_search = true) const; diff --git a/src/playlistparsers/xmlparser.cpp b/src/playlistparsers/xmlparser.cpp index bddeaa7a..8d2e9c2b 100644 --- a/src/playlistparsers/xmlparser.cpp +++ b/src/playlistparsers/xmlparser.cpp @@ -18,11 +18,11 @@ * */ -#include "playlistparsers/parserbase.h" -#include "xmlparser.h" - #include +#include "parserbase.h" +#include "xmlparser.h" + class CollectionBackendInterface; XMLParser::XMLParser(CollectionBackendInterface *collection, QObject *parent) diff --git a/src/playlistparsers/xspfparser.cpp b/src/playlistparsers/xspfparser.cpp index 4b2ee7ee..f69a681d 100644 --- a/src/playlistparsers/xspfparser.cpp +++ b/src/playlistparsers/xspfparser.cpp @@ -33,8 +33,8 @@ #include "core/timeconstants.h" #include "core/utilities.h" -#include "playlist/playlist.h" -#include "playlistparsers/xmlparser.h" +#include "settings/playlistsettingspage.h" +#include "xmlparser.h" #include "xspfparser.h" class CollectionBackendInterface; @@ -137,7 +137,7 @@ return_song: } -void XSPFParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, Playlist::Path path_type) const { +void XSPFParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, const PlaylistSettingsPage::PathType path_type) const { QXmlStreamWriter writer(device); writer.setAutoFormatting(true); @@ -148,8 +148,8 @@ void XSPFParser::Save(const SongList &songs, QIODevice *device, const QDir &dir, writer.writeDefaultNamespace("http://xspf.org/ns/0/"); QSettings s; - s.beginGroup(Playlist::kSettingsGroup); - bool write_metadata = s.value(Playlist::kWriteMetadata, true).toBool(); + s.beginGroup(PlaylistSettingsPage::kSettingsGroup); + bool write_metadata = s.value("write_metadata", true).toBool(); s.endGroup(); StreamElement tracklist("trackList", &writer); diff --git a/src/playlistparsers/xspfparser.h b/src/playlistparsers/xspfparser.h index 6ed6bb72..51cb50ca 100644 --- a/src/playlistparsers/xspfparser.h +++ b/src/playlistparsers/xspfparser.h @@ -30,7 +30,7 @@ #include #include "core/song.h" -#include "playlist/playlist.h" +#include "settings/playlistsettingspage.h" #include "xmlparser.h" class QIODevice; @@ -45,11 +45,13 @@ class XSPFParser : public XMLParser { QString name() const override { return "XSPF"; } QStringList file_extensions() const override { return QStringList() << "xspf"; } + bool load_supported() const override { return true; } + bool save_supported() const override { return true; } bool TryMagic(const QByteArray &data) const override; SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override; - void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), const PlaylistSettingsPage::PathType path_type = PlaylistSettingsPage::PathType_Automatic) const override; private: Song ParseTrack(QXmlStreamReader *reader, const QDir &dir, const bool collection_search) const; diff --git a/src/settings/playlistsettingspage.cpp b/src/settings/playlistsettingspage.cpp index 7db994cf..f2d9ca7f 100644 --- a/src/settings/playlistsettingspage.cpp +++ b/src/settings/playlistsettingspage.cpp @@ -72,23 +72,23 @@ void PlaylistSettingsPage::Load() { ui_->checkbox_playlist_clear->setChecked(s.value("playlist_clear", true).toBool()); ui_->checkbox_auto_sort->setChecked(s.value("auto_sort", false).toBool()); - Playlist::Path path = Playlist::Path(s.value(Playlist::kPathType, Playlist::Path_Automatic).toInt()); - switch (path) { - case Playlist::Path_Automatic: + PathType path_type = PathType(s.value("path_type", PathType_Automatic).toInt()); + switch (path_type) { + case PathType_Automatic: ui_->radiobutton_automaticpath->setChecked(true); break; - case Playlist::Path_Absolute: + case PathType_Absolute: ui_->radiobutton_absolutepath->setChecked(true); break; - case Playlist::Path_Relative: + case PathType_Relative: ui_->radiobutton_relativepath->setChecked(true); break; - case Playlist::Path_Ask_User: + case PathType_Ask_User: ui_->radiobutton_askpath->setChecked(true); } ui_->checkbox_editmetadatainline->setChecked(s.value("editmetadatainline", false).toBool()); - ui_->checkbox_writemetadata->setChecked(s.value(Playlist::kWriteMetadata, false).toBool()); + ui_->checkbox_writemetadata->setChecked(s.value("write_metadata", false).toBool()); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) ui_->checkbox_delete_files->setChecked(s.value("delete_files", false).toBool()); @@ -107,18 +107,18 @@ void PlaylistSettingsPage::Load() { void PlaylistSettingsPage::Save() { - Playlist::Path path = Playlist::Path_Automatic; + PathType path_type = PathType_Automatic; if (ui_->radiobutton_automaticpath->isChecked()) { - path = Playlist::Path_Automatic; + path_type = PathType_Automatic; } else if (ui_->radiobutton_absolutepath->isChecked()) { - path = Playlist::Path_Absolute; + path_type = PathType_Absolute; } else if (ui_->radiobutton_relativepath->isChecked()) { - path = Playlist::Path_Relative; + path_type = PathType_Relative; } else if (ui_->radiobutton_askpath->isChecked()) { - path = Playlist::Path_Ask_User; + path_type = PathType_Ask_User; } QSettings s; @@ -132,9 +132,9 @@ void PlaylistSettingsPage::Save() { s.setValue("select_track", ui_->checkbox_select_track->isChecked()); s.setValue("show_toolbar", ui_->checkbox_show_toolbar->isChecked()); s.setValue("playlist_clear", ui_->checkbox_playlist_clear->isChecked()); - s.setValue(Playlist::kPathType, static_cast(path)); + s.setValue("path_type", static_cast(path_type)); s.setValue("editmetadatainline", ui_->checkbox_editmetadatainline->isChecked()); - s.setValue(Playlist::kWriteMetadata, ui_->checkbox_writemetadata->isChecked()); + s.setValue("write_metadata", ui_->checkbox_writemetadata->isChecked()); s.setValue("delete_files", ui_->checkbox_delete_files->isChecked()); s.setValue("auto_sort", ui_->checkbox_auto_sort->isChecked()); s.endGroup(); diff --git a/src/settings/playlistsettingspage.h b/src/settings/playlistsettingspage.h index 013ac714..58d9638b 100644 --- a/src/settings/playlistsettingspage.h +++ b/src/settings/playlistsettingspage.h @@ -38,8 +38,16 @@ class PlaylistSettingsPage : public SettingsPage { public: explicit PlaylistSettingsPage(SettingsDialog *dialog, QWidget *parent = nullptr); ~PlaylistSettingsPage() override; + static const char *kSettingsGroup; + enum PathType { + PathType_Automatic = 0, // Automatically select path type + PathType_Absolute, // Always use absolute paths + PathType_Relative, // Always use relative paths + PathType_Ask_User, // Only used in preferences: to ask user which of the previous values he wants to use. + }; + void Load() override; void Save() override;