Use a save dialog option instead of quick change menu.

This is less confusing IMO. The dialog will shown up only if users decided to in the preferences, so that will not bother users who don't need this.
This reuses lot of things from Alan contribution from #4484
This commit is contained in:
Arnaud Bienner 2014-10-07 00:23:28 +02:00
parent 54d76506a7
commit 78804b12c6
26 changed files with 121 additions and 92 deletions

View File

@ -138,6 +138,8 @@ class Playlist : public QAbstractListModel {
Path_Automatic = 0, // Automatically select path type Path_Automatic = 0, // Automatically select path type
Path_Absolute, // Always use absolute paths Path_Absolute, // Always use absolute paths
Path_Relative, // Always use relative 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.
}; };
static const char* kCddaMimeType; static const char* kCddaMimeType;

View File

@ -18,6 +18,7 @@
#include "playlistbackend.h" #include "playlistbackend.h"
#include "playlistcontainer.h" #include "playlistcontainer.h"
#include "playlistmanager.h" #include "playlistmanager.h"
#include "playlistsaveoptionsdialog.h"
#include "playlistview.h" #include "playlistview.h"
#include "core/application.h" #include "core/application.h"
#include "core/logging.h" #include "core/logging.h"
@ -172,9 +173,10 @@ void PlaylistManager::Load(const QString& filename) {
playlist->InsertUrls(urls << QUrl::fromLocalFile(filename)); playlist->InsertUrls(urls << QUrl::fromLocalFile(filename));
} }
void PlaylistManager::Save(int id, const QString& filename) { void PlaylistManager::Save(int id, const QString& filename,
Playlist::Path path_type) {
if (playlists_.contains(id)) { if (playlists_.contains(id)) {
parser_->Save(playlist(id)->GetAllSongs(), filename); parser_->Save(playlist(id)->GetAllSongs(), filename, path_type);
} else { } else {
// Playlist is not in the playlist manager: probably save action was // Playlist is not in the playlist manager: probably save action was
// triggered // triggered
@ -184,16 +186,18 @@ void PlaylistManager::Save(int id, const QString& filename) {
watcher->setFuture(future); watcher->setFuture(future);
NewClosure(watcher, SIGNAL(finished()), this, NewClosure(watcher, SIGNAL(finished()), this,
SLOT(ItemsLoadedForSavePlaylist(QFutureWatcher<Song>*, QString)), SLOT(ItemsLoadedForSavePlaylist(QFutureWatcher<Song>*, QString,
Playlist::Path)),
watcher, filename); watcher, filename);
} }
} }
void PlaylistManager::ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher, void PlaylistManager::ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher,
const QString& filename) { const QString& filename,
Playlist::Path path_type) {
SongList song_list = watcher->future().results(); SongList song_list = watcher->future().results();
parser_->Save(song_list, filename); parser_->Save(song_list, filename, path_type);
} }
void PlaylistManager::SaveWithUI(int id, const QString& suggested_filename) { void PlaylistManager::SaveWithUI(int id, const QString& suggested_filename) {
@ -230,10 +234,23 @@ void PlaylistManager::SaveWithUI(int id, const QString& suggested_filename) {
return; return;
} }
QSettings s;
s.beginGroup(Playlist::kSettingsGroup);
int p = s.value(Playlist::kPathType, Playlist::Path_Automatic).toInt();
Playlist::Path path = static_cast<Playlist::Path>(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_playlist", filename);
settings.endGroup(); settings.endGroup();
Save(id == -1 ? current_id() : id, filename); Save(id == -1 ? current_id() : id, filename, path);
} }
void PlaylistManager::Rename(int id, const QString& new_name) { void PlaylistManager::Rename(int id, const QString& new_name) {

View File

@ -76,7 +76,7 @@ class PlaylistManagerInterface : public QObject {
virtual void New(const QString& name, const SongList& songs = SongList(), virtual void New(const QString& name, const SongList& songs = SongList(),
const QString& special_type = QString()) = 0; const QString& special_type = QString()) = 0;
virtual void Load(const QString& filename) = 0; virtual void Load(const QString& filename) = 0;
virtual void Save(int id, const QString& filename) = 0; virtual void Save(int id, const QString& filename, Playlist::Path path_type) = 0;
virtual void Rename(int id, const QString& new_name) = 0; virtual void Rename(int id, const QString& new_name) = 0;
virtual void Delete(int id) = 0; virtual void Delete(int id) = 0;
virtual bool Close(int id) = 0; virtual bool Close(int id) = 0;
@ -181,7 +181,7 @@ class PlaylistManager : public PlaylistManagerInterface {
void New(const QString& name, const SongList& songs = SongList(), void New(const QString& name, const SongList& songs = SongList(),
const QString& special_type = QString()); const QString& special_type = QString());
void Load(const QString& filename); void Load(const QString& filename);
void Save(int id, const QString& filename); void Save(int id, const QString& filename, Playlist::Path path_type);
// Display a file dialog to let user choose a file before saving the file // Display a file dialog to let user choose a file before saving the file
void SaveWithUI(int id, const QString& suggested_filename); void SaveWithUI(int id, const QString& suggested_filename);
void Rename(int id, const QString& new_name); void Rename(int id, const QString& new_name);
@ -232,7 +232,8 @@ class PlaylistManager : public PlaylistManagerInterface {
void UpdateSummaryText(); void UpdateSummaryText();
void SongsDiscovered(const SongList& songs); void SongsDiscovered(const SongList& songs);
void ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher, void ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher,
const QString& filename); const QString& filename,
Playlist::Path path_type);
private: private:
Playlist* AddPlaylist(int id, const QString& name, Playlist* AddPlaylist(int id, const QString& name,

View File

@ -1,5 +1,5 @@
/* This file is part of Clementine. /* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com> Copyright 2014, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -29,44 +29,24 @@ PlaylistSaveOptionsDialog::PlaylistSaveOptionsDialog(QWidget* parent)
: QDialog(parent), ui(new Ui::PlaylistSaveOptionsDialog) { : QDialog(parent), ui(new Ui::PlaylistSaveOptionsDialog) {
ui->setupUi(this); ui->setupUi(this);
ui->filePaths->addItem(tr("Automatic"), PlaylistSaveOptions::Paths_Automatic); ui->filePaths->addItem(tr("Automatic"), Playlist::Path_Automatic);
ui->filePaths->addItem(tr("Relative"), PlaylistSaveOptions::Paths_Relative); ui->filePaths->addItem(tr("Relative"), Playlist::Path_Relative);
ui->filePaths->addItem(tr("Absolute"), PlaylistSaveOptions::Paths_Absolute); ui->filePaths->addItem(tr("Absolute"), Playlist::Path_Absolute);
ui->pathSeparators->addItem(tr("Automatic"),
PlaylistSaveOptions::Separators_Automatic);
ui->pathSeparators->addItem(tr("Windows-style") + " (\\)",
PlaylistSaveOptions::Separators_Windows);
ui->pathSeparators->addItem(tr("Unix-style") + " (/)",
PlaylistSaveOptions::Separators_Unix);
QSettings s;
s.beginGroup(kSettingsGroup);
ui->filePaths->setCurrentIndex(ui->filePaths->findData(
s.value("file_paths", PlaylistSaveOptions::Paths_Automatic)));
ui->pathSeparators->setCurrentIndex(ui->pathSeparators->findData(
s.value("path_separators", PlaylistSaveOptions::Separators_Automatic)));
} }
PlaylistSaveOptionsDialog::~PlaylistSaveOptionsDialog() { delete ui; } PlaylistSaveOptionsDialog::~PlaylistSaveOptionsDialog() { delete ui; }
void PlaylistSaveOptionsDialog::accept() { void PlaylistSaveOptionsDialog::accept() {
QSettings s; if (ui->remember_user_choice->isChecked()) {
s.beginGroup(kSettingsGroup); QSettings s;
s.setValue("file_paths", s.beginGroup(Playlist::kSettingsGroup);
ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt()); s.setValue(Playlist::kPathType,
s.setValue( ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
"path_separators", }
ui->pathSeparators->itemData(ui->pathSeparators->currentIndex()).toInt());
QDialog::accept(); QDialog::accept();
} }
PlaylistSaveOptions PlaylistSaveOptionsDialog::options() const { Playlist::Path PlaylistSaveOptionsDialog::path_type() const {
PlaylistSaveOptions o; return static_cast<Playlist::Path>(ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
o.filePathStyle = static_cast<PlaylistSaveOptions::FilePathStyle>(
ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
o.pathSeparatorStyle = static_cast<PlaylistSaveOptions::PathSeparatorStyle>(
ui->pathSeparators->itemData(ui->pathSeparators->currentIndex()).toInt());
return o;
} }

View File

@ -1,5 +1,5 @@
/* This file is part of Clementine. /* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com> Copyright 2014, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
#include <QDialog> #include <QDialog>
struct PlaylistSaveOptions; #include "playlist.h"
namespace Ui { namespace Ui {
class PlaylistSaveOptionsDialog; class PlaylistSaveOptionsDialog;
@ -34,7 +34,7 @@ class PlaylistSaveOptionsDialog : public QDialog {
~PlaylistSaveOptionsDialog(); ~PlaylistSaveOptionsDialog();
void accept(); void accept();
PlaylistSaveOptions options() const; Playlist::Path path_type() const;
private: private:
static const char* kSettingsGroup; static const char* kSettingsGroup;

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>348</width> <width>348</width>
<height>114</height> <height>116</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,7 +15,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -23,18 +23,25 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Path separators</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="filePaths"/> <widget class="QComboBox" name="filePaths"/>
</item> </item>
<item row="1" column="1"> </layout>
<widget class="QComboBox" name="pathSeparators"/> </item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="remember_user_choice">
<property name="toolTip">
<string>This can be changed later through the preferences</string>
</property>
<property name="text">
<string>Remember my choice</string>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -50,13 +50,14 @@ SongList AsxIniParser::Load(QIODevice* device, const QString& playlist_path,
} }
void AsxIniParser::Save(const SongList& songs, QIODevice* device, void AsxIniParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir,
Playlist::Path path_type) const {
QTextStream s(device); QTextStream s(device);
s << "[Reference]" << endl; s << "[Reference]" << endl;
int n = 1; int n = 1;
for (const Song& song : songs) { for (const Song& song : songs) {
s << "Ref" << n << "=" << URLOrRelativeFilename(song.url(), dir) << endl; s << "Ref" << n << "=" << URLOrFilename(song.url(), dir, path_type) << endl;
++n; ++n;
} }
} }

View File

@ -34,7 +34,8 @@ class AsxIniParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
}; };
#endif // ASXINIPARSER_H #endif // ASXINIPARSER_H

View File

@ -118,7 +118,7 @@ return_song:
} }
void ASXParser::Save(const SongList& songs, QIODevice* device, void ASXParser::Save(const SongList& songs, QIODevice* device,
const QDir&) const { const QDir&, Playlist::Path path_type) const {
QXmlStreamWriter writer(device); QXmlStreamWriter writer(device);
writer.setAutoFormatting(true); writer.setAutoFormatting(true);
writer.setAutoFormattingIndent(2); writer.setAutoFormattingIndent(2);

View File

@ -34,7 +34,8 @@ class ASXParser : public XMLParser {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
private: private:
Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const; Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const;

View File

@ -352,7 +352,8 @@ qint64 CueParser::IndexToMarker(const QString& index) const {
} }
void CueParser::Save(const SongList& songs, QIODevice* device, void CueParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir,
Playlist::Path path_type) const {
// TODO // TODO
} }

View File

@ -54,7 +54,8 @@ class CueParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
private: private:
// A single TRACK entry in .cue file. // A single TRACK entry in .cue file.

View File

@ -105,7 +105,8 @@ bool M3UParser::ParseMetadata(const QString& line,
} }
void M3UParser::Save(const SongList& songs, QIODevice* device, void M3UParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir,
Playlist::Path path_type) const {
device->write("#EXTM3U\n"); device->write("#EXTM3U\n");
QSettings s; QSettings s;
@ -124,7 +125,7 @@ void M3UParser::Save(const SongList& songs, QIODevice* device,
.arg(song.title()); .arg(song.title());
device->write(meta.toUtf8()); device->write(meta.toUtf8());
} }
device->write(URLOrRelativeFilename(song.url(), dir).toUtf8()); device->write(URLOrFilename(song.url(), dir, path_type).toUtf8());
device->write("\n"); device->write("\n");
} }
} }

View File

@ -42,7 +42,8 @@ class M3UParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
private: private:
enum M3UType { enum M3UType {

View File

@ -86,22 +86,17 @@ Song ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning,
return song; return song;
} }
QString ParserBase::URLOrRelativeFilename(const QUrl& url, QString ParserBase::URLOrFilename(const QUrl& url,
const QDir& dir) const { const QDir& dir,
Playlist::Path path_type) const {
if (url.scheme() != "file") return url.toString(); if (url.scheme() != "file") return url.toString();
QSettings s;
s.beginGroup(Playlist::kSettingsGroup);
int p = s.value(Playlist::kPathType, Playlist::Path_Automatic).toInt();
const Playlist::Path path = static_cast<Playlist::Path>(p);
s.endGroup();
const QString filename = url.toLocalFile(); const QString filename = url.toLocalFile();
if (path != Playlist::Path_Absolute && QDir::isAbsolutePath(filename)) { if (path_type != Playlist::Path_Absolute && QDir::isAbsolutePath(filename)) {
const QString relative = dir.relativeFilePath(filename); const QString relative = dir.relativeFilePath(filename);
if (!relative.startsWith("../") || path == Playlist::Path_Relative) if (!relative.startsWith("../") || path_type == Playlist::Path_Relative)
return relative; return relative;
} }
return filename; return filename;

View File

@ -22,6 +22,7 @@
#include <QDir> #include <QDir>
#include "core/song.h" #include "core/song.h"
#include "playlist/playlist.h"
class LibraryBackendInterface; class LibraryBackendInterface;
@ -51,7 +52,8 @@ class ParserBase : public QObject {
virtual SongList Load(QIODevice* device, const QString& playlist_path = "", virtual SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const = 0; const QDir& dir = QDir()) const = 0;
virtual void Save(const SongList& songs, QIODevice* device, virtual void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const = 0; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const = 0;
protected: protected:
// Loads a song. If filename_or_url is a URL (with a scheme other than // Loads a song. If filename_or_url is a URL (with a scheme other than
@ -65,10 +67,12 @@ class ParserBase : public QObject {
void LoadSong(const QString& filename_or_url, qint64 beginning, void LoadSong(const QString& filename_or_url, qint64 beginning,
const QDir& dir, Song* song) const; const QDir& dir, Song* song) const;
// If the URL is a file:// URL then returns its path relative to the // If the URL is a file:// URL then returns its path, absolute or relative to
// directory. Otherwise returns the URL as is. // the directory depending on the path_type option.
// Otherwise returns the URL as is.
// This function should always be used when saving a playlist. // This function should always be used when saving a playlist.
QString URLOrRelativeFilename(const QUrl& url, const QDir& dir) const; QString URLOrFilename(const QUrl& url, const QDir& dir,
Playlist::Path path_type) const;
private: private:
LibraryBackendInterface* library_; LibraryBackendInterface* library_;

View File

@ -131,7 +131,8 @@ SongList PlaylistParser::LoadFromDevice(QIODevice* device,
} }
void PlaylistParser::Save(const SongList& songs, void PlaylistParser::Save(const SongList& songs,
const QString& filename) const { const QString& filename,
Playlist::Path path_type) const {
QFileInfo info(filename); QFileInfo info(filename);
// Find a parser that supports this file extension // Find a parser that supports this file extension
@ -145,5 +146,5 @@ void PlaylistParser::Save(const SongList& songs,
QFile file(filename); QFile file(filename);
file.open(QIODevice::WriteOnly); file.open(QIODevice::WriteOnly);
return parser->Save(songs, &file, info.absolutePath()); return parser->Save(songs, &file, info.absolutePath(), path_type);
} }

View File

@ -22,6 +22,7 @@
#include <QObject> #include <QObject>
#include "core/song.h" #include "core/song.h"
#include "playlist/playlist.h"
class ParserBase; class ParserBase;
class LibraryBackendInterface; class LibraryBackendInterface;
@ -48,7 +49,7 @@ class PlaylistParser : public QObject {
SongList LoadFromDevice(QIODevice* device, SongList LoadFromDevice(QIODevice* device,
const QString& path_hint = QString(), const QString& path_hint = QString(),
const QDir& dir_hint = QDir()) const; const QDir& dir_hint = QDir()) const;
void Save(const SongList& songs, const QString& filename) const; void Save(const SongList& songs, const QString& filename, Playlist::Path) const;
private: private:
QString FilterForParser(const ParserBase* parser, QString FilterForParser(const ParserBase* parser,

View File

@ -62,7 +62,7 @@ SongList PLSParser::Load(QIODevice* device, const QString& playlist_path,
} }
void PLSParser::Save(const SongList& songs, QIODevice* device, void PLSParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir, Playlist::Path path_type) const {
QTextStream s(device); QTextStream s(device);
s << "[playlist]" << endl; s << "[playlist]" << endl;
s << "Version=2" << endl; s << "Version=2" << endl;
@ -70,7 +70,7 @@ void PLSParser::Save(const SongList& songs, QIODevice* device,
int n = 1; int n = 1;
for (const Song& song : songs) { for (const Song& song : songs) {
s << "File" << n << "=" << URLOrRelativeFilename(song.url(), dir) << endl; s << "File" << n << "=" << URLOrFilename(song.url(), dir, path_type) << endl;
s << "Title" << n << "=" << song.title() << endl; s << "Title" << n << "=" << song.title() << endl;
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl; s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
++n; ++n;

View File

@ -34,7 +34,8 @@ class PLSParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
}; };
#endif // PLSPARSER_H #endif // PLSPARSER_H

View File

@ -77,7 +77,7 @@ void WplParser::ParseSeq(const QDir& dir, QXmlStreamReader* reader,
} }
void WplParser::Save(const SongList& songs, QIODevice* device, void WplParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir, Playlist::Path path_type) const {
QXmlStreamWriter writer(device); QXmlStreamWriter writer(device);
writer.setAutoFormatting(true); writer.setAutoFormatting(true);
writer.setAutoFormattingIndent(2); writer.setAutoFormattingIndent(2);
@ -98,7 +98,7 @@ void WplParser::Save(const SongList& songs, QIODevice* device,
StreamElement seq("seq", &writer); StreamElement seq("seq", &writer);
for (const Song& song : songs) { for (const Song& song : songs) {
writer.writeStartElement("media"); writer.writeStartElement("media");
writer.writeAttribute("src", URLOrRelativeFilename(song.url(), dir)); writer.writeAttribute("src", URLOrFilename(song.url(), dir, path_type));
writer.writeEndElement(); writer.writeEndElement();
} }
} }

View File

@ -32,7 +32,8 @@ class WplParser : public XMLParser {
SongList Load(QIODevice* device, const QString& playlist_path, SongList Load(QIODevice* device, const QString& playlist_path,
const QDir& dir) const; const QDir& dir) const;
void Save(const SongList& songs, QIODevice* device, const QDir& dir) const; void Save(const SongList& songs, QIODevice* device, const QDir& dir,
Playlist::Path path_type = Playlist::Path_Automatic) const;
private: private:
void ParseSeq(const QDir& dir, QXmlStreamReader* reader, void ParseSeq(const QDir& dir, QXmlStreamReader* reader,

View File

@ -103,7 +103,7 @@ return_song:
} }
void XSPFParser::Save(const SongList& songs, QIODevice* device, void XSPFParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir) const { const QDir& dir, Playlist::Path path_type) const {
QFileInfo file; QFileInfo file;
QXmlStreamWriter writer(device); QXmlStreamWriter writer(device);
writer.setAutoFormatting(true); writer.setAutoFormatting(true);
@ -120,7 +120,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device,
StreamElement tracklist("trackList", &writer); StreamElement tracklist("trackList", &writer);
for (const Song& song : songs) { for (const Song& song : songs) {
QString filename_or_url = URLOrRelativeFilename(song.url(), dir).toUtf8(); QString filename_or_url = URLOrFilename(song.url(), dir, path_type).toUtf8();
StreamElement track("track", &writer); StreamElement track("track", &writer);
writer.writeTextElement("location", filename_or_url); writer.writeTextElement("location", filename_or_url);
@ -154,7 +154,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device,
// playlist. // playlist.
QUrl url = QUrl(art_filename); QUrl url = QUrl(art_filename);
url.setScheme("file"); // Need to explicitly set this. url.setScheme("file"); // Need to explicitly set this.
art_filename = URLOrRelativeFilename(url, dir).toUtf8(); art_filename = URLOrFilename(url, dir, path_type).toUtf8();
} else { } else {
// Just use whatever URL was in the Song. // Just use whatever URL was in the Song.
art_filename = art; art_filename = art;

View File

@ -39,7 +39,8 @@ class XSPFParser : public XMLParser {
SongList Load(QIODevice* device, const QString& playlist_path = "", SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const; const QDir& dir = QDir()) const;
void Save(const SongList& songs, QIODevice* device, void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir()) const; const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const;
private: private:
Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const; Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const;

View File

@ -146,6 +146,8 @@ void BehaviourSettingsPage::Load() {
case Playlist::Path_Relative: case Playlist::Path_Relative:
ui_->b_relative_path->setChecked(true); ui_->b_relative_path->setChecked(true);
break; break;
case Playlist::Path_Ask_User:
ui_->b_ask_path->setChecked(true);
} }
ui_->b_write_metadata->setChecked( ui_->b_write_metadata->setChecked(
s.value(Playlist::kWriteMetadata, true).toBool()); s.value(Playlist::kWriteMetadata, true).toBool());
@ -185,6 +187,8 @@ void BehaviourSettingsPage::Save() {
path = Playlist::Path_Absolute; path = Playlist::Path_Absolute;
} else if (ui_->b_relative_path->isChecked()) { } else if (ui_->b_relative_path->isChecked()) {
path = Playlist::Path_Relative; path = Playlist::Path_Relative;
} else if (ui_->b_ask_path->isChecked()) {
path = Playlist::Path_Ask_User;
} }
s.beginGroup(MainWindow::kSettingsGroup); s.beginGroup(MainWindow::kSettingsGroup);

View File

@ -265,6 +265,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QRadioButton" name="b_ask_path">
<property name="text">
<string>Ask when saving</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_7"> <spacer name="verticalSpacer_7">
<property name="orientation"> <property name="orientation">