void ReconcileProjectDlg::OnApply(wxCommandEvent& event)
{
    // get the list of files to add to the project
    wxDataViewItemArray items;
    if(event.GetId() == wxID_APPLY) {
        m_dataviewAssigned->GetSelections(items);
    } else {
        m_dataviewAssignedModel->GetChildren(wxDataViewItem(0), items);
    }

    // virtual folder to file name
    wxStringSet_t vds;
    StringMultimap_t filesToAdd;
    for(size_t i = 0; i < items.GetCount(); ++i) {
        ReconcileFileItemData* data =
            dynamic_cast<ReconcileFileItemData*>(m_dataviewAssignedModel->GetClientObject(items.Item(i)));
        if(data) {
            filesToAdd.insert(std::make_pair(data->GetVirtualFolder(), data->GetFilename()));
            vds.insert(data->GetVirtualFolder());
        }
    }

    wxStringSet_t::const_iterator iter = vds.begin();
    for(; iter != vds.end(); ++iter) {
        std::pair<StringMultimap_t::iterator, StringMultimap_t::iterator> range = filesToAdd.equal_range(*iter);
        StringMultimap_t::iterator from = range.first;
        wxArrayString vdFiles;
        for(; from != range.second; ++from) {
            vdFiles.Add(from->second);
        }
        wxArrayString additions = AddMissingFiles(vdFiles, *iter);

        if(additions.GetCount()) {
            m_projectModified = true;
        }
        // We must also remove the processed files from m_newfiles, otherwise a rerun of the wizard will offer them for
        // insertion again
        for(size_t n = 0; n < additions.GetCount(); ++n) {
            m_newfiles.erase(additions.Item(n));
        }
    }
    m_dataviewAssignedModel->DeleteItems(wxDataViewItem(0), items);
}
void ReconcileProjectDlg::OnUndoSelectedFiles(wxCommandEvent& event)
{
    wxDataViewItemArray items;
    m_dataviewAssigned->GetSelections(items);

    for(size_t i=0; i<items.GetCount(); ++i) {
        wxVariant v;
        ReconcileFileItemData* data = dynamic_cast<ReconcileFileItemData*>(m_dataviewAssignedModel->GetClientObject( items.Item(i) ));
        if ( data ) {
            wxFileName fn(data->GetFilename());
            fn.MakeRelativeTo(m_toplevelDir);

            wxVector<wxVariant> cols;
            cols.push_back(::MakeIconText(fn.GetFullPath(), GetBitmap(fn.GetFullName())));
            m_dvListCtrl1Unassigned->AppendItem( cols, (wxUIntPtr)NULL );

        }
    }

    // get the list of items
    wxArrayString allfiles;
    for(int i=0 ; i<m_dvListCtrl1Unassigned->GetItemCount(); ++i) {
        wxVariant v;
        m_dvListCtrl1Unassigned->GetValue(v, i, 0);
        wxDataViewIconText it;
        it << v;
        allfiles.Add(it.GetText());
    }

    m_dataviewAssignedModel->DeleteItems(wxDataViewItem(0), items);

    // Could not find a nicer way of doing this, but
    // we want the files to be sorted again
    m_dvListCtrl1Unassigned->DeleteAllItems();

    std::sort(allfiles.begin(), allfiles.end());
    for(size_t i=0; i<allfiles.GetCount(); ++i) {
        wxVector<wxVariant> cols;
        cols.push_back( ::MakeIconText(allfiles.Item(i), GetBitmap(allfiles.Item(i)) ) );
        m_dvListCtrl1Unassigned->AppendItem( cols, (wxUIntPtr)NULL);
    }
}
void ReconcileProjectDlg::OnDeleteStaleFiles(wxCommandEvent& event)
{
    ProjectPtr proj = ManagerST::Get()->GetProject(m_projname);
    wxCHECK_RET(proj, "Can't find a Project with the supplied name");

    wxDataViewItemArray items;
    if (event.GetId() == wxID_DELETE) {
        m_dataviewStaleFiles->GetSelections( items );
    } else {
        m_dataviewStaleFilesModel->GetChildren(wxDataViewItem(0), items);
    }
    
    proj->BeginTranscation();
    for(size_t i=0; i<items.GetCount(); ++i) {
        ReconcileFileItemData* data =  dynamic_cast<ReconcileFileItemData*>(m_dataviewStaleFilesModel->GetClientObject(items.Item(i)));
        if ( data ) {
            proj->RemoveFile( data->GetFilename(), data->GetVirtualFolder() );
        }
        m_projectModified = true;
    }
    proj->CommitTranscation();
    m_dataviewStaleFilesModel->DeleteItems(wxDataViewItem(0), items);
}