From 6895572d875ecf55da2f81f8328458b74ade9ab9 Mon Sep 17 00:00:00 2001 From: Oleksiy Yakovenko Date: Sun, 28 Jan 2024 18:41:12 +0100 Subject: [PATCH] undo: set appropriate undo action name --- include/deadbeef/deadbeef.h | 6 ++++ plugins/cocoaui/AppDelegate.m | 35 +++++++++++-------- .../cocoaui/Playlist/PlaylistContentView.m | 3 ++ plugins/cocoaui/main.m | 4 ++- src/plugins.c | 9 ++++- src/undo/undomanager.c | 28 +++++++++++---- src/undo/undomanager.h | 9 ++++- 7 files changed, 71 insertions(+), 23 deletions(-) diff --git a/include/deadbeef/deadbeef.h b/include/deadbeef/deadbeef.h index 032f26e44e..2fe2226394 100644 --- a/include/deadbeef/deadbeef.h +++ b/include/deadbeef/deadbeef.h @@ -1712,7 +1712,13 @@ typedef struct { ddb_playItem_t * (*streamer_get_playing_track_safe) (void); #endif + /// Called to create an undo action from all actions + /// accumulated since the previous calls void (*undo_process)(void); + + /// Set the action name to be displayed in Undo/Redo menu item. + /// The name is reset to null for each new action when undo_process is called. + void (*undo_set_action_name) (const char *name); } DB_functions_t; // NOTE: an item placement must be selected like this diff --git a/plugins/cocoaui/AppDelegate.m b/plugins/cocoaui/AppDelegate.m index 37cdd869f0..9f18956ca6 100644 --- a/plugins/cocoaui/AppDelegate.m +++ b/plugins/cocoaui/AppDelegate.m @@ -450,25 +450,25 @@ - (void)openFiles:(BOOL)clear play:(BOOL)play { } } } - deadbeef->plt_add_files_end (plt, 0); if (!fileadd_cancelled) { dispatch_async(dispatch_get_main_queue(), ^{ if (clear) { deadbeef->plt_clear(plt_curr); - deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0); } ddb_playItem_t *tail = deadbeef->plt_get_tail_item(plt_curr, PL_MAIN); + deadbeef->undo_set_action_name("Add Files"); [PlaylistUtil.shared moveItemsFromPlaylist:plt toPlaylist:plt_curr afterItem:tail]; if (tail != NULL) { deadbeef->pl_item_unref (tail); } deadbeef->pl_save_current(); + deadbeef->plt_add_files_end (plt, 0); + deadbeef->plt_unref (plt); + deadbeef->plt_unref (plt_curr); + if (play) { - deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0); deadbeef->sendmessage (DB_EV_PLAY_NUM, 0, 0, 0); } - deadbeef->plt_unref (plt); - deadbeef->plt_unref (plt_curr); }); } else { @@ -510,7 +510,6 @@ - (IBAction)addFoldersAction:(id)sender { deadbeef->plt_add_dir2 (0, plt, fileName.UTF8String, NULL, NULL); } } - deadbeef->plt_add_files_end (plt, 0); if (!fileadd_cancelled) { dispatch_async(dispatch_get_main_queue(), ^{ ddb_playItem_t *tail = deadbeef->plt_get_tail_item(plt_curr, PL_MAIN); @@ -518,10 +517,11 @@ - (IBAction)addFoldersAction:(id)sender { if (tail != NULL) { deadbeef->pl_item_unref (tail); } + deadbeef->pl_save_current(); + deadbeef->undo_set_action_name("Add Folders"); + deadbeef->plt_add_files_end (plt, 0); deadbeef->plt_unref (plt); deadbeef->plt_unref (plt_curr); - deadbeef->pl_save_current(); - deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0); }); } else { @@ -543,22 +543,30 @@ - (IBAction)addLocationAction:(id)sender { if (returnCode == NSModalResponseOK) { NSString *text = [self.addLocationTextField.stringValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - ddb_playlist_t *plt = deadbeef->plt_get_curr (); + ddb_playlist_t *plt = deadbeef->plt_alloc ("add-location"); + ddb_playlist_t *plt_curr = deadbeef->plt_get_curr (); if (!deadbeef->plt_add_files_begin (plt, 0)) { dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(aQueue, ^{ DB_playItem_t *tail = deadbeef->plt_get_last (plt, PL_MAIN); - deadbeef->plt_insert_file2 (0, plt, tail, text.UTF8String, NULL, NULL, NULL); + deadbeef->plt_insert_file2 (0, plt, tail, text.UTF8String, NULL, NULL, NULL); + [PlaylistUtil.shared moveItemsFromPlaylist:plt toPlaylist:plt_curr afterItem:tail]; if (tail) { deadbeef->pl_item_unref (tail); } - deadbeef->plt_add_files_end (plt, 0); - deadbeef->plt_unref (plt); deadbeef->pl_save_current (); + + dispatch_async(dispatch_get_main_queue(), ^{ + deadbeef->undo_set_action_name("Add Location"); + deadbeef->plt_add_files_end (plt, 0); + deadbeef->plt_unref (plt); + deadbeef->plt_unref (plt_curr); + }); }); } else { deadbeef->plt_unref (plt); + deadbeef->plt_unref (plt_curr); } } }]; @@ -857,15 +865,14 @@ - (IBAction)loadPlaylistAction:(id)sender { if (!deadbeef->plt_add_files_begin (plt, 0)) { int abort = 0; deadbeef->plt_load2 (0, plt, NULL, fname.UTF8String, &abort, NULL, NULL); - deadbeef->plt_add_files_end (plt, 0); if (!abort) { dispatch_async(dispatch_get_main_queue(), ^{ deadbeef->plt_clear (plt_curr); [PlaylistUtil.shared moveItemsFromPlaylist:plt toPlaylist:plt_curr afterItem:NULL]; deadbeef->plt_save_config (plt); + deadbeef->plt_add_files_end (plt, 0); deadbeef->plt_unref (plt); deadbeef->plt_unref (plt_curr); - deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0); }); } else { diff --git a/plugins/cocoaui/Playlist/PlaylistContentView.m b/plugins/cocoaui/Playlist/PlaylistContentView.m index 16cbbd9a10..f59a6e9ae8 100644 --- a/plugins/cocoaui/Playlist/PlaylistContentView.m +++ b/plugins/cocoaui/Playlist/PlaylistContentView.m @@ -162,6 +162,9 @@ - (BOOL)performDragOperation:(id)sender { row = [self.dataModel rowForIndex:sel]; } + + deadbeef->undo_set_action_name("Drag & drop"); + if ([pboard.types containsObject:ddbPlaylistItemsUTIType]) { NSArray *classes = @[[PlaylistLocalDragDropHolder class]]; NSDictionary *options = @{}; diff --git a/plugins/cocoaui/main.m b/plugins/cocoaui/main.m index c5cc226fc2..e2f90b7ceb 100644 --- a/plugins/cocoaui/main.m +++ b/plugins/cocoaui/main.m @@ -61,7 +61,9 @@ int cocoaui_command (int command, ...) { NSUndoManager *undoManager = appDelegate.mainWindow.window.undoManager; DdbUndoBuffer *buffer = [[DdbUndoBuffer alloc] initWithUndoBuffer:undobuffer]; - [undoManager setActionName:[NSString stringWithUTF8String:name]]; + NSString *actionName = @(name ?: ""); + actionName = [actionName stringByReplacingOccurrencesOfString:@"&" withString:@"&&"]; + [undoManager setActionName:actionName]; [undoManager registerUndoBuffer:buffer]; } diff --git a/src/plugins.c b/src/plugins.c index 40676221c7..9900c52001 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -144,9 +144,15 @@ _viz_spectrum_listen_stub (void *ctx, void (*callback)(void *ctx, const ddb_audi static void _undo_process(void) { - undomanager_flush(undomanager_shared(), "Some Action"); + undomanager_flush(undomanager_shared()); } +static void +_undo_set_action_name (const char *name) { + undomanager_set_action_name (undomanager_shared(), name); +} + + // deadbeef api static DB_functions_t deadbeef_api = { .vmajor = DB_API_VERSION_MAJOR, @@ -540,6 +546,7 @@ static DB_functions_t deadbeef_api = { .streamer_get_playing_track_safe = (DB_playItem_t *(*) (void))streamer_get_playing_track, .undo_process = _undo_process, + .undo_set_action_name = _undo_set_action_name, }; DB_functions_t *deadbeef = &deadbeef_api; diff --git a/src/undo/undomanager.c b/src/undo/undomanager.c index 6f9b4d274e..ae5fc5f8bb 100644 --- a/src/undo/undomanager.c +++ b/src/undo/undomanager.c @@ -22,12 +22,14 @@ */ #include +#include #include "undomanager.h" extern DB_functions_t *deadbeef; struct undomanager_s { undobuffer_t *buffer; + char *action_name; }; static undomanager_t *_shared; @@ -44,6 +46,7 @@ undomanager_free (undomanager_t *undomanager) { if (undomanager == _shared) { _shared = NULL; } + free (undomanager->action_name); if (undomanager->buffer != NULL) { undobuffer_free(undomanager->buffer); } @@ -87,17 +90,30 @@ _plug_get_gui (void) { } void -undomanager_flush(undomanager_t *undomanager, const char *name) { - undobuffer_t *undobuffer = undomanager_consume_buffer(undomanager); - if (!undobuffer_has_operations(undobuffer)) { +undomanager_set_action_name (undomanager_t *undomanager, const char *name) { + free (undomanager->action_name); + undomanager->action_name = name ? strdup (name) : NULL; +} + +const char * +undomanager_get_action_name (undomanager_t *undomanager) { + return undomanager->action_name; +} + +void +undomanager_flush(undomanager_t *undomanager) { + undobuffer_t *undobuffer = undomanager_consume_buffer (undomanager); + if (!undobuffer_has_operations (undobuffer)) { return; } - DB_plugin_t *ui_plugin = _plug_get_gui(); + DB_plugin_t *ui_plugin = _plug_get_gui (); if (ui_plugin && ui_plugin->command) { - ui_plugin->command (111, undobuffer, name); + ui_plugin->command (111, undobuffer, undomanager_get_action_name (undomanager)); } else { - undobuffer_free(undobuffer); // lost + undobuffer_free (undobuffer); // lost } + + undomanager_set_action_name (undomanager, NULL); } diff --git a/src/undo/undomanager.h b/src/undo/undomanager.h index 759adbdabc..6d6d7c65cd 100644 --- a/src/undo/undomanager.h +++ b/src/undo/undomanager.h @@ -44,7 +44,14 @@ undomanager_consume_buffer (undomanager_t *undomanager); // Send the accumulated undo buffer to the UI for registration void -undomanager_flush(undomanager_t *undomanager, const char *name); +undomanager_flush(undomanager_t *undomanager); + +void +undomanager_set_action_name (undomanager_t *undomanager, const char *name); + +const char * +undomanager_get_action_name (undomanager_t *undomanager); + #pragma mark - Shared instance