From 350a991f264297849b204d502adc675bf7e50448 Mon Sep 17 00:00:00 2001
From: Mikolaj Wielgus <wielgusmikolaj@gmail.com>
Date: Thu, 5 Dec 2019 20:35:37 +0100
Subject: [PATCH] Allow multiple selections in Kicad project manager (starting
 point)

---
 kicad/tree_project_frame.cpp | 454 ++++++++++++++++++++---------------
 kicad/tree_project_frame.h   |   4 +-
 kicad/treeprojectfiles.cpp   |   8 +-
 3 files changed, 264 insertions(+), 202 deletions(-)

diff --git a/kicad/tree_project_frame.cpp b/kicad/tree_project_frame.cpp
index 5a01659f57..cb848cb0c0 100644
--- a/kicad/tree_project_frame.cpp
+++ b/kicad/tree_project_frame.cpp
@@ -63,37 +63,36 @@
 // list of files extensions listed in the tree project window
 // *.sch files are always allowed, do not add here
 // Add extensions in a compatible regex format to see others files types
-static const wxChar* s_allowedExtensionsToList[] =
-{
+static const wxChar* s_allowedExtensionsToList[] = {
     wxT( "^.*\\.pro$" ),
     wxT( "^.*\\.pdf$" ),
-    wxT( "^[^$].*\\.brd$" ),        // Legacy Pcbnew files
-    wxT( "^[^$].*\\.kicad_pcb$" ),  // S format Pcbnew board files
-    wxT( "^[^$].*\\.kicad_wks$" ),  // S format kicad page layout descr files
-    wxT( "^[^$].*\\.kicad_mod$" ),  // S format kicad footprint files, currently not listed
-    wxT( "^.*\\.net$" ),            // pcbnew netlist file
-    wxT( "^.*\\.cir$" ),            // Spice netlist file
-    wxT( "^.*\\.lib$" ),            // Schematic library file
+    wxT( "^[^$].*\\.brd$" ),       // Legacy Pcbnew files
+    wxT( "^[^$].*\\.kicad_pcb$" ), // S format Pcbnew board files
+    wxT( "^[^$].*\\.kicad_wks$" ), // S format kicad page layout help_textr files
+    wxT( "^[^$].*\\.kicad_mod$" ), // S format kicad footprint files, currently not listed
+    wxT( "^.*\\.net$" ),           // pcbnew netlist file
+    wxT( "^.*\\.cir$" ),           // Spice netlist file
+    wxT( "^.*\\.lib$" ),           // Schematic library file
     wxT( "^.*\\.txt$" ),
-    wxT( "^.*\\.pho$" ),            // Gerber file (Old Kicad extension)
-    wxT( "^.*\\.gbr$" ),            // Gerber file
-    wxT( "^.*\\.gbrjob$" ),         // Gerber job file
-    wxT( "^.*\\.gb[alops]$" ),      // Gerber back (or bottom) layer file (deprecated Protel ext)
-    wxT( "^.*\\.gt[alops]$" ),      // Gerber front (or top) layer file (deprecated Protel ext)
-    wxT( "^.*\\.g[0-9]{1,2}$" ),    // Gerber inner layer file (deprecated Protel ext)
+    wxT( "^.*\\.pho$" ),           // Gerber file (Old Kicad extension)
+    wxT( "^.*\\.gbr$" ),           // Gerber file
+    wxT( "^.*\\.gbrjob$" ),        // Gerber job file
+    wxT( "^.*\\.gb[alops]$" ),     // Gerber back (or bottom) layer file (deprecated Protel ext)
+    wxT( "^.*\\.gt[alops]$" ),     // Gerber front (or top) layer file (deprecated Protel ext)
+    wxT( "^.*\\.g[0-9]{1,2}$" ),   // Gerber inner layer file (deprecated Protel ext)
     wxT( "^.*\\.odt$" ),
     wxT( "^.*\\.htm$" ),
     wxT( "^.*\\.html$" ),
-    wxT( "^.*\\.rpt$" ),            // Report files
-    wxT( "^.*\\.csv$" ),            // Report files in comma separated format
-    wxT( "^.*\\.pos$" ),            // Footprint position files
-    wxT( "^.*\\.cmp$" ),            // Cvpcb cmp/footprint link files
-    wxT( "^.*\\.drl$" ),            // Excellon drill files
-    wxT( "^.*\\.nc$" ),             // Excellon NC drill files (alternate file ext)
-    wxT( "^.*\\.xnc$" ),            // Excellon NC drill files (alternate file ext)
-    wxT( "^.*\\.svg$" ),            // SVG print/plot files
-    wxT( "^.*\\.ps$" ),             // Postscript plot files
-    NULL                            // end of list
+    wxT( "^.*\\.rpt$" ),           // Report files
+    wxT( "^.*\\.csv$" ),           // Report files in comma separated format
+    wxT( "^.*\\.pos$" ),           // Footprint position files
+    wxT( "^.*\\.cmp$" ),           // Cvpcb cmp/footprint link files
+    wxT( "^.*\\.drl$" ),           // Excellon drill files
+    wxT( "^.*\\.nc$" ),            // Excellon NC drill files (alternate file ext)
+    wxT( "^.*\\.xnc$" ),           // Excellon NC drill files (alternate file ext)
+    wxT( "^.*\\.svg$" ),           // SVG print/plot files
+    wxT( "^.*\\.ps$" ),            // Postscript plot files
+    NULL                           // end of list
 };
 
 
@@ -172,12 +171,12 @@ TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME()
 
 void TREE_PROJECT_FRAME::OnSwitchToSelectedProject( wxCommandEvent& event )
 {
-    TREEPROJECT_ITEM* tree_data = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !tree_data )
+    if( tree_data.size() != 1 )
         return;
 
-    wxString prj_filename = tree_data->GetFileName();
+    wxString prj_filename = tree_data[0]->GetFileName();
 
     m_Parent->LoadProject( prj_filename );
 }
@@ -186,79 +185,80 @@ void TREE_PROJECT_FRAME::OnSwitchToSelectedProject( wxCommandEvent& event )
 void TREE_PROJECT_FRAME::OnOpenDirectory( wxCommandEvent& event )
 {
     // Get the root directory name:
-    TREEPROJECT_ITEM* treeData = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !treeData )
-        return;
-
-    // Ask for the new sub directory name
-    wxString curr_dir = treeData->GetDir();
-
-    if( curr_dir.IsEmpty() )
+    for( TREEPROJECT_ITEM* item_data : tree_data )
     {
-        // Use project path if the tree view path was empty.
-        curr_dir = wxPathOnly( m_Parent->GetProjectFileName() );
+        // Ask for the new sub directory name
+        wxString curr_dir = item_data->GetDir();
 
-        // As a last resort use the user's documents folder.
-        if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
-            curr_dir = wxStandardPaths::Get().GetDocumentsDir();
+        if( curr_dir.IsEmpty() )
+        {
+            // Use project path if the tree view path was empty.
+            curr_dir = wxPathOnly( m_Parent->GetProjectFileName() );
 
-        if( !curr_dir.IsEmpty() )
-            curr_dir += wxFileName::GetPathSeparator();
-    }
+            // As a last resort use the user's documents folder.
+            if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
+                curr_dir = wxStandardPaths::Get().GetDocumentsDir();
+
+            if( !curr_dir.IsEmpty() )
+                curr_dir += wxFileName::GetPathSeparator();
+        }
 
 #ifdef __WXMAC__
-    wxString msg;
+        wxString msg;
 
-    // Quote in case there are spaces in the path.
-    msg.Printf( "open \"%s\"", curr_dir );
+        // Quote in case there are spaces in the path.
+        msg.Printf( "open \"%s\"", curr_dir );
 
-    system( msg.c_str() );
+        system( msg.c_str() );
 #else
-    // Quote in case there are spaces in the path.
-    AddDelimiterString( curr_dir );
+        // Quote in case there are spaces in the path.
+        AddDelimiterString( curr_dir );
 
-    wxLaunchDefaultApplication( curr_dir );
+        wxLaunchDefaultApplication( curr_dir );
 #endif
+    }
 }
 
 
 void TREE_PROJECT_FRAME::OnCreateNewDirectory( wxCommandEvent& event )
 {
     // Get the root directory name:
-    TREEPROJECT_ITEM* treeData = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !treeData )
-        return;
-
-    wxString prj_dir = wxPathOnly( m_Parent->GetProjectFileName() );
-
-    // Ask for the new sub directory name
-    wxString curr_dir = treeData->GetDir();
-
-    if( !curr_dir.IsEmpty() )    // A subdir is selected
+    for( TREEPROJECT_ITEM* item_data : tree_data )
     {
-        // Make this subdir name relative to the current path.
-        // It will be more easy to read by the user, in the next dialog
-        wxFileName fn;
-        fn.AssignDir( curr_dir );
-        fn.MakeRelativeTo( prj_dir );
-        curr_dir = fn.GetPath();
+        wxString prj_dir = wxPathOnly( m_Parent->GetProjectFileName() );
 
-        if( !curr_dir.IsEmpty() )
-            curr_dir += wxFileName::GetPathSeparator();
-    }
+        // Ask for the new sub directory name
+        wxString curr_dir = item_data->GetDir();
 
-    wxString msg = wxString::Format( _( "Current project directory:\n%s" ), GetChars( prj_dir ) );
-    wxString subdir = wxGetTextFromUser( msg, _( "Create New Directory" ), curr_dir );
+        if( !curr_dir.IsEmpty() ) // A subdir is selected
+        {
+            // Make this subdir name relative to the current path.
+            // It will be more easy to read by the user, in the next dialog
+            wxFileName fn;
+            fn.AssignDir( curr_dir );
+            fn.MakeRelativeTo( prj_dir );
+            curr_dir = fn.GetPath();
 
-    if( subdir.IsEmpty() )
-        return;
+            if( !curr_dir.IsEmpty() )
+                curr_dir += wxFileName::GetPathSeparator();
+        }
 
-    wxString full_dirname = prj_dir + wxFileName::GetPathSeparator() + subdir;
+        wxString msg =
+                wxString::Format( _( "Current project directory:\n%s" ), GetChars( prj_dir ) );
+        wxString subdir = wxGetTextFromUser( msg, _( "Create New Directory" ), curr_dir );
+
+        if( subdir.IsEmpty() )
+            return;
+
+        wxString full_dirname = prj_dir + wxFileName::GetPathSeparator() + subdir;
 
     // Make the new item and let the file watcher add it to the tree
     wxMkdir( full_dirname );
+    }
 }
 
 
@@ -294,8 +294,8 @@ wxTreeItemId TREE_PROJECT_FRAME::AddItemToTreeProject( const wxString& aName,
                                                wxTreeItemId& aRoot, bool aRecurse )
 {
     wxTreeItemId newItemId;
-    TreeFileType type = TREE_UNKNOWN;
-    wxFileName   fn( aName );
+    TreeFileType    type = TREE_UNKNOWN;
+    wxFileName      fn( aName );
 
     // Files/dirs names starting by "." are not visible files under unices.
     // Skip them also under Windows
@@ -447,7 +447,7 @@ wxTreeItemId TREE_PROJECT_FRAME::AddItemToTreeProject( const wxString& aName,
 
         if( dir.IsOpened() )    // protected dirs will not open properly.
         {
-            wxString dir_filename;
+            wxString        dir_filename;
 
             data->SetPopulated( true );
 
@@ -536,155 +536,211 @@ void TREE_PROJECT_FRAME::ReCreateTreePrj()
 
 void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event )
 {
-    int                 tree_id;
-    TREEPROJECT_ITEM*   tree_data;
-    wxString            fullFileName;
     wxTreeItemId        curr_item = Event.GetItem();
 
     // Ensure item is selected (Under Windows right click does not select the item)
     m_TreeProject->SelectItem( curr_item );
 
-    tree_data = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !tree_data )
+    bool can_switch_to_project = true;
+    bool can_create_new_directory = true;
+    bool can_open_this_directory = true;
+    bool can_edit = true;
+    bool can_rename = true;
+    bool can_delete = true;
+    bool can_print = true;
+
+    if( tree_data.size() == 0 )
         return;
 
-    tree_id = tree_data->GetType();
-    fullFileName = tree_data->GetFileName();
-
-    wxMenu popupMenu;
-
-    switch( tree_id )
+    if( tree_data.size() != 1 )
     {
-    case TREE_PROJECT:
-        // Add a swith to an other project option only if the selected item
-        // is not the root item (current project)
-        if( curr_item != m_TreeProject->GetRootItem() )
-        {
-            AddMenuItem( &popupMenu, ID_PROJECT_SWITCH_TO_OTHER,
-                         _( "&Switch to this Project" ),
-                         _( "Close all editors, and switch to the selected project" ),
-                         KiBitmap( open_project_xpm ) );
-            popupMenu.AppendSeparator();
-        }
-
-        AddMenuItem( &popupMenu, ID_PROJECT_NEWDIR,
-                     _( "New D&irectory..." ),
-                     _( "Create a New Directory" ),
-                     KiBitmap( directory_xpm ) );
-
-        AddMenuItem( &popupMenu, ID_PROJECT_OPEN_DIR,
-#ifdef __APPLE__
-                     _( "Reveal in Finder" ),
-                     _( "Reveals the directory in a Finder window" ),
-#else
-                     _( "&Open Directory in File Explorer" ),
-                     _( "Opens the directory in the default system file manager" ),
-#endif
-                     KiBitmap( directory_browser_xpm ) );
-        break;
-
-    case TREE_DIRECTORY:
-        AddMenuItem( &popupMenu, ID_PROJECT_NEWDIR,
-                     _( "New D&irectory..." ),
-                     _( "Create a New Directory" ),
-                     KiBitmap( directory_xpm ) );
-        AddMenuItem( &popupMenu, ID_PROJECT_OPEN_DIR,
-#ifdef __APPLE__
-                     _( "Reveal in Finder" ),
-                     _( "Reveals the directory in a Finder window" ),
-#else
-                     _( "&Open Directory in File Explorer" ),
-                     _( "Opens the directory in the default system file manager" ),
-#endif
-                     KiBitmap( directory_browser_xpm ) );
-
-        popupMenu.AppendSeparator();
-        AddMenuItem( &popupMenu,  ID_PROJECT_DELETE,
-                     _( "&Delete Directory" ),
-                     _( "Delete the Directory and its content" ),
-                     KiBitmap( delete_xpm ) );
-        break;
-
-    default:
-        AddMenuItem( &popupMenu, ID_PROJECT_TXTEDIT,
-                     _( "&Edit in a Text Editor" ),
-                     _( "Open the file in a Text Editor" ),
-                     KiBitmap( editor_xpm ) );
-        AddMenuItem( &popupMenu, ID_PROJECT_RENAME,
-                     _( "&Rename File..." ),
-                     _( "Rename file" ),
-                     KiBitmap( right_xpm ) );
-
-        popupMenu.AppendSeparator();
-        AddMenuItem( &popupMenu,  ID_PROJECT_DELETE,
-                     _( "&Delete File" ),
-                     _( "Delete the file and its content" ),
-                     KiBitmap( delete_xpm ) );
-
-        if( CanPrintFile( fullFileName ) )
-        {
-            popupMenu.AppendSeparator();
-            AddMenuItem( &popupMenu, ID_PROJECT_PRINT,
-#ifdef __APPLE__
-                         _( "Print..." ),
-#else
-                         _( "&Print" ),
-#endif
-                         _( "Print the contents of the file" ),
-                         KiBitmap( print_button_xpm ) );
-        }
-        break;
+        can_switch_to_project = false;
+        can_create_new_directory = false;
+        can_rename = false;
+        can_print = false;
     }
 
-    PopupMenu( &popupMenu );
+    if( curr_item == m_TreeProject->GetRootItem() )
+        can_switch_to_project = false;
+
+    for( TREEPROJECT_ITEM* item_data : tree_data )
+    {
+        int      tree_id = item_data->GetType();
+        wxString full_file_name = item_data->GetFileName();
+
+        switch( tree_id )
+        {
+        case TREE_PROJECT:
+            can_edit = false;
+            can_rename = false;
+            can_delete = false;
+            can_print = false;
+            break;
+        case TREE_DIRECTORY:
+            can_switch_to_project = false;
+            can_edit = false;
+            can_rename = false;
+            can_print = false;
+            break;
+        default:
+            can_switch_to_project = false;
+            can_create_new_directory = false;
+            can_open_this_directory = false;
+            if( !CanPrintFile( full_file_name ) )
+                can_print = false;
+            break;
+        }
+    }
+
+    wxMenu   popup_menu;
+    wxString text;
+    wxString help_text;
+
+    if( can_switch_to_project )
+    {
+        AddMenuItem( &popup_menu, ID_PROJECT_SWITCH_TO_OTHER, _( "&Switch to this Project" ),
+                _( "Close all editors, and switch to the selected project" ),
+                KiBitmap( open_project_xpm ) );
+        popup_menu.AppendSeparator();
+    }
+
+    if( can_create_new_directory )
+    {
+        AddMenuItem( &popup_menu, ID_PROJECT_NEWDIR, _( "New D&irectory..." ),
+                _( "Create a New Directory" ), KiBitmap( directory_xpm ) );
+    }
+
+    if( can_open_this_directory )
+    {
+        if( tree_data.size() == 1 )
+        {
+#ifdef __APPLE__
+            text = _( "Reveal in Finder" );
+            help_text = _( "Reveals the directory in a Finder window" );
+#else
+            text = _( "&Open Directory in File Explorer" );
+            help_text = _( "Opens the directory in the default system file manager" );
+#endif
+        }
+        else
+        {
+#ifdef __APPLE__
+            text = _( "Reveal in Finder" );
+            help_text = _( "Reveals the directories in a Finder window" );
+#else
+            text = _( "&Open Directories in File Explorer" );
+            help_text = _( "Opens the directories in the default system file manager" );
+#endif
+        }
+
+        AddMenuItem( &popup_menu, ID_PROJECT_OPEN_DIR, text, help_text,
+                KiBitmap( directory_browser_xpm ) );
+    }
+
+    if( can_edit )
+    {
+        if( tree_data.size() == 1 )
+            help_text = _( "Open the file in a Text Editor" );
+        else
+            help_text = _( "Open the files in a Text Editor" );
+
+        AddMenuItem( &popup_menu, ID_PROJECT_TXTEDIT, _( "&Edit in a Text Editor" ), help_text,
+                KiBitmap( editor_xpm ) );
+    }
+
+    if( can_rename )
+    {
+        if( tree_data.size() == 1 )
+        {
+            text = _( "&Rename File..." );
+            help_text = _( "Rename file" );
+        }
+        else
+        {
+            text = _( "&Rename Files..." );
+            help_text = _( "Rename files" );
+        }
+
+        AddMenuItem( &popup_menu, ID_PROJECT_RENAME, text, help_text, KiBitmap( right_xpm ) );
+    }
+
+    if( can_delete )
+    {
+        if( tree_data.size() == 1 )
+            help_text = _( "Delete the file and its content" );
+        else
+            help_text = _( "Delete the files and their contents" );
+
+        if( can_switch_to_project || can_create_new_directory || can_open_this_directory || can_edit
+                || can_rename )
+            popup_menu.AppendSeparator();
+        AddMenuItem(
+                &popup_menu, ID_PROJECT_DELETE, _( "&Delete" ), help_text, KiBitmap( delete_xpm ) );
+    }
+
+    if( can_print )
+    {
+        popup_menu.AppendSeparator();
+        AddMenuItem( &popup_menu, ID_PROJECT_PRINT,
+#ifdef __APPLE__
+                _( "Print..." ),
+#else
+                _( "&Print" ),
+#endif
+                _( "Print the contents of the file" ), KiBitmap( print_button_xpm ) );
+    }
+
+    PopupMenu( &popup_menu );
 }
 
 
 void TREE_PROJECT_FRAME::OnOpenSelectedFileWithTextEditor( wxCommandEvent& event )
 {
-    TREEPROJECT_ITEM* tree_data = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !tree_data || tree_data->GetType() == TREE_DIRECTORY )
-        return;
+    for( TREEPROJECT_ITEM* item_data : tree_data )
+    {
+        wxString fullFileName = item_data->GetFileName();
+        AddDelimiterString( fullFileName );
+        wxString editorname = Pgm().GetEditorName();
 
-    wxString    fullFileName = tree_data->GetFileName();
-    AddDelimiterString( fullFileName );
-    wxString    editorname = Pgm().GetEditorName();
-
-    if( !editorname.IsEmpty() )
-        ExecuteFile( this, editorname, fullFileName );
+        if( !editorname.IsEmpty() )
+            ExecuteFile( this, editorname, fullFileName );
+    }
 }
 
 
 void TREE_PROJECT_FRAME::OnDeleteFile( wxCommandEvent& )
 {
-    TREEPROJECT_ITEM* tree_data = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( tree_data )
-        tree_data->Delete();
+    for( TREEPROJECT_ITEM* item_data : tree_data )
+        item_data->Delete();
 }
 
 
 void TREE_PROJECT_FRAME::OnPrintFile( wxCommandEvent& )
 {
-    TREEPROJECT_ITEM* tree_data = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( tree_data )
-        tree_data->Print();
+    for( TREEPROJECT_ITEM* item_data : tree_data )
+        item_data->Print();
 }
 
 
 void TREE_PROJECT_FRAME::OnRenameFile( wxCommandEvent& )
 {
-    wxTreeItemId        curr_item   = m_TreeProject->GetSelection();
-    TREEPROJECT_ITEM*   tree_data   = GetSelectedData();
+    wxTreeItemId                   curr_item = m_TreeProject->GetFocusedItem();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !tree_data )
+    // XXX: Unnecessary?
+    if( tree_data.size() != 1 )
         return;
 
     wxString buffer = m_TreeProject->GetItemText( curr_item );
-    wxString msg = wxString::Format( _( "Change filename: \"%s\"" ), tree_data->GetFileName() );
+    wxString msg = wxString::Format( _( "Change filename: \"%s\"" ), tree_data[0]->GetFileName() );
     wxTextEntryDialog dlg( this, msg, _( "Change filename" ), buffer );
 
     if( dlg.ShowModal() != wxID_OK )
@@ -697,19 +753,19 @@ void TREE_PROJECT_FRAME::OnRenameFile( wxCommandEvent& )
     if( buffer.IsEmpty() )
         return; // empty file name not allowed
 
-    tree_data->Rename( buffer, true );
+    tree_data[0]->Rename( buffer, true );
     m_isRenaming = true;
 }
 
 
 void TREE_PROJECT_FRAME::OnSelect( wxTreeEvent& Event )
 {
-    TREEPROJECT_ITEM* selected_item = GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> tree_data = GetSelectedData();
 
-    if( !selected_item )
+    if( tree_data.size() != 1 )
         return;
 
-    selected_item->Activate( this );
+    tree_data[0]->Activate( this );
 }
 
 
@@ -775,9 +831,17 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event )
 }
 
 
-TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetSelectedData()
+std::vector<TREEPROJECT_ITEM*> TREE_PROJECT_FRAME::GetSelectedData()
 {
-    return GetItemIdData( m_TreeProject->GetSelection() );
+    wxArrayTreeItemIds             selection;
+    std::vector<TREEPROJECT_ITEM*> data;
+
+    m_TreeProject->GetSelections( selection );
+
+    for( auto it = selection.begin(); it != selection.end(); it++ )
+        data.push_back( GetItemIdData( *it ) );
+
+    return data;
 }
 
 
@@ -818,7 +882,7 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
                 subdirs_id.pop();
                 kid = m_TreeProject->GetFirstChild( root_id, cookie );
 
-                if( !kid.IsOk() )
+                if( ! kid.IsOk() )
                     continue;
             }
         }
diff --git a/kicad/tree_project_frame.h b/kicad/tree_project_frame.h
index 2651a126b0..6fc35f4240 100644
--- a/kicad/tree_project_frame.h
+++ b/kicad/tree_project_frame.h
@@ -83,13 +83,13 @@ protected:
      * Note this is not necessary the "clicked" item,
      * because when expanding, collapsing an item this item is not selected
      */
-    TREEPROJECT_ITEM* GetSelectedData();
+    std::vector<TREEPROJECT_ITEM*> GetSelectedData();
 
     /**
      * Function GetItemIdData
      * return the item data corresponding to a wxTreeItemId identifier
      * @param  aId = the wxTreeItemId identifier.
-     * @return a TREEPROJECT_ITEM pointer correspondinfg to item id aId
+     * @return a TREEPROJECT_ITEM pointer corresponding to item id aId
      */
     TREEPROJECT_ITEM* GetItemIdData( wxTreeItemId aId );
 
diff --git a/kicad/treeprojectfiles.cpp b/kicad/treeprojectfiles.cpp
index 4ec9881fe7..3630777378 100644
--- a/kicad/treeprojectfiles.cpp
+++ b/kicad/treeprojectfiles.cpp
@@ -39,11 +39,9 @@
 IMPLEMENT_ABSTRACT_CLASS( TREEPROJECTFILES, wxTreeCtrl )
 
 
-TREEPROJECTFILES::TREEPROJECTFILES( TREE_PROJECT_FRAME* parent ) :
-    wxTreeCtrl( parent, ID_PROJECT_TREE,
-                wxDefaultPosition, wxDefaultSize,
-                wxTR_HAS_BUTTONS, wxDefaultValidator,
-                wxT( "EDATreeCtrl" ) )
+TREEPROJECTFILES::TREEPROJECTFILES( TREE_PROJECT_FRAME* parent )
+        : wxTreeCtrl( parent, ID_PROJECT_TREE, wxDefaultPosition, wxDefaultSize,
+                wxTR_HAS_BUTTONS | wxTR_MULTIPLE, wxDefaultValidator, wxT( "EDATreeCtrl" ) )
 {
     m_Parent = parent;