Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

playlist export: add missing file extension #4531

Merged
merged 4 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 44 additions & 35 deletions src/library/baseplaylistfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,17 @@
#include "moc_baseplaylistfeature.cpp"
#include "track/track.h"
#include "util/assert.h"
#include "util/file.h"
#include "widget/wlibrary.h"
#include "widget/wlibrarytextbrowser.h"

namespace {

const ConfigKey kConfigKeyLastImportExportPlaylistDirectory(
"[Library]", "LastImportExportPlaylistDirectory");

} // anonymous namespace

BasePlaylistFeature::BasePlaylistFeature(
Library* pLibrary,
UserSettingsPointer pConfig,
Expand Down Expand Up @@ -350,17 +358,18 @@ void BasePlaylistFeature::slotDeletePlaylist() {

void BasePlaylistFeature::slotImportPlaylist() {
//qDebug() << "slotImportPlaylist() row:" << m_lastRightClickedIndex.data();
QString playlist_file = getPlaylistFile();
if (playlist_file.isEmpty()) {
const QString playlistFile = getPlaylistFile();
if (playlistFile.isEmpty()) {
return;
}

// Update the import/export playlist directory
QFileInfo fileName(playlist_file);
m_pConfig->set(ConfigKey("[Library]", "LastImportExportPlaylistDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(playlistFile);
fileDirectory.truncate(playlistFile.lastIndexOf(QDir::separator()));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this always truncates at position 0, see https://bugs.launchpad.net/bugs/1964508

Native separator is \ on Windows and maybe Qt has already converted the path to use /? In that case lastIndexOf("\") would return -1 which is equivalent to passing 0 to truncate
https://doc.qt.io/qt-5/qstring.html#truncate
It is not recommended to use QDir::separator() for constructing paths, but appearantly it also creates issues when computing paths
https://doc.qt.io/qt-5/qdir.html#separator

m_pConfig->set(kConfigKeyLastImportExportPlaylistDirectory,
ConfigValue(fileDirectory));

slotImportPlaylistFile(playlist_file);
slotImportPlaylistFile(playlistFile);
activateChild(m_lastRightClickedIndex);
}

Expand Down Expand Up @@ -396,24 +405,24 @@ void BasePlaylistFeature::slotImportPlaylistFile(const QString& playlist_file) {

void BasePlaylistFeature::slotCreateImportPlaylist() {
// Get file to read
QStringList playlist_files = LibraryFeature::getPlaylistFiles();
if (playlist_files.isEmpty()) {
const QStringList playlistFiles = LibraryFeature::getPlaylistFiles();
if (playlistFiles.isEmpty()) {
return;
}

// Set last import directory
QFileInfo fileName(playlist_files.first());
m_pConfig->set(ConfigKey("[Library]", "LastImportExportPlaylistDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(playlistFiles.first());
fileDirectory.truncate(playlistFiles.first().lastIndexOf(QDir::separator()));
m_pConfig->set(kConfigKeyLastImportExportPlaylistDirectory,
ConfigValue(fileDirectory));

int lastPlaylistId = -1;

// For each selected element create a different playlist.
for (const QString& playlistFile : playlist_files) {
fileName = QFileInfo(playlistFile);

for (const QString& playlistFile : playlistFiles) {
const QFileInfo fileInfo(playlistFile);
// Get a valid name
QString baseName = fileName.baseName();
const QString baseName = fileInfo.baseName();
QString name;

bool validNameGiven = false;
Expand Down Expand Up @@ -455,28 +464,28 @@ void BasePlaylistFeature::slotExportPlaylist() {
qDebug() << "Export playlist" << playlistName;

QString lastPlaylistDirectory = m_pConfig->getValue(
ConfigKey("[Library]", "LastImportExportPlaylistDirectory"),
kConfigKeyLastImportExportPlaylistDirectory,
QStandardPaths::writableLocation(QStandardPaths::MusicLocation));

// Open a dialog to let the user choose the file location for playlist export.
// The location is set to the last used directory for import/export and the file
// name to the playlist name.
QString filefilter = tr("M3U Playlist (*.m3u)");
QString file_location = QFileDialog::getSaveFileName(
nullptr,
const QString fileLocation = getFilePathWithVerifiedExtensionFromFileDialog(
tr("Export Playlist"),
lastPlaylistDirectory.append("/").append(playlistName),
lastPlaylistDirectory.append("/").append(playlistName).append(".m3u"),
tr("M3U Playlist (*.m3u);;M3U8 Playlist (*.m3u8);;"
"PLS Playlist (*.pls);;Text CSV (*.csv);;Readable Text (*.txt)"),
&filefilter);
// Exit method if user cancelled the open dialog.
if (file_location.isNull() || file_location.isEmpty()) {
tr("M3U Playlist (*.m3u)"));
// Exit method if the file name is empty because the user cancelled the save dialog.
if (fileLocation.isEmpty()) {
return;
}
QFileInfo fileName(file_location);

// Update the import/export playlist directory
m_pConfig->set(ConfigKey("[Library]", "LastImportExportPlaylistDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(fileLocation);
fileDirectory.truncate(fileLocation.lastIndexOf(QDir::separator()));
m_pConfig->set(kConfigKeyLastImportExportPlaylistDirectory,
ConfigValue(fileDirectory));

// The user has picked a new directory via a file dialog. This means the
// system sandboxer (if we are sandboxed) has granted us permission to this
Expand All @@ -498,25 +507,25 @@ void BasePlaylistFeature::slotExportPlaylist() {
bool useRelativePath = m_pConfig->getValue<bool>(
ConfigKey("[Library]", "UseRelativePathOnExport"));

if (file_location.endsWith(".csv", Qt::CaseInsensitive)) {
ParserCsv::writeCSVFile(file_location, pPlaylistTableModel.data(), useRelativePath);
} else if (file_location.endsWith(".txt", Qt::CaseInsensitive)) {
if (fileLocation.endsWith(".csv", Qt::CaseInsensitive)) {
ParserCsv::writeCSVFile(fileLocation, pPlaylistTableModel.data(), useRelativePath);
} else if (fileLocation.endsWith(".txt", Qt::CaseInsensitive)) {
if (m_playlistDao.getHiddenType(pPlaylistTableModel->getPlaylist()) == PlaylistDAO::PLHT_SET_LOG) {
ParserCsv::writeReadableTextFile(file_location, pPlaylistTableModel.data(), true);
ParserCsv::writeReadableTextFile(fileLocation, pPlaylistTableModel.data(), true);
} else {
ParserCsv::writeReadableTextFile(file_location, pPlaylistTableModel.data(), false);
ParserCsv::writeReadableTextFile(fileLocation, pPlaylistTableModel.data(), false);
}
} else {
// Create and populate a list of files of the playlist
QList<QString> playlist_items;
QList<QString> playlistItems;
int rows = pPlaylistTableModel->rowCount();
for (int i = 0; i < rows; ++i) {
QModelIndex index = pPlaylistTableModel->index(i, 0);
playlist_items << pPlaylistTableModel->getTrackLocation(index);
playlistItems << pPlaylistTableModel->getTrackLocation(index);
}
exportPlaylistItemsIntoFile(
file_location,
playlist_items,
fileLocation,
playlistItems,
useRelativePath);
}
}
Expand Down
89 changes: 49 additions & 40 deletions src/library/crate/cratefeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "sources/soundsourceproxy.h"
#include "track/track.h"
#include "util/dnd.h"
#include "util/file.h"
#include "widget/wlibrary.h"
#include "widget/wlibrarysidebar.h"
#include "widget/wlibrarytextbrowser.h"
Expand All @@ -36,6 +37,9 @@ QString formatLabel(
crateSummary.getTrackDurationText());
}

const ConfigKey kConfigKeyLastImportExportCrateDirectoryKey(
"[Library]", "LastImportExportCrateDirectory");

} // anonymous namespace

CrateFeature::CrateFeature(Library* pLibrary,
Expand Down Expand Up @@ -563,36 +567,37 @@ QModelIndex CrateFeature::indexFromCrateId(CrateId crateId) const {
void CrateFeature::slotImportPlaylist() {
//qDebug() << "slotImportPlaylist() row:" ; //<< m_lastRightClickedIndex.data();

QString playlist_file = getPlaylistFile();
if (playlist_file.isEmpty()) {
QString playlistFile = getPlaylistFile();
if (playlistFile.isEmpty()) {
return;
}

// Update the import/export crate directory
QFileInfo fileName(playlist_file);
m_pConfig->set(ConfigKey("[Library]","LastImportExportCrateDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(playlistFile);
fileDirectory.truncate(playlistFile.lastIndexOf(QDir::separator()));
m_pConfig->set(kConfigKeyLastImportExportCrateDirectoryKey,
ConfigValue(fileDirectory));

slotImportPlaylistFile(playlist_file);
slotImportPlaylistFile(playlistFile);
activateChild(m_lastRightClickedIndex);
}

void CrateFeature::slotImportPlaylistFile(const QString& playlist_file) {
void CrateFeature::slotImportPlaylistFile(const QString& playlistFile) {
// The user has picked a new directory via a file dialog. This means the
// system sandboxer (if we are sandboxed) has granted us permission to this
// folder. We don't need access to this file on a regular basis so we do not
// register a security bookmark.
// TODO(XXX): Parsing a list of track locations from a playlist file
// is a general task and should be implemented separately.
QList<QString> entries;
if (playlist_file.endsWith(".m3u", Qt::CaseInsensitive) ||
playlist_file.endsWith(".m3u8", Qt::CaseInsensitive)) {
if (playlistFile.endsWith(".m3u", Qt::CaseInsensitive) ||
playlistFile.endsWith(".m3u8", Qt::CaseInsensitive)) {
// .m3u8 is Utf8 representation of an m3u playlist
entries = ParserM3u().parse(playlist_file);
} else if (playlist_file.endsWith(".pls", Qt::CaseInsensitive)) {
entries = ParserPls().parse(playlist_file);
} else if (playlist_file.endsWith(".csv", Qt::CaseInsensitive)) {
entries = ParserCsv().parse(playlist_file);
entries = ParserM3u().parse(playlistFile);
} else if (playlistFile.endsWith(".pls", Qt::CaseInsensitive)) {
entries = ParserPls().parse(playlistFile);
} else if (playlistFile.endsWith(".csv", Qt::CaseInsensitive)) {
entries = ParserCsv().parse(playlistFile);
} else {
return;
}
Expand All @@ -602,27 +607,27 @@ void CrateFeature::slotImportPlaylistFile(const QString& playlist_file) {
void CrateFeature::slotCreateImportCrate() {

// Get file to read
QStringList playlist_files = LibraryFeature::getPlaylistFiles();
if (playlist_files.isEmpty()) {
QStringList playlistFiles = LibraryFeature::getPlaylistFiles();
if (playlistFiles.isEmpty()) {
return;
}


// Set last import directory
QFileInfo fileName(playlist_files.first());
m_pConfig->set(ConfigKey("[Library]","LastImportExportCrateDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(playlistFiles.first());
fileDirectory.truncate(playlistFiles.first().lastIndexOf(QDir::separator()));
m_pConfig->set(kConfigKeyLastImportExportCrateDirectoryKey,
ConfigValue(fileDirectory));

CrateId lastCrateId;

// For each selected file
for (const QString& playlistFile : playlist_files) {
fileName = QFileInfo(playlistFile);
for (const QString& playlistFile : playlistFiles) {
const QFileInfo fileInfo(playlistFile);

Crate crate;

// Get a valid name
QString baseName = fileName.baseName();
const QString baseName = fileInfo.baseName();
for (int i = 0;; ++i) {
auto name = baseName;
if (i > 0) {
Expand Down Expand Up @@ -683,23 +688,27 @@ void CrateFeature::slotExportPlaylist() {
}

QString lastCrateDirectory = m_pConfig->getValue(
ConfigKey("[Library]", "LastImportExportCrateDirectory"),
kConfigKeyLastImportExportCrateDirectoryKey,
QStandardPaths::writableLocation(QStandardPaths::MusicLocation));

QString file_location = QFileDialog::getSaveFileName(nullptr,
// Open a dialog to let the user choose the file location for crate export.
// The location is set to the last used directory for import/export and the file
// name to the playlist name.
const QString fileLocation = getFilePathWithVerifiedExtensionFromFileDialog(
tr("Export Crate"),
lastCrateDirectory.append("/").append(crate.getName()),
tr("M3U Playlist (*.m3u);;M3U8 Playlist (*.m3u8);;PLS Playlist "
"(*.pls);;Text CSV (*.csv);;Readable Text (*.txt)"));
"(*.pls);;Text CSV (*.csv);;Readable Text (*.txt)"),
tr("M3U Playlist (*.m3u)"));
// Exit method if user cancelled the open dialog.
if (file_location.isNull() || file_location.isEmpty()) {
if (fileLocation.isEmpty()) {
return;
}

// Update the import/export crate directory
QFileInfo fileName(file_location);
m_pConfig->set(ConfigKey("[Library]","LastImportExportCrateDirectory"),
ConfigValue(fileName.dir().absolutePath()));
QString fileDirectory(fileLocation);
fileDirectory.truncate(fileLocation.lastIndexOf(QDir::separator()));
m_pConfig->set(kConfigKeyLastImportExportCrateDirectoryKey,
ConfigValue(fileDirectory));

// The user has picked a new directory via a file dialog. This means the
// system sandboxer (if we are sandboxed) has granted us permission to this
Expand All @@ -718,21 +727,21 @@ void CrateFeature::slotExportPlaylist() {
pCrateTableModel->selectCrate(m_crateTableModel.selectedCrate());
pCrateTableModel->select();

if (file_location.endsWith(".csv", Qt::CaseInsensitive)) {
ParserCsv::writeCSVFile(file_location, pCrateTableModel.data(), useRelativePath);
} else if (file_location.endsWith(".txt", Qt::CaseInsensitive)) {
ParserCsv::writeReadableTextFile(file_location, pCrateTableModel.data(), false);
} else{
if (fileLocation.endsWith(".csv", Qt::CaseInsensitive)) {
ParserCsv::writeCSVFile(fileLocation, pCrateTableModel.data(), useRelativePath);
} else if (fileLocation.endsWith(".txt", Qt::CaseInsensitive)) {
ParserCsv::writeReadableTextFile(fileLocation, pCrateTableModel.data(), false);
} else {
ronso0 marked this conversation as resolved.
Show resolved Hide resolved
// populate a list of files of the crate
QList<QString> playlist_items;
QList<QString> playlistItems;
int rows = pCrateTableModel->rowCount();
for (int i = 0; i < rows; ++i) {
QModelIndex index = m_crateTableModel.index(i, 0);
playlist_items << m_crateTableModel.getTrackLocation(index);
playlistItems << m_crateTableModel.getTrackLocation(index);
}
exportPlaylistItemsIntoFile(
file_location,
playlist_items,
fileLocation,
playlistItems,
useRelativePath);
}
}
Expand Down
Loading