diff options
Diffstat (limited to 'src/delete-files/delete-files.cc')
-rw-r--r-- | src/delete-files/delete-files.cc | 163 |
1 files changed, 110 insertions, 53 deletions
diff --git a/src/delete-files/delete-files.cc b/src/delete-files/delete-files.cc index 5472cbd..72fc534 100644 --- a/src/delete-files/delete-files.cc +++ b/src/delete-files/delete-files.cc @@ -39,6 +39,7 @@ #ifdef USE_QT #include <QMessageBox> #include <QPushButton> +#include <libaudqt/libaudqt.h> #endif class DeleteFiles : public GeneralPlugin @@ -76,118 +77,174 @@ static GtkWidget * dialog = nullptr; static QMessageBox * qdialog = nullptr; #endif -static void move_to_trash (const char * filename) +static bool delete_uri (const char * uri, bool use_trash) { - GFile * gfile = g_file_new_for_path (filename); + GFile * gfile = g_file_new_for_uri (uri); GError * gerror = nullptr; - if (! g_file_trash (gfile, nullptr, & gerror)) + bool success = use_trash ? + g_file_trash (gfile, nullptr, & gerror) : + g_file_delete (gfile, nullptr, & gerror); + + if (! success) { - aud_ui_show_error (str_printf (_("Error moving %s to trash: %s."), - filename, gerror->message)); + aud_ui_show_error (gerror->message); g_error_free (gerror); } g_object_unref ((GObject *) gfile); + return success; } -static void really_delete (const char * filename) +class DeleteOperation { - if (g_unlink (filename) < 0) - aud_ui_show_error (str_printf (_("Error deleting %s: %s."), filename, strerror (errno))); -} +public: + DeleteOperation (Playlist playlist) : + m_playlist (playlist), + m_use_trash (aud_get_bool ("delete_files", "use_trash")) + { + int num_entries = playlist.n_entries (); + for (int i = 0; i < num_entries; i ++) + { + if (playlist.entry_selected (i)) + m_files.append (playlist.entry_filename (i)); + } + } -static void confirm_delete () -{ - Index<String> files; + StringBuf prompt () const + { + StringBuf buf; - auto playlist = Playlist::active_playlist (); - int entry_count = playlist.n_entries (); + if (! m_files.len ()) + { + buf.insert (-1, _("No files are selected.")); + } + else if (m_files.len () == 1) + { + const char * format = m_use_trash ? + _("Do you want to move %s to the trash?") : + _("Do you want to permanently delete %s?"); + StringBuf display = uri_to_display (m_files[0]); + str_append_printf (buf, format, (const char *) display); + } + else + { + const char * format = m_use_trash ? + _("Do you want to move %d files to the trash?") : + _("Do you want to permanently delete %d files?"); + str_append_printf (buf, format, m_files.len ()); + } + + return buf; + } - for (int i = 0; i < entry_count; i ++) + const char * action () const { - if (playlist.entry_selected (i)) - files.append (playlist.entry_filename (i)); + if (! m_files.len ()) + return nullptr; + + return m_use_trash ? _("Move to trash") : _("Delete"); } - playlist.remove_selected (); + const char * icon () const + { + if (! m_files.len ()) + return nullptr; + + return m_use_trash ? "user-trash" : "edit-delete"; + } - for (const String & uri : files) + void run () const { - StringBuf filename = uri_to_filename (uri); + /* work around -Wignored-attributes on MinGW */ + auto string_compare = [] (const String & a, const String & b) + { return strcmp (a, b); }; - if (filename) + Index<String> deleted; + + for (auto & uri: m_files) { - if (aud_get_bool ("delete_files", "use_trash")) - move_to_trash (filename); - else - really_delete (filename); + if (delete_uri (uri, m_use_trash)) + deleted.append (uri); } - else - aud_ui_show_error (str_printf - (_("Error deleting %s: not a local file."), (const char *) uri)); + + deleted.sort (string_compare); + + /* make sure selection matches what we actually deleted */ + int num_entries = m_playlist.n_entries (); + for (int i = 0; i < num_entries; i++) + { + int j = deleted.bsearch (m_playlist.entry_filename (i), string_compare); + m_playlist.select_entry (i, (j >= 0)); + } + + m_playlist.remove_selected (); } -} + +private: + const Playlist m_playlist; + const bool m_use_trash; + Index<String> m_files; +}; static void start_delete () { - const char * message, * action, * icon; + auto op = new DeleteOperation (Playlist::active_playlist ()); - if (aud_get_bool ("delete_files", "use_trash")) - { - message = _("Do you want to move the selected files to the trash?"); - action = _("Move to Trash"); - icon = "user-trash"; - } - else + StringBuf prompt = op->prompt (); + const char * action = op->action (); + const char * icon = op->icon (); + + if (! action) { - message = _("Do you want to permanently delete the selected files?"); - action = _("Delete"); - icon = "edit-delete"; + aud_ui_show_error (prompt); + delete op; + return; } #ifdef USE_GTK if (aud_get_mainloop_type () == MainloopType::GLib) { if (dialog) - { - gtk_window_present ((GtkWindow *) dialog); - return; - } + gtk_widget_destroy (dialog); - auto button1 = audgui_button_new (action, icon, (AudguiCallback) confirm_delete, nullptr); + auto run_cb = aud::obj_member<DeleteOperation, & DeleteOperation::run>; + auto button1 = audgui_button_new (action, icon, run_cb, op); auto button2 = audgui_button_new (_("Cancel"), "process-stop", nullptr, nullptr); - dialog = audgui_dialog_new (GTK_MESSAGE_QUESTION, _("Delete Files"), message, button1, button2); + dialog = audgui_dialog_new (GTK_MESSAGE_QUESTION, _("Delete Files"), prompt, button1, button2); g_signal_connect (dialog, "destroy", (GCallback) gtk_widget_destroyed, & dialog); + g_signal_connect_swapped (dialog, "destroy", (GCallback) aud::delete_obj<DeleteOperation>, op); gtk_widget_show_all (dialog); } #endif #ifdef USE_QT if (aud_get_mainloop_type () == MainloopType::Qt) { - if (qdialog) - return; + delete qdialog; qdialog = new QMessageBox; qdialog->setAttribute (Qt::WA_DeleteOnClose); qdialog->setIcon (QMessageBox::Question); qdialog->setWindowTitle (_("Delete Files")); - qdialog->setText (message); + qdialog->setText ((const char *) prompt); auto remove = new QPushButton (action, qdialog); auto cancel = new QPushButton (_("Cancel"), qdialog); - remove->setIcon (QIcon::fromTheme (icon)); - cancel->setIcon (QIcon::fromTheme ("process-stop")); + remove->setIcon (audqt::get_icon (icon)); + cancel->setIcon (audqt::get_icon ("process-stop")); qdialog->addButton (remove, QMessageBox::AcceptRole); qdialog->addButton (cancel, QMessageBox::RejectRole); - QObject::connect (remove, & QPushButton::clicked, confirm_delete); - QObject::connect (qdialog, & QObject::destroyed, [] () { + QObject::connect (remove, & QPushButton::clicked, [op] () { + op->run (); + }); + QObject::connect (qdialog, & QObject::destroyed, [op] () { qdialog = nullptr; + delete op; }); qdialog->show (); |