void VirtualDirectoryTree::StoreChild(const wxString& displayname, const wxString& vdPath)
{
    VirtualDirectoryTree* child = new VirtualDirectoryTree(this, displayname, vdPath);
    if (IsSourceVD(displayname.Lower()) || IsHeaderVD(displayname.Lower()) || IsResourceVD(displayname.Lower())) {
        m_children.push_back(child); // We want these processed last, so push_back
    } else {
        m_children.push_front(child);
    }
}
wxString VirtualDirectoryTree::FindBestMatchVDir(const wxString& path, const wxString& ext) const
{
    // Try all children first
    for(size_t n = 0; n < m_children.size(); ++n) {
        wxString vdir = m_children[n]->FindBestMatchVDir(path, ext);
        if(!vdir.empty()) {
            return vdir;
        }
    }

    // Now try here. If there's an exact match, we're the correct one _unless_ there's a src/header/resource immediate
    // child
    wxString vdpath(m_vdPath.AfterFirst(':')); // We need to compare without the projectname
    vdpath.Replace(":", wxString(wxFILE_SEP_PATH));
    if(vdpath == path) {
        // Try for a src/header/etc immediate child. If there is one, it's presumably where files with a matching ext
        // should go
        for(size_t c = 0; c < m_children.size(); ++c) {
            wxString childname = m_children[c]->GetDisplayname();
            if(IsSourceVD(childname.Lower())) {
                if(ext == "cpp" || ext == "c" || ext == "cc") {
                    return m_children[c]->GetVPath();
                }
            }

            if(IsHeaderVD(childname.Lower())) {
                if(ext == "h" || ext == "hpp" || ext == "hh") {
                    return m_children[c]->GetVPath();
                }
            }

            if(IsResourceVD(childname.Lower())) {
                if(ext == "rc") {
                    return m_children[c]->GetVPath();
                }
            }
        }

        // None found so return us
        return m_vdPath;
    }

    return "";
}