@@ -34,10 +34,11 @@
|
||||
|
||||
const int DeleteFiles::kBatchSize = 50;
|
||||
|
||||
DeleteFiles::DeleteFiles(TaskManager *task_manager, std::shared_ptr<MusicStorage> storage)
|
||||
DeleteFiles::DeleteFiles(TaskManager *task_manager, std::shared_ptr<MusicStorage> storage, const bool use_trash)
|
||||
: thread_(nullptr),
|
||||
task_manager_(task_manager),
|
||||
storage_(storage),
|
||||
use_trash_(use_trash),
|
||||
started_(false),
|
||||
task_id_(0),
|
||||
progress_(0) {
|
||||
@@ -112,6 +113,7 @@ void DeleteFiles::ProcessSomeFiles() {
|
||||
|
||||
MusicStorage::DeleteJob job;
|
||||
job.metadata_ = song;
|
||||
job.use_trash_ = use_trash_;
|
||||
|
||||
if (!storage_->DeleteFromStorage(job)) {
|
||||
songs_with_errors_ << song;
|
||||
|
||||
@@ -38,7 +38,7 @@ class DeleteFiles : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeleteFiles(TaskManager *task_manager, std::shared_ptr<MusicStorage> storage);
|
||||
explicit DeleteFiles(TaskManager *task_manager, std::shared_ptr<MusicStorage> storage, const bool use_trash);
|
||||
~DeleteFiles() override;
|
||||
|
||||
static const int kBatchSize;
|
||||
@@ -59,6 +59,7 @@ signals:
|
||||
std::shared_ptr<MusicStorage> storage_;
|
||||
|
||||
SongList songs_;
|
||||
bool use_trash_;
|
||||
|
||||
bool started_;
|
||||
|
||||
|
||||
@@ -108,6 +108,17 @@ bool FilesystemMusicStorage::DeleteFromStorage(const DeleteJob &job) {
|
||||
QString path = job.metadata_.url().toLocalFile();
|
||||
QFileInfo fileInfo(path);
|
||||
|
||||
if (job.use_trash_) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
if (fileInfo.isDir())
|
||||
return Utilities::MoveToTrashRecursive(path);
|
||||
else
|
||||
return QFile::moveToTrash(path);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fileInfo.isDir())
|
||||
return Utilities::RemoveRecursive(path);
|
||||
else
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
#include "database.h"
|
||||
#include "player.h"
|
||||
#include "appearance.h"
|
||||
#include "filesystemmusicstorage.h"
|
||||
#include "deletefiles.h"
|
||||
#include "engine/enginetype.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "engine/engine_fwd.h"
|
||||
@@ -100,6 +102,7 @@
|
||||
#include "dialogs/trackselectiondialog.h"
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#include "dialogs/addstreamdialog.h"
|
||||
#include "dialogs/deleteconfirmationdialog.h"
|
||||
#include "organize/organizedialog.h"
|
||||
#include "widgets/fancytabwidget.h"
|
||||
#include "widgets/playingwidget.h"
|
||||
@@ -261,15 +264,16 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd
|
||||
playlist_play_pause_(nullptr),
|
||||
playlist_stop_after_(nullptr),
|
||||
playlist_undoredo_(nullptr),
|
||||
playlist_organize_(nullptr),
|
||||
playlist_copy_url_(nullptr),
|
||||
playlist_show_in_collection_(nullptr),
|
||||
playlist_copy_to_collection_(nullptr),
|
||||
playlist_move_to_collection_(nullptr),
|
||||
playlist_open_in_browser_(nullptr),
|
||||
playlist_organize_(nullptr),
|
||||
#ifndef Q_OS_WIN
|
||||
playlist_copy_to_device_(nullptr),
|
||||
#endif
|
||||
playlist_open_in_browser_(nullptr),
|
||||
playlist_copy_url_(nullptr),
|
||||
playlist_delete_(nullptr),
|
||||
playlist_queue_(nullptr),
|
||||
playlist_queue_play_next_(nullptr),
|
||||
playlist_skip_(nullptr),
|
||||
@@ -286,7 +290,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd
|
||||
doubleclick_addmode_(BehaviourSettingsPage::AddBehaviour_Append),
|
||||
doubleclick_playmode_(BehaviourSettingsPage::PlayBehaviour_Never),
|
||||
menu_playmode_(BehaviourSettingsPage::PlayBehaviour_Never),
|
||||
exit_count_(0)
|
||||
exit_count_(0),
|
||||
delete_files_(false)
|
||||
{
|
||||
|
||||
qLog(Debug) << "Starting";
|
||||
@@ -659,16 +664,16 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd
|
||||
playlist_menu_->addAction(ui_->action_add_files_to_transcoder);
|
||||
#endif
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_copy_url_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy URL(s)..."), this, SLOT(PlaylistCopyUrl()));
|
||||
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in collection..."), this, SLOT(ShowInCollection()));
|
||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
||||
playlist_organize_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, SLOT(PlaylistMoveToCollection()));
|
||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
||||
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
|
||||
#endif
|
||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
||||
playlist_organize_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, SLOT(PlaylistMoveToCollection()));
|
||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
||||
playlist_open_in_browser_->setVisible(false);
|
||||
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in collection..."), this, SLOT(ShowInCollection()));
|
||||
playlist_copy_url_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy URL(s)..."), this, SLOT(PlaylistCopyUrl()));
|
||||
playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
|
||||
playlist_menu_->addSeparator();
|
||||
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_->action_clear_playlist);
|
||||
@@ -990,6 +995,10 @@ void MainWindow::ReloadSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
s.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
||||
delete_files_ = s.value("delete_files", false).toBool();
|
||||
s.endGroup();
|
||||
|
||||
osd_->ReloadSettings();
|
||||
|
||||
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings_.value("search_for_cover_auto", true).toBool());
|
||||
@@ -1733,6 +1742,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
playlist_copy_to_device_->setVisible(false);
|
||||
#endif
|
||||
playlist_organize_->setVisible(false);
|
||||
playlist_delete_->setVisible(false);
|
||||
|
||||
playlist_copy_url_->setVisible(selected > 0);
|
||||
|
||||
@@ -1805,6 +1815,10 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
playlist_copy_to_device_->setVisible(editable > 0);
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
playlist_delete_->setVisible(delete_files_ && editable > 0);
|
||||
#endif
|
||||
|
||||
// Remove old item actions, if any.
|
||||
for (QAction *action : playlistitem_actions_) {
|
||||
playlist_menu_->removeAction(action);
|
||||
@@ -2850,3 +2864,39 @@ void MainWindow::Love() {
|
||||
if (tray_icon_) tray_icon_->LoveStateChanged(false);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::PlaylistDelete() {
|
||||
|
||||
if (!delete_files_) return;
|
||||
|
||||
SongList selected_songs;
|
||||
QStringList files;
|
||||
bool is_current_item = false;
|
||||
for (const QModelIndex &proxy_idx : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||
QModelIndex source_idx = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_idx);
|
||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_idx.row());
|
||||
if (!item || !item->Metadata().url().isLocalFile()) continue;
|
||||
selected_songs << item->Metadata();
|
||||
files << item->Metadata().url().toLocalFile();
|
||||
if (item == app_->player()->GetCurrentItem()) is_current_item = true;
|
||||
}
|
||||
if (selected_songs.isEmpty()) return;
|
||||
|
||||
if (DeleteConfirmationDialog::warning(files) != QDialogButtonBox::Yes) return;
|
||||
|
||||
if (app_->player()->GetState() == Engine::Playing && app_->playlist_manager()->current()->rowCount() == selected_songs.count()) {
|
||||
app_->player()->Stop();
|
||||
}
|
||||
|
||||
ui_->playlist->view()->RemoveSelected();
|
||||
|
||||
if (app_->player()->GetState() == Engine::Playing && is_current_item) {
|
||||
app_->player()->Next();
|
||||
}
|
||||
|
||||
std::shared_ptr<MusicStorage> storage(new FilesystemMusicStorage("/"));
|
||||
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage, true);
|
||||
connect(delete_files, SIGNAL(Finished(SongList)), SLOT(DeleteFinished(SongList)));
|
||||
delete_files->Start(selected_songs);
|
||||
|
||||
}
|
||||
|
||||
@@ -264,6 +264,8 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
|
||||
void ExitFinished();
|
||||
|
||||
void PlaylistDelete();
|
||||
|
||||
private:
|
||||
|
||||
void SaveSettings();
|
||||
@@ -331,15 +333,16 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
QAction *playlist_play_pause_;
|
||||
QAction *playlist_stop_after_;
|
||||
QAction *playlist_undoredo_;
|
||||
QAction *playlist_organize_;
|
||||
QAction *playlist_copy_url_;
|
||||
QAction *playlist_show_in_collection_;
|
||||
QAction *playlist_copy_to_collection_;
|
||||
QAction *playlist_move_to_collection_;
|
||||
QAction *playlist_open_in_browser_;
|
||||
QAction *playlist_organize_;
|
||||
#ifndef Q_OS_WIN
|
||||
QAction *playlist_copy_to_device_;
|
||||
#endif
|
||||
QAction *playlist_open_in_browser_;
|
||||
QAction *playlist_copy_url_;
|
||||
QAction *playlist_delete_;
|
||||
QAction *playlist_queue_;
|
||||
QAction* playlist_queue_play_next_;
|
||||
QAction *playlist_skip_;
|
||||
@@ -369,6 +372,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
Song song_playing_;
|
||||
QImage image_original_;
|
||||
int exit_count_;
|
||||
bool delete_files_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ class MusicStorage {
|
||||
typedef std::function<void(float progress)> ProgressFunction;
|
||||
|
||||
struct CopyJob {
|
||||
CopyJob() : overwrite_(false), mark_as_listened_(false), remove_original_(false), albumcover_(false) {}
|
||||
QString source_;
|
||||
QString destination_;
|
||||
Song metadata_;
|
||||
@@ -70,7 +71,9 @@ class MusicStorage {
|
||||
};
|
||||
|
||||
struct DeleteJob {
|
||||
DeleteJob() : use_trash_(false) {}
|
||||
Song metadata_;
|
||||
bool use_trash_;
|
||||
};
|
||||
|
||||
virtual QString LocalPath() const { return QString(); }
|
||||
|
||||
@@ -253,6 +253,30 @@ QString MakeTempDir(const QString template_name) {
|
||||
|
||||
}
|
||||
|
||||
bool MoveToTrashRecursive(const QString &path) {
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
QDir dir(path);
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden)) {
|
||||
if (!MoveToTrashRecursive(path + "/" + child))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files | QDir::Hidden)) {
|
||||
if (!QFile::moveToTrash(path + "/" + child))
|
||||
return false;
|
||||
}
|
||||
|
||||
return dir.rmdir(path);
|
||||
|
||||
#else
|
||||
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool RemoveRecursive(const QString &path) {
|
||||
|
||||
QDir dir(path);
|
||||
|
||||
@@ -64,6 +64,7 @@ quint64 FileSystemFreeSpace(const QString &path);
|
||||
|
||||
QString MakeTempDir(const QString template_name = QString());
|
||||
|
||||
bool MoveToTrashRecursive(const QString &path);
|
||||
bool RemoveRecursive(const QString &path);
|
||||
bool CopyRecursive(const QString &source, const QString &destination);
|
||||
bool Copy(QIODevice *source, QIODevice *destination);
|
||||
|
||||
Reference in New Issue
Block a user