]> git.sesse.net Git - vlc/blobdiff - modules/gui/wxwidgets/dialogs/playlist.cpp
- Undo [14667]
[vlc] / modules / gui / wxwidgets / dialogs / playlist.cpp
index 85d408924ee37a523ae16d1f1d5c4904ea3dce08..c4102e84169f729dea8305762fb289e0800b90ff 100644 (file)
@@ -4,8 +4,8 @@
  * Copyright (C) 2000-2005 the VideoLAN team
  * $Id$
  *
- * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
- *          Clément Stenac <zorglub@videolan.org>
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *          Clément Stenac <zorglub@videolan.org>
  *
  * This program is free software; you can redistribute it and/OR MODIFy
  * it under the terms of the GNU General Public License as published by
@@ -27,7 +27,6 @@
  *****************************************************************************/
 #include "dialogs/playlist.hpp"
 #include "dialogs/iteminfo.hpp"
-#include "interface.hpp" // Needed for D&D - TODO: Split
 
 #include "bitmaps/shuffle.xpm"
 #include "bitmaps/repeat.xpm"
@@ -47,6 +46,9 @@
 #include <wx/dynarray.h>
 #include <wx/imaglist.h>
 
+#include <vlc_meta.h>
+#include "charset.h"
+
 #define HELP_SHUFFLE N_( "Shuffle" )
 #define HELP_LOOP N_( "Repeat All" )
 #define HELP_REPEAT N_( "Repeat One" )
@@ -60,9 +62,9 @@ static int PlaylistNext( vlc_object_t *, const char *,
 static int ItemChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
 static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
-                      vlc_value_t oval, vlc_value_t nval, void *param );
+                         vlc_value_t oval, vlc_value_t nval, void *param );
 static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
-                      vlc_value_t oval, vlc_value_t nval, void *param );
+                        vlc_value_t oval, vlc_value_t nval, void *param );
 
 /*****************************************************************************
  * Event Table.
@@ -94,6 +96,7 @@ enum
     PopupSort_Event,
     PopupDel_Event,
     PopupInfo_Event,
+    PopupAddNode_Event,
 
     SearchText_Event,
     Search_Event,
@@ -151,10 +154,13 @@ BEGIN_EVENT_TABLE(Playlist, wxFrame)
     EVT_MENU( PopupSort_Event, Playlist::OnPopupSort)
     EVT_MENU( PopupDel_Event, Playlist::OnPopupDel)
     EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo)
+    EVT_MENU( PopupAddNode_Event, Playlist::OnPopupAddNode)
 
     /* Tree control events */
     EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem )
     EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown )
+    EVT_TREE_BEGIN_DRAG( TreeCtrl_Event, Playlist::OnDragItemBegin )
+    EVT_TREE_END_DRAG( TreeCtrl_Event, Playlist::OnDragItemEnd )
 
     EVT_CONTEXT_MENU( Playlist::OnPopup )
 
@@ -186,6 +192,7 @@ public:
 protected:
     int i_id;
 friend class Playlist;
+friend class PlaylistFileDropTarget;
 };
 
 /*****************************************************************************
@@ -270,6 +277,7 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
     node_popup->Append( PopupSort_Event, wxU(_("Sort this branch")) );
     node_popup->Append( PopupDel_Event, wxU(_("Delete")) );
     node_popup->Append( PopupInfo_Event, wxU(_("Info")) );
+    node_popup->Append( PopupAddNode_Event, wxU(_("Add node")) );
 
     item_popup = new wxMenu;
     item_popup->Append( PopupPlay_Event, wxU(_("Play")) );
@@ -366,7 +374,9 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
 
 #if wxUSE_DRAG_AND_DROP
     /* Associate drop targets with the playlist */
-    SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) );
+    SetDropTarget( new PlaylistFileDropTarget( this ) );
+    menubar->SetDropTarget( new PlaylistFileDropTarget( this ) );
+    toolbar->SetDropTarget( new PlaylistFileDropTarget( this ) );
 #endif
 
     i_saved_id = -1;
@@ -492,8 +502,7 @@ void Playlist::UpdateTreeItem( wxTreeItemId item )
     wxString msg;
     wxString duration = wxU( "" );
     char *psz_author = vlc_input_item_GetInfo( &p_item->input,
-                                                     _("Meta-information"),
-                                                     _("Artist"));
+                                               _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) );
     if( !psz_author )
     {
         UnlockPlaylist( p_intf->p_sys, p_playlist );
@@ -517,7 +526,7 @@ void Playlist::UpdateTreeItem( wxTreeItemId item )
     else
     {
         msg = wxString(wxU( psz_author )) + wxT(" - ") +
-                    wxString(wxU(p_item->input.psz_name)) + duration;
+              wxString(wxU(p_item->input.psz_name)) + duration;
     }
     free( psz_author );
     treectrl->SetItemText( item , msg );
@@ -1138,6 +1147,166 @@ void Playlist::OnEnDis( wxCommandEvent& event )
     msg_Warn( p_intf, "not implemented" );
 }
 
+void Playlist::OnDragItemBegin( wxTreeEvent& event )
+{
+    event.Allow();
+    draged_tree_item = event.GetItem();
+}
+
+void Playlist::OnDragItemEnd( wxTreeEvent& event )
+{
+    wxTreeItemId dest_tree_item = event.GetItem();
+
+    if( !dest_tree_item.IsOk() ) return;
+
+    /* check that we're not trying to move a node into one of it's children */
+    wxTreeItemId parent = dest_tree_item;
+    while( parent != treectrl->GetRootItem() )
+    {
+        if( draged_tree_item == parent ) return;
+        parent = treectrl->GetItemParent( parent );
+    }
+
+    LockPlaylist( p_intf->p_sys, p_playlist );
+
+    PlaylistItem *p_wxdrageditem =
+        (PlaylistItem *)treectrl->GetItemData( draged_tree_item );
+    PlaylistItem *p_wxdestitem =
+        (PlaylistItem *)treectrl->GetItemData( dest_tree_item );
+    if( !p_wxdrageditem || !p_wxdestitem )
+    {
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+        return;
+    }
+
+    playlist_item_t *p_drageditem =
+        playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id );
+    playlist_item_t *p_destitem =
+        playlist_ItemGetById(p_playlist, p_wxdestitem->i_id );
+    if( !p_drageditem || !p_destitem )
+    {
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+        return;
+    }
+
+    if( p_destitem->i_children == -1 )
+    /* this is a leaf */
+    {
+        parent = treectrl->GetItemParent( dest_tree_item );
+        PlaylistItem *p_parent =
+            (PlaylistItem *)treectrl->GetItemData( parent );
+        if( !p_parent )
+        {
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+            return;
+        }
+        playlist_item_t *p_destitem2 =
+            playlist_ItemGetById( p_playlist, p_parent->i_id );
+        if( !p_destitem2 )
+        {
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+            return;
+        }
+        int i;
+        for( i = 0; i < p_destitem2->i_children; i++ )
+        {
+            if( p_destitem2->pp_children[i] == p_destitem ) break;
+        }
+        playlist_TreeMove( p_playlist, p_drageditem, p_destitem2,
+                           i, i_current_view );
+    }
+    else
+    /* this is a node */
+    {
+        playlist_TreeMove( p_playlist, p_drageditem, p_destitem,
+                           0, i_current_view );
+    }
+
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+
+    /* FIXME: having this Rebuild() is dirty */
+    Rebuild( VLC_TRUE );
+}
+
+#if wxUSE_DRAG_AND_DROP
+PlaylistFileDropTarget::PlaylistFileDropTarget( Playlist *p ):p( p ){}
+
+/********************************************************************
+ * File Drag And Drop handling
+ ********************************************************************/
+bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y,
+                               const wxArrayString& filenames )
+{
+    int i_pos = 0;
+    playlist_item_t *p_dest;
+
+    LockPlaylist( p->p_intf->p_sys, p->p_playlist );
+
+    /* find the destination node and position in that node */
+    const wxPoint pt( x, y );
+    wxTreeItemId item = p->treectrl->HitTest( pt );
+
+    if( !item.IsOk() )
+    {
+        /* We were droped below the last item so we append to the
+         * general node */
+        p_dest = p->p_playlist->p_general;
+        i_pos = PLAYLIST_END;
+    }
+    else
+    {
+        PlaylistItem *p_plitem =
+            (PlaylistItem *)p->treectrl->GetItemData( item );
+        p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id );
+
+        if( p_dest->i_children == -1 )
+        {
+            /* This is a leaf. Append right after it
+             * We thus need to find the parrent node and the position of the
+             * leaf in it's children list */
+            wxTreeItemId parent = p->treectrl->GetItemParent( item );
+            PlaylistItem *p_parent =
+                (PlaylistItem *)p->treectrl->GetItemData( parent );
+            if( !p_parent )
+            {
+                UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+                return FALSE;
+            }
+            playlist_item_t *p_node =
+                playlist_ItemGetById( p->p_playlist, p_parent->i_id );
+            if( !p_node )
+            {
+                UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+                return FALSE;
+            }
+            for( i_pos = 0; i_pos < p_node->i_children; i_pos++ )
+            {
+                if( p_node->pp_children[i_pos] == p_dest ) break;
+            }
+            p_dest = p_node;
+        }
+    }
+
+    UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+
+    /* Put the items in the playlist node */
+    for( size_t i = 0; i < filenames.GetCount(); i++ )
+    {
+        const char *psz_utf8 = wxDnDFromLocale( filenames[i] );
+        playlist_item_t *p_item =
+            playlist_ItemNew( p->p_playlist, psz_utf8, psz_utf8 );
+        playlist_NodeAddItem( p->p_playlist, p_item, p->i_current_view,
+                              p_dest, PLAYLIST_PREPARSE, i_pos );
+        wxDnDLocaleFree( psz_utf8 );
+    }
+
+    /* FIXME: having this Rebuild() is dirty */
+    p->Rebuild( VLC_TRUE );
+
+    return TRUE;
+}
+#endif
+
 /**********************************************************************
  * Menu
  **********************************************************************/
@@ -1435,6 +1604,31 @@ void Playlist::OnPopupInfo( wxCommandEvent& event )
     UnlockPlaylist( p_intf->p_sys, p_playlist );
 }
 
+void Playlist::OnPopupAddNode( wxCommandEvent& event )
+{
+    wxTextEntryDialog text( NULL, wxU(_( "Please enter node name" )),
+        wxU(_( "Add node" )), wxU(_( "New node" )) );
+    if( text.ShowModal() != wxID_OK ) return;
+
+    char *psz_name = wxFromLocale( text.GetValue() );
+
+    LockPlaylist( p_intf->p_sys, p_playlist );
+
+    PlaylistItem *p_wxitem;
+    playlist_item_t *p_item;
+
+    p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
+
+    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+
+    playlist_NodeCreate( p_playlist, i_current_view, psz_name, p_item );
+
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+    Rebuild( VLC_TRUE );
+
+    wxLocaleFree( psz_name );
+}
+
 
 /*****************************************************************************
  * Custom events management
@@ -1519,7 +1713,7 @@ static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
     playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));
     memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) );
 
-    if( p_playlist_dialog->i_items_to_append++ > 50 )
+    if( ++p_playlist_dialog->i_items_to_append >= 50 )
     {
         /* Too many items waiting to be added, it will be quicker to rebuild
          * the whole playlist */