]> git.sesse.net Git - vlc/commitdiff
macosx: Move drag and drop support to new PLModel and rewrite
authorDavid Fuhrmann <dfuhrmann@videolan.org>
Sun, 30 Nov 2014 18:00:29 +0000 (19:00 +0100)
committerDavid Fuhrmann <dfuhrmann@videolan.org>
Tue, 30 Dec 2014 15:10:48 +0000 (16:10 +0100)
This simplifies the methods, also using a simpler storage for
dragged items.

modules/gui/macosx/MainWindow.m
modules/gui/macosx/PLItem.h
modules/gui/macosx/PLItem.m
modules/gui/macosx/PLModel.h
modules/gui/macosx/PLModel.m
modules/gui/macosx/playlist.m

index 1ff023e727402dd4dc0c847b7c61dd00d3b652ee..79f60ff71df43b4000918f5d810d85c66b14b057 100644 (file)
@@ -1182,7 +1182,7 @@ static VLCMainWindow *_o_sharedInstance = nil;
 {
     if ([[item identifier] isEqualToString:@"playlist"] || [[item identifier] isEqualToString:@"medialibrary"]) {
         NSPasteboard *o_pasteboard = [info draggingPasteboard];
-        if ([[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"] || [[o_pasteboard types] containsObject: NSFilenamesPboardType])
+        if ([[o_pasteboard types] containsObject: VLCPLItemPasteboadType] || [[o_pasteboard types] containsObject: NSFilenamesPboardType])
             return NSDragOperationGeneric;
     }
     return NSDragOperationNone;
@@ -1225,11 +1225,10 @@ static VLCMainWindow *_o_sharedInstance = nil;
         NSArray * array = [[[VLCMain sharedInstance] playlist] draggedItems];
 
         NSUInteger count = [array count];
-        playlist_item_t * p_item = NULL;
 
         PL_LOCK;
         for(NSUInteger i = 0; i < count; i++) {
-            p_item = [[array objectAtIndex:i] pointerValue];
+            playlist_item_t *p_item = playlist_ItemGetById(p_playlist, [[array objectAtIndex:i] plItemId]);
             if (!p_item) continue;
             playlist_NodeAddCopy(p_playlist, p_item, p_node, PLAYLIST_END);
         }
index 5cc387259ef9583d4784323ef36e012d195d46c9..55741466e506a1c1ac90015c5fc8f1b18153d8b5 100644 (file)
@@ -36,9 +36,9 @@
 @property(readonly, copy) NSMutableArray *children;
 @property(readonly) int plItemId;
 @property(readonly) input_item_t *input;
-@property(readonly) PLItem *parent;
+@property(readwrite, retain) PLItem *parent;
 
-- (id)initWithPlaylistItem:(playlist_item_t *)p_item parent:(PLItem *)parent;
+- (id)initWithPlaylistItem:(playlist_item_t *)p_item;
 
 - (BOOL)isLeaf;
 
index d072937cf35bfcd43a367813e5f4e2bb6016aa9e..f5c0f5f9b892ee6fe22da8dac9fb10d26f86766f 100644 (file)
@@ -33,7 +33,7 @@
 @synthesize input=p_input;
 @synthesize parent=_parent;
 
-- (id)initWithPlaylistItem:(playlist_item_t *)p_item parent:(PLItem *)parent;
+- (id)initWithPlaylistItem:(playlist_item_t *)p_item;
 {
     self = [super init];
     if(self) {
@@ -42,8 +42,6 @@
         p_input = p_item->p_input;
         input_item_Hold(p_input);
         _children = [[NSMutableArray alloc] init];
-        [parent retain];
-        _parent = parent;
     }
 
     return self;
     [super dealloc];
 }
 
+// own hash and isEqual methods are important to retain expandable state
+// when items are moved / recreated
+- (NSUInteger)hash
+{
+    return (NSUInteger)[self plItemId];
+}
+
+- (BOOL)isEqual:(id)other
+{
+    if (other == self)
+        return YES;
+    if (!other || ![other isKindOfClass:[self class]])
+        return NO;
+    return [self plItemId] == [other plItemId];
+}
 
 - (BOOL)isLeaf
 {
 
 - (void)addChild:(PLItem *)item atPos:(int)pos
 {
-//    if ([o_children count] > pos) {
-//        NSLog(@"invalid position %d", pos);
-//    }
     [_children insertObject:item atIndex:pos];
+    [item setParent: self];
 
 }
 
 - (void)deleteChild:(PLItem *)child
 {
+    [child setParent:nil];
     [_children removeObject:child];
 }
 
index 8239f59248f2c08bdc44225e940be787c40e313d..35ca03d2f34911a639e42481afdf83c174c92cb4 100644 (file)
 
 #include <vlc_common.h>
 
+#define VLCPLItemPasteboadType @"VLCPlaylistItemPboardType"
+
+@class VLCPlaylist;
+
 @interface PLModel : NSObject<NSOutlineViewDataSource>
 {
     PLItem *_rootItem;
 
     playlist_t *p_playlist;
     NSOutlineView *_outlineView;
+
+    // TODO: write these objects to the pastboard properly?
+    NSMutableArray *_draggedItems;
+
+    // TODO: for transition
+    VLCPlaylist *_playlist;
 }
 
 @property(readonly) PLItem *rootItem;
+@property(readonly, copy) NSArray *draggedItems;
+
 
-- (id)initWithOutlineView:(NSOutlineView *)outlineView playlist:(playlist_t *)pl rootItem:(playlist_item_t *)root;
+- (id)initWithOutlineView:(NSOutlineView *)outlineView playlist:(playlist_t *)pl rootItem:(playlist_item_t *)root playlistObject:(id)plObj;
 
 - (void)changeRootItem:(playlist_item_t *)p_root;
 
index 0aa3177a211ab08df8d69eccc6a8e8467886bc62..8f1cf98e0157865854a53bd833232657e27c62ae 100644 (file)
 
 #import "misc.h"
 
+#import "playlist.h"
+
 #include <vlc_playlist.h>
 #include <vlc_input_item.h>
+#import <vlc_input.h>
 #include <vlc_url.h>
 
 #define TRACKNUM_COLUMN @"tracknumber"
 @implementation PLModel
 
 @synthesize rootItem=_rootItem;
+@synthesize draggedItems=_draggedItems;
+
 
-- (id)initWithOutlineView:(NSOutlineView *)outlineView playlist:(playlist_t *)pl rootItem:(playlist_item_t *)root;
+- (id)initWithOutlineView:(NSOutlineView *)outlineView playlist:(playlist_t *)pl rootItem:(playlist_item_t *)root playlistObject:(id)plObj;
 {
     self = [super init];
     if(self) {
         p_playlist = pl;
         _outlineView = [outlineView retain];
+        _playlist = plObj;
 
         PL_LOCK;
-        _rootItem = [[PLItem alloc] initWithPlaylistItem:root parent:nil];
+        _rootItem = [[PLItem alloc] initWithPlaylistItem:root];
         [self rebuildPLItem:_rootItem];
         PL_UNLOCK;
 
@@ -67,7 +73,7 @@
     NSLog(@"change root item to %p", p_root);
     PL_ASSERT_LOCKED;
     [_rootItem release];
-    _rootItem = [[PLItem alloc] initWithPlaylistItem:p_root parent:nil];
+    _rootItem = [[PLItem alloc] initWithPlaylistItem:p_root];
     [self rebuildPLItem:_rootItem];
     [_outlineView reloadData];
 }
             if (p_child->i_flags & PLAYLIST_DBL_FLAG)
                 continue;
 
-            PLItem *o_child = [[[PLItem alloc] initWithPlaylistItem:p_child parent:o_item] autorelease];
+            PLItem *o_child = [[[PLItem alloc] initWithPlaylistItem:p_child] autorelease];
             [o_item addChild:o_child atPos:currPos++];
 
             if (p_child->i_children >= 0) {
     playlist_item_t *p_item = playlist_ItemGetById(p_playlist, i_item);
     if (!p_item || p_item->i_flags & PLAYLIST_DBL_FLAG)
     {
-        PL_UNLOCK; return;
+        PL_UNLOCK;
+        return;
     }
 
     int pos;
         if(p_item->p_parent->pp_children[pos] == p_item)
             break;
 
-    PLItem *o_new_item = [[[PLItem alloc] initWithPlaylistItem:p_item parent:o_parent] autorelease];
+    PLItem *o_new_item = [[[PLItem alloc] initWithPlaylistItem:p_item] autorelease];
     PL_UNLOCK;
     if (pos < 0)
         return;
     return o_value;
 }
 
+#pragma mark -
+#pragma mark Drag and Drop support
+
+- (BOOL)isItem: (PLItem *)p_item inNode: (PLItem *)p_node
+{
+    while(p_item) {
+        if ([p_item plItemId] == [p_node plItemId]) {
+            return YES;
+        }
+
+        p_item = [p_item parent];
+    }
+
+    return NO;
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
+{
+    NSUInteger itemCount = [items count];
+    [_draggedItems release];
+    _draggedItems = [[NSMutableArray alloc] initWithArray:items];
+
+    /* Add the data to the pasteboard object. */
+    [pboard declareTypes: [NSArray arrayWithObject:VLCPLItemPasteboadType] owner: self];
+    [pboard setData:[NSData data] forType:VLCPLItemPasteboadType];
+
+    return YES;
+}
+
+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
+{
+    NSPasteboard *o_pasteboard = [info draggingPasteboard];
+
+    /* Dropping ON items is not allowed if item is not a node */
+    if (item) {
+        if (index == NSOutlineViewDropOnItemIndex && [item isLeaf]) {
+            return NSDragOperationNone;
+        }
+    }
+
+    if (![self editAllowed])
+        return NSDragOperationNone;
+
+    /* Drop from the Playlist */
+    if ([[o_pasteboard types] containsObject:VLCPLItemPasteboadType]) {
+        NSUInteger count = [_draggedItems count];
+        for (NSUInteger i = 0 ; i < count ; i++) {
+            /* We refuse to Drop in a child of an item we are moving */
+            if ([self isItem: item inNode: [_draggedItems objectAtIndex:i]]) {
+                return NSDragOperationNone;
+            }
+        }
+        return NSDragOperationMove;
+    }
+    /* Drop from the Finder */
+    else if ([[o_pasteboard types] containsObject: NSFilenamesPboardType]) {
+        return NSDragOperationGeneric;
+    }
+    return NSDragOperationNone;
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)targetItem childIndex:(NSInteger)index
+{
+    NSPasteboard *o_pasteboard = [info draggingPasteboard];
+
+    /* Drag & Drop inside the playlist */
+    if ([[o_pasteboard types] containsObject:VLCPLItemPasteboadType]) {
+        if (index == -1) // this is no valid target, sanitize to top of table
+            index = 0;
+
+        if (targetItem == nil) {
+            targetItem = _rootItem;
+        }
+
+        NSMutableArray *o_filteredItems = [NSMutableArray arrayWithArray:_draggedItems];
+        const NSUInteger draggedItemsCount = [_draggedItems count];
+        for (NSInteger i = 0; i < [o_filteredItems count]; i++) {
+            for (NSUInteger j = 0; j < draggedItemsCount; j++) {
+                PLItem *itemToCheck = [o_filteredItems objectAtIndex:i];
+                PLItem *nodeToTest = [_draggedItems objectAtIndex:j];
+                if ([itemToCheck plItemId] == [nodeToTest plItemId])
+                    continue;
+
+                if ([self isItem:itemToCheck inNode:nodeToTest]) {
+                    [o_filteredItems removeObjectAtIndex:i];
+                    --i;
+                    break;
+                }
+            }
+        }
+
+        NSUInteger count = [o_filteredItems count];
+        if (count == 0)
+            return NO;
+
+        playlist_item_t **pp_items = (playlist_item_t **)calloc(count, sizeof(playlist_item_t*));
+        if (!pp_items)
+            return NO;
+
+        PL_LOCK;
+        playlist_item_t *p_new_parent = playlist_ItemGetById(p_playlist, [targetItem plItemId]);
+        if (!p_new_parent) {
+            PL_UNLOCK;
+            return NO;
+        }
+
+        NSUInteger j = 0;
+        for (NSUInteger i = 0; i < count; i++) {
+            playlist_item_t *p_item = playlist_ItemGetById(p_playlist, [[o_filteredItems objectAtIndex:i] plItemId]);
+            if (p_item)
+                pp_items[j++] = p_item;
+        }
+
+        if (playlist_TreeMoveMany(p_playlist, j, pp_items, p_new_parent, index) != VLC_SUCCESS) {
+            PL_UNLOCK;
+            free(pp_items);
+            return NO;
+        }
+
+        PL_UNLOCK;
+        free(pp_items);
+
+        // rebuild our model
+        NSUInteger filteredItemsCount = [o_filteredItems count];
+        for(NSUInteger i = 0; i < filteredItemsCount; ++i) {
+            PLItem *o_item = [o_filteredItems objectAtIndex:i];
+            NSLog(@"delete child from parent %p", [o_item parent]);
+            [[o_item parent] deleteChild:o_item];
+            [targetItem addChild:o_item atPos:index + i];
+        }
+
+        [_outlineView reloadData];
+
+        NSMutableIndexSet *selectedIndexes = [[NSMutableIndexSet alloc] init];
+        for(NSUInteger i = 0; i < draggedItemsCount; ++i) {
+            NSInteger row = [_outlineView rowForItem:[_draggedItems objectAtIndex:i]];
+            if (row < 0)
+                continue;
+
+            [selectedIndexes addIndex:row];
+        }
+
+        if ([selectedIndexes count] == 0)
+            [selectedIndexes addIndex:[_outlineView rowForItem:targetItem]];
+
+        [_outlineView selectRowIndexes:selectedIndexes byExtendingSelection:NO];
+        [selectedIndexes release];
+
+        return YES;
+    }
+
+    else if ([[o_pasteboard types] containsObject: NSFilenamesPboardType]) {
+
+        NSArray *o_values = [[o_pasteboard propertyListForType: NSFilenamesPboardType]
+                             sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
+        NSUInteger count = [o_values count];
+        NSMutableArray *o_array = [NSMutableArray arrayWithCapacity:count];
+        input_thread_t *p_input = playlist_CurrentInput(p_playlist);
+
+        if (count == 1 && p_input) {
+            int i_result = input_AddSubtitleOSD(p_input, vlc_path2uri([[o_values objectAtIndex:0] UTF8String], NULL), true, true);
+            vlc_object_release(p_input);
+            if (i_result == VLC_SUCCESS)
+                return YES;
+        }
+        else if (p_input)
+            vlc_object_release(p_input);
+
+        for (NSUInteger i = 0; i < count; i++) {
+            NSDictionary *o_dic;
+            char *psz_uri = vlc_path2uri([[o_values objectAtIndex:i] UTF8String], NULL);
+            if (!psz_uri)
+                continue;
+
+            o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
+
+            free(psz_uri);
+
+            [o_array addObject: o_dic];
+        }
+
+//        if (item == nil)
+            [_playlist appendArray:o_array atPos:index enqueue: YES];
+        // TODO support for drop on sub nodes
+//        else {
+//            assert(p_node->i_children != -1);
+//            [_playlist appendNodeArray:o_array inNode: p_node atPos:index enqueue:YES];
+//        }
+        return YES;
+    }
+    return NO;
+}
+
 @end
index ea9adf534c96550093f1c568730e6752516c934f..0f18743866f20c9e0fdcd528065a9530b67c0fbb 100644 (file)
     NSImage *o_descendingSortingImage;
     NSImage *o_ascendingSortingImage;
 
-    NSMutableArray *o_nodes_array;
-    NSMutableArray *o_items_array;
-
     BOOL b_selected_item_met;
     BOOL b_isSortDescending;
     id o_tc_sortColumn;
         playlist_t * p_playlist = pl_Get(VLCIntf);
         p_current_root_item = p_playlist->p_local_category;
         o_outline_dict = [[NSMutableDictionary alloc] init];
-
-        o_nodes_array = [[NSMutableArray alloc] init];
-        o_items_array = [[NSMutableArray alloc] init];
     }
     return self;
 }
 - (void)dealloc
 {
     [o_outline_dict release];
-    [o_nodes_array release];
-    [o_items_array release];
     [super dealloc];
 }
 
     [self reloadStyles];
     [self initStrings];
 
-    o_model = [[PLModel alloc] initWithOutlineView:o_outline_view playlist:p_playlist rootItem:p_current_root_item];
+    o_model = [[PLModel alloc] initWithOutlineView:o_outline_view playlist:p_playlist rootItem:p_current_root_item playlistObject:self];
     [o_outline_view setDataSource:o_model];
     [o_outline_view reloadData];
 
     return NO;
 }
 
-/* This method is useful for instance to remove the selected children of an
-   already selected node */
-- (void)removeItemsFrom:(id)o_items ifChildrenOf:(id)o_nodes
-{
-    NSUInteger itemCount = [o_items count];
-    NSUInteger nodeCount = [o_nodes count];
-    for (NSUInteger i = 0 ; i < itemCount ; i++) {
-        for (NSUInteger j = 0 ; j < nodeCount ; j++) {
-            if (o_items == o_nodes) {
-                if (j == i) continue;
-            }
-            if ([self isItem: [o_items objectAtIndex:i]
-                    inNode: [o_nodes objectAtIndex:j]
-                    checkItemExistence: NO locked:NO]) {
-                [o_items removeObjectAtIndex:i];
-                /* We need to execute the next iteration with the same index
-                   since the current item has been deleted */
-                i--;
-                break;
-            }
-        }
-    }
-}
-
 - (IBAction)savePlaylist:(id)sender
 {
     playlist_t * p_playlist = pl_Get(VLCIntf);
     return o_playing_item;
 }
 
+// TODO remove method
 - (NSArray *)draggedItems
 {
-    return [[o_nodes_array arrayByAddingObjectsFromArray: o_items_array] retain];
+    return [[self model] draggedItems];
 }
 
 - (void)setColumn: (NSString *)o_column state: (NSInteger)i_state translationDict:(NSDictionary *)o_dict
     return o_value;
 }
 
-
-/* Required for drag & drop and reordering */
-- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
-{
-    playlist_t *p_playlist = pl_Get(VLCIntf);
-
-    /* First remove the items that were moved during the last drag & drop
-       operation */
-    [o_items_array removeAllObjects];
-    [o_nodes_array removeAllObjects];
-
-    NSUInteger itemCount = [items count];
-
-    for (NSUInteger i = 0 ; i < itemCount ; i++) {
-        id o_item = [items objectAtIndex:i];
-
-        /* Fill the items and nodes to move in 2 different arrays */
-        if (![o_item isLeaf])
-            [o_nodes_array addObject: o_item];
-        else
-            [o_items_array addObject: o_item];
-    }
-
-    /* Now we need to check if there are selected items that are in already
-       selected nodes. In that case, we only want to move the nodes */
-    [self removeItemsFrom: o_nodes_array ifChildrenOf: o_nodes_array];
-    [self removeItemsFrom: o_items_array ifChildrenOf: o_nodes_array];
-
-    /* We add the "VLCPlaylistItemPboardType" type to be able to recognize
-       a Drop operation coming from the playlist. */
-
-    [pboard declareTypes: [NSArray arrayWithObject:@"VLCPlaylistItemPboardType"] owner: self];
-    [pboard setData:[NSData data] forType:@"VLCPlaylistItemPboardType"];
-
-    return YES;
-}
-
-- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
-{
-    playlist_t *p_playlist = pl_Get(VLCIntf);
-    NSPasteboard *o_pasteboard = [info draggingPasteboard];
-
-    if (!p_playlist) return NSDragOperationNone;
-
-    /* Dropping ON items is not allowed if item is not a node */
-    if (item) {
-        if (index == NSOutlineViewDropOnItemIndex &&
-                ((playlist_item_t *)[item pointerValue])->i_children == -1) {
-            return NSDragOperationNone;
-        }
-    }
-
-    /* We refuse to drop an item in anything else than a child of the General
-       Node. We still accept items that would be root nodes of the outlineview
-       however, to allow drop in an empty playlist. */
-    /// todo
-    //    if (!(([self isItem: [item pointerValue] inNode: p_playlist->p_local_category checkItemExistence: NO locked: NO] ||
-//            (var_CreateGetBool(p_playlist, "media-library") && [self isItem: [item pointerValue] inNode: p_playlist->p_ml_category checkItemExistence: NO locked: NO])) || item == nil)) {
-//        return NSDragOperationNone;
-//    }
-
-    /* Drop from the Playlist */
-    if ([[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"]) {
-        NSUInteger count = [o_nodes_array count];
-        for (NSUInteger i = 0 ; i < count ; i++) {
-            /* We refuse to Drop in a child of an item we are moving */
-            if ([self isItem: item inNode: [o_nodes_array objectAtIndex:i] checkItemExistence: NO locked:NO]) {
-                return NSDragOperationNone;
-            }
-        }
-        return NSDragOperationMove;
-    }
-    /* Drop from the Finder */
-    else if ([[o_pasteboard types] containsObject: NSFilenamesPboardType]) {
-        return NSDragOperationGeneric;
-    }
-    return NSDragOperationNone;
-}
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index
-{
-    playlist_t * p_playlist =  pl_Get(VLCIntf);
-    NSPasteboard *o_pasteboard = [info draggingPasteboard];
-
-    /* Drag & Drop inside the playlist */
-    if ([[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"]) {
-        if (index == -1) // this is no valid target, sanitize to top of table
-            index = 0;
-
-        int i_row = 0;
-        playlist_item_t *p_new_parent, *p_item = NULL;
-        NSArray *o_all_items = [o_nodes_array arrayByAddingObjectsFromArray: o_items_array];
-        /* If the item is to be dropped as root item of the outline, make it a
-           child of the respective general node, if is either the pl or the ml
-           Else, choose the proposed parent as parent. */
-        if (item == nil) {
-            // TODO edit allowed / no drop in other types
-            if ([[self model] currentRootType] == ROOT_TYPE_PLAYLIST ||
-                [[self model] currentRootType] == ROOT_TYPE_MEDIALIBRARY)
-                item = [[self model] rootItem];
-            else
-                return NO;
-        }
-
-        /* Make sure the proposed parent is a node.
-           (This should never be true) */
-        if (p_new_parent->i_children < 0)
-            return NO;
-
-        NSUInteger count = [o_all_items count];
-        if (count == 0)
-            return NO;
-
-        playlist_item_t **pp_items = (playlist_item_t **)calloc(count, sizeof(playlist_item_t*));
-        if (!pp_items)
-            return NO;
-
-        PL_LOCK;
-        p_new_parent = playlist_ItemGetById(p_playlist, [item plItemId]);
-        if (!p_new_parent) {
-            PL_UNLOCK;
-            return NO;
-        }
-
-        NSUInteger j = 0;
-        for (NSUInteger i = 0; i < count; i++) {
-            p_item = playlist_ItemGetById(p_playlist, [[o_all_items objectAtIndex:i] plItemId]);
-            if (p_item)
-                pp_items[j++] = p_item;
-        }
-
-        if (j == 0 || playlist_TreeMoveMany(p_playlist, j, pp_items, p_new_parent, index) != VLC_SUCCESS) {
-            PL_UNLOCK;
-            free(pp_items);
-            return NO;
-        }
-
-        PL_UNLOCK;
-        free(pp_items);
-
-        [self playlistUpdated];
-        i_row = [o_outline_view rowForItem:[o_all_items objectAtIndex:0]];
-
-        if (i_row == -1)
-            i_row = [o_outline_view rowForItem:item];
-
-        [o_outline_view deselectAll: self];
-        [o_outline_view selectRowIndexes:[NSIndexSet indexSetWithIndex:i_row] byExtendingSelection:NO];
-        [o_outline_view scrollRowToVisible: i_row];
-
-        return YES;
-    }
-
-    else if ([[o_pasteboard types] containsObject: NSFilenamesPboardType]) {
-        // TODO: can this already checked in drop validation?
-        if (![[self model] editAllowed])
-            return NO;
-
-        playlist_item_t *p_node = [item pointerValue];
-
-        NSArray *o_values = [[o_pasteboard propertyListForType: NSFilenamesPboardType]
-                                sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
-        NSUInteger count = [o_values count];
-        NSMutableArray *o_array = [NSMutableArray arrayWithCapacity:count];
-        input_thread_t * p_input = pl_CurrentInput(VLCIntf);
-
-        if (count == 1 && p_input) {
-            int i_result = input_AddSubtitleOSD(p_input, vlc_path2uri([[o_values objectAtIndex:0] UTF8String], NULL), true, true);
-            vlc_object_release(p_input);
-            if (i_result == VLC_SUCCESS)
-                return YES;
-        }
-        else if (p_input)
-            vlc_object_release(p_input);
-
-        for (NSUInteger i = 0; i < count; i++) {
-            NSDictionary *o_dic;
-            char *psz_uri = vlc_path2uri([[o_values objectAtIndex:i] UTF8String], NULL);
-            if (!psz_uri)
-                continue;
-
-            o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
-
-            free(psz_uri);
-
-            [o_array addObject: o_dic];
-        }
-
-        if (item == nil)
-            [self appendArray:o_array atPos:index enqueue: YES];
-        else {
-            assert(p_node->i_children != -1);
-            [self appendNodeArray:o_array inNode: p_node atPos:index enqueue:YES];
-        }
-        return YES;
-    }
-    return NO;
-}
-
 @end