30#include <wx/stdpaths.h> 
   33#include <wx/textdlg.h> 
   35#include <wx/wupdlock.h> 
   55#include <wx/dcclient.h> 
   56#include <wx/progdlg.h> 
   57#include <wx/settings.h> 
  106    wxT( 
"^.*\\.kicad_pro$" ),
 
  109    wxT( 
"^.*\\.kicad_sch$" ),     
 
  110    wxT( 
"^[^$].*\\.brd$" ),       
 
  111    wxT( 
"^[^$].*\\.kicad_pcb$" ), 
 
  112    wxT( 
"^[^$].*\\.kicad_dru$" ), 
 
  113    wxT( 
"^[^$].*\\.kicad_wks$" ), 
 
  114    wxT( 
"^[^$].*\\.kicad_mod$" ), 
 
  118    wxT( 
"^.*\\.kicad_sym$" ),     
 
  123    wxT( 
"^.*\\.gbrjob$" ),        
 
  124    wxT( 
"^.*\\.gb[alops]$" ),     
 
  125    wxT( 
"^.*\\.gt[alops]$" ),     
 
  126    wxT( 
"^.*\\.g[0-9]{1,2}$" ),   
 
  127    wxT( 
"^.*\\.gm[0-9]{1,2}$" ),  
 
  131    wxT( 
"^.*\\.html$" ),
 
  142    wxT( 
"^.*\\.kicad_jobset" ),   
 
 
  225        wxSashLayoutWindow( parent, 
ID_LEFT_FRAME, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL )
 
  236    Bind( wxEVT_FSWATCHER,
 
  239    Bind( wxEVT_SYS_COLOUR_CHANGED,
 
  253    m_filters.emplace_back( wxT( 
"^no KiCad files found" ) );
 
 
  261    Unbind( wxEVT_FSWATCHER,
 
  263    Unbind( wxEVT_SYS_COLOUR_CHANGED,
 
 
  290    if( tree_data.size() != 1 )
 
  293    wxString prj_filename = tree_data[0]->GetFileName();
 
  295    m_Parent->LoadProject( prj_filename );
 
 
  307        wxString curr_dir = item_data->GetDir();
 
  309        if( curr_dir.IsEmpty() )
 
  312            curr_dir = wxPathOnly( 
m_Parent->GetProjectFileName() );
 
  315            if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
 
  318            if( !curr_dir.IsEmpty() )
 
  319                curr_dir += wxFileName::GetPathSeparator();
 
 
  334        wxString prj_dir = wxPathOnly( 
m_Parent->GetProjectFileName() );
 
  337        wxString curr_dir = item_data->GetDir();
 
  339        if( curr_dir.IsEmpty() )
 
  342        wxString new_dir = wxGetTextFromUser( 
_( 
"Directory name:" ), 
_( 
"Create New Directory" ) );
 
  344        if( new_dir.IsEmpty() )
 
  347        wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir;
 
  349        if( !wxMkdir( full_dirname ) )
 
 
  396    return wxEmptyString;
 
 
  402    std::vector<wxString> projects;
 
  403    wxString              dir_filename;
 
  404    bool                  haveFile = dir.GetFirst( &dir_filename );
 
  408        wxFileName file( dir_filename );
 
  412            projects.push_back( file.GetName() );
 
  414        haveFile = dir.GetNext( &dir_filename );
 
 
  425                                                      const wxTreeItemId& aParent,
 
  426                                                      std::vector<wxString>* aProjectNames,
 
  430    wxFileName     fn( aName );
 
  433        return wxTreeItemId();
 
  435    if( wxDirExists( aName ) )
 
  443        bool    addFile = 
false;
 
  445        for( 
const wxString& m_filter : 
m_filters )
 
  447            wxCHECK2_MSG( reg.Compile( m_filter, wxRE_ICASE ), 
continue,
 
  448                          wxString::Format( 
"Regex %s failed to compile.", m_filter ) );
 
  450            if( reg.Matches( aName ) )
 
  458            return wxTreeItemId();
 
  465            if( ext == wxT( 
"" ) )
 
  468            if( reg.Compile( wxString::FromAscii( 
"^.*\\." ) + ext + wxString::FromAscii( 
"$" ), wxRE_ICASE )
 
  469                    && reg.Matches( aName ) )
 
  477    wxString   file = wxFileNameFromPath( aName );
 
  478    wxFileName currfile( file );
 
  480    bool       showAllSchematics = 
m_TreeProject->GetGitRepo() != 
nullptr;
 
  484            && ( currfile.GetName().CmpNoCase( 
project.GetName() ) == 0 ) )
 
  486        return wxTreeItemId();
 
  495                return wxTreeItemId();
 
  500            wxDir                 parentDir( parentTreeItem->
GetDir() );
 
  501            std::vector<wxString> projects = 
getProjects( parentDir );
 
  504                return wxTreeItemId();
 
  509    wxTreeItemIdValue cookie;
 
  510    wxTreeItemId      kid = 
m_TreeProject->GetFirstChild( aParent, cookie );
 
  517            return itemData->GetId();    
 
  538                if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 )
 
  544                            return wxTreeItemId();
 
  550                            return wxTreeItemId();
 
  577    wxTreeItemId       newItemId = 
m_TreeProject->AppendItem( aParent, file );
 
  584    wxString fileName = currfile.GetName().Lower();
 
  585    wxString projName = 
project.GetName().Lower();
 
  587    if( fileName == projName || fileName.StartsWith( projName + 
"-" ) )
 
  591    bool subdir_populated = 
false;
 
  602            std::vector<wxString> projects = 
getProjects( dir );
 
  603            wxString              dir_filename;
 
  604            bool                  haveFile = dir.GetFirst( &dir_filename );
 
  609            subdir_populated = aRecurse;
 
  615                wxString 
path = aName + wxFileName::GetPathSeparator() + dir_filename;
 
  618                haveFile = dir.GetNext( &dir_filename );
 
  627    if( subdir_populated )
 
 
  641    while( 
tp.get_tasks_running() )
 
  643        tp.wait_for( std::chrono::milliseconds( 250 ) );
 
  651    wxString pro_dir = 
m_Parent->GetProjectFileName();
 
  669    wxFileName fn = pro_dir;
 
  670    bool prjReset = 
false;
 
  681    bool prjOpened = fn.FileExists();
 
  684    if( 
Pgm().GetCommonSettings()->m_Git.enableGit )
 
  690            m_TreeProject->GitCommon()->SetUsername( 
Prj().GetLocalSettings().m_GitRepoUsername );
 
  691            m_TreeProject->GitCommon()->SetSSHKey( 
Prj().GetLocalSettings().m_GitSSHKey );
 
  698    if( !prjOpened && !prjReset )
 
  701        prjOpened = fn.FileExists();
 
  721        pro_dir = wxPathOnly( 
m_Parent->GetProjectFileName() );
 
  722        wxDir dir( pro_dir );
 
  726            std::vector<wxString> projects = 
getProjects( dir );
 
  728            bool                  haveFile = dir.GetFirst( &filename );
 
  732                if( filename != fn.GetFullName() )
 
  734                    wxString 
name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
 
  741                haveFile = dir.GetNext( &filename );
 
  758                wxLogTrace( 
traceGit, 
"PROJECT_TREE_PANE::ReCreateTreePrj: starting timers" );
 
 
  777    wxTreeItemId curr_item = Event.GetItem();
 
  784    wxFileName prj_dir( 
Prj().GetProjectPath(), wxEmptyString );
 
  786    prj_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
 
  787                       | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
 
  788    git_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
 
  789                       | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
 
  790    wxString  prj_name = prj_dir.GetFullPath();
 
  791    wxString  git_name = git_dir.GetFullPath();
 
  793    bool can_switch_to_project = 
true;
 
  794    bool can_create_new_directory = 
true;
 
  795    bool can_open_this_directory = 
true;
 
  796    bool can_edit = 
true;
 
  797    bool can_rename = 
true;
 
  798    bool can_delete = 
true;
 
  799    bool run_jobs = 
false;
 
  803    bool vcs_can_init    = !vcs_has_repo;
 
  804    bool vcs_can_remove = vcs_has_repo && git_name.StartsWith( prj_name ); 
 
  807    bool vcs_can_pull    = vcs_can_fetch;
 
  808    bool vcs_can_switch  = vcs_has_repo;
 
  814    vcs_menu &= libgit_init;
 
  816    if( selection.size() == 0 )
 
  820    if( selection.size() != 1 )
 
  822        can_switch_to_project = 
false;
 
  823        can_create_new_directory = 
false;
 
  832            can_switch_to_project = 
false;
 
  838        can_delete = item->CanDelete();
 
  839        can_rename = item->CanRename();
 
  841        switch( item->GetType() )
 
  849                can_switch_to_project = 
false;
 
  853                can_create_new_directory = 
false;
 
  854                can_open_this_directory = 
false;
 
  859            can_switch_to_project = 
false;
 
  866            can_switch_to_project = 
false;
 
  867            can_create_new_directory = 
false;
 
  868            can_open_this_directory = 
false;
 
  881            can_switch_to_project = 
false;
 
  882            can_create_new_directory = 
false;
 
  883            can_open_this_directory = 
false;
 
  893    if( can_switch_to_project )
 
  896                           _( 
"Close all editors, and switch to the selected project" ),
 
  898        popup_menu.AppendSeparator();
 
  901    if( can_create_new_directory )
 
  907    if( can_open_this_directory )
 
  909        if( selection.size() == 1 )
 
  912            text = 
_( 
"Reveal in Finder" );
 
  913            help_text = 
_( 
"Reveals the directory in a Finder window" );
 
  915            text = 
_( 
"Open Directory in File Explorer" );
 
  916            help_text = 
_( 
"Opens the directory in the default system file manager" );
 
  922            text = 
_( 
"Reveal in Finder" );
 
  923            help_text = 
_( 
"Reveals the directories in a Finder window" );
 
  925            text = 
_( 
"Open Directories in File Explorer" );
 
  926            help_text = 
_( 
"Opens the directories in the default system file manager" );
 
  936        if( selection.size() == 1 )
 
  937            help_text = 
_( 
"Open the file in a Text Editor" );
 
  939            help_text = 
_( 
"Open files in a Text Editor" );
 
  945    if( run_jobs && selection.size() == 1 )
 
  953        if( selection.size() == 1 )
 
  955            text = 
_( 
"Rename File..." );
 
  956            help_text = 
_( 
"Rename file" );
 
  960            text = 
_( 
"Rename Files..." );
 
  961            help_text = 
_( 
"Rename files" );
 
  970        if( selection.size() == 1 )
 
  971            help_text = 
_( 
"Delete the file and its content" );
 
  973            help_text = 
_( 
"Delete the files and their contents" );
 
  975        if( can_switch_to_project
 
  976                || can_create_new_directory
 
  977                || can_open_this_directory
 
  981            popup_menu.AppendSeparator();
 
  995        wxMenu*     vcs_submenu = 
new wxMenu();
 
  996        wxMenu*     branch_submenu = 
new wxMenu();
 
  997        wxMenuItem* vcs_menuitem = 
nullptr;
 
 1000                                            _( 
"Add Project to Version Control..." ),
 
 1001                                            _( 
"Initialize a new repository" ) );
 
 1002        vcs_menuitem->Enable( vcs_can_init );
 
 1006                                            _( 
"Commit changes to the local repository" ) );
 
 1007        vcs_menuitem->Enable( vcs_can_commit );
 
 1009        vcs_menuitem = vcs_submenu->Append( 
ID_GIT_PUSH, 
_( 
"Push" ),
 
 1010                                            _( 
"Push committed local changes to remote repository" ) );
 
 1011        vcs_menuitem->Enable( vcs_can_push );
 
 1013        vcs_menuitem = vcs_submenu->Append( 
ID_GIT_PULL, 
_( 
"Pull" ),
 
 1014                                            _( 
"Pull changes from remote repository into local" ) );
 
 1015        vcs_menuitem->Enable( vcs_can_pull );
 
 1017        vcs_submenu->AppendSeparator();
 
 1020                                            _( 
"Commit changes to the local repository" ) );
 
 1021        vcs_menuitem->Enable( vcs_can_commit );
 
 1023        vcs_submenu->AppendSeparator();
 
 1029        std::vector<wxString> branchNames = 
m_TreeProject->GitCommon()->GetBranchNames();
 
 1032        for( 
size_t ii = 1; ii < branchNames.size() && ii < 6; ++ii )
 
 1034            wxString msg = 
_( 
"Switch to branch " ) + branchNames[ii];
 
 1036            vcs_menuitem->Enable( vcs_can_switch );
 
 1040                                     _( 
"Switch to a different branch" ) );
 
 1041        vcs_menuitem->Enable( vcs_can_switch );
 
 1045        vcs_submenu->AppendSeparator();
 
 1047        vcs_menuitem = vcs_submenu->Append( 
ID_GIT_REMOVE_VCS, 
_( 
"Remove Version Control" ),
 
 1048                             _( 
"Delete all version control files from the project directory." ) );
 
 1049        vcs_menuitem->Enable( vcs_can_remove );
 
 1051        popup_menu.AppendSeparator();
 
 1052        popup_menu.AppendSubMenu( vcs_submenu, 
_( 
"Version Control" ) );
 
 1055    if( popup_menu.GetMenuItemCount() > 0 )
 
 1056        PopupMenu( &popup_menu );
 
 
 1064    if( editorname.IsEmpty() )
 
 1066        wxMessageBox( 
_( 
"No text editor selected in KiCad.  Please choose one." ) );
 
 1074        wxString fullFileName = item_data->GetFileName();
 
 1076        if( !fullFileName.IsEmpty() )
 
 1078            ExecuteFile( editorname, fullFileName.wc_str(), 
nullptr, 
false );
 
 
 1089        item_data->Delete();
 
 
 1099    if( tree_data.size() != 1 )
 
 1103    wxString msg = wxString::Format( 
_( 
"Change filename: '%s'" ),
 
 1104                                     tree_data[0]->GetFileName() );
 
 1105    wxTextEntryDialog dlg( wxGetTopLevelParent( 
this ), msg, 
_( 
"Change filename" ), buffer );
 
 1107    if( dlg.ShowModal() != wxID_OK )
 
 1110    buffer = dlg.GetValue();
 
 1111    buffer.Trim( 
true );
 
 1112    buffer.Trim( 
false );
 
 1114    if( buffer.IsEmpty() )
 
 1117    tree_data[0]->Rename( buffer, 
true );
 
 
 1126    if( tree_data.size() != 1 )
 
 
 1149        std::vector<wxTreeItemId> validItemIds;
 
 1152        for( wxTreeItemId 
id : validItemIds )
 
 
 1171    wxTreeItemId       itemId    = Event.GetItem();
 
 1181    wxTreeItemIdValue   cookie;
 
 1182    wxTreeItemId        kid = 
m_TreeProject->GetFirstChild( itemId, cookie );
 
 1185    bool subdir_populated = 
false;
 
 1188    for( ; kid.IsOk(); kid = 
m_TreeProject->GetNextChild( itemId, cookie ) )
 
 1199        wxDir       dir( fileName );
 
 1201        if( dir.IsOpened() )
 
 1203            std::vector<wxString> projects = 
getProjects( dir );
 
 1204            wxString              dir_filename;
 
 1205            bool                  haveFile = dir.GetFirst( &dir_filename );
 
 1210                wxString 
name = fileName + wxFileName::GetPathSeparator() + dir_filename;
 
 1213                haveFile = dir.GetNext( &dir_filename );
 
 1219            subdir_populated = 
true;
 
 1228    if( subdir_populated )
 
 
 1236    wxArrayTreeItemIds              selection;
 
 1237    std::vector<PROJECT_TREE_ITEM*> data;
 
 1241    for( 
const wxTreeItemId itemId : selection )
 
 1247            wxLogTrace( 
traceGit, wxS( 
"Null tree item returned for selection, dynamic_cast failed?" ) );
 
 1251        data.push_back( item );
 
 
 1266    wxString prj_dir = wxPathOnly( 
m_Parent->GetProjectFileName() );
 
 1270    if( prj_dir == aSubDir )
 
 1274    wxTreeItemIdValue        cookie;
 
 1275    wxTreeItemId             root_id = 
m_root;
 
 1276    std::stack<wxTreeItemId> subdirs_id;
 
 1278    wxTreeItemId child = 
m_TreeProject->GetFirstChild( root_id, cookie );
 
 1282        if( ! child.IsOk() )
 
 1284            if( subdirs_id.empty() )    
 
 1291                root_id = subdirs_id.top();
 
 1312                subdirs_id.push( child );
 
 
 1330    if( !( event.GetChangeType() & ( wxFSW_EVENT_CREATE |
 
 1331                                     wxFSW_EVENT_DELETE |
 
 1332                                     wxFSW_EVENT_RENAME |
 
 1333                                     wxFSW_EVENT_MODIFY ) ) )
 
 1338    const wxFileName& pathModified = 
event.GetPath();
 
 1339    wxString subdir = pathModified.GetPath();
 
 1340    wxString fn = pathModified.GetFullPath();
 
 1343    if( pathModified.GetFullName().IsEmpty() )
 
 1345        subdir = subdir.BeforeLast( 
'/' );
 
 1346        fn = fn.BeforeLast( 
'/' );
 
 1351    if( !root_id.IsOk() )
 
 1354    CallAfter( [
this] ()
 
 1356        wxLogTrace( 
traceGit, wxS( 
"File system event detected, updating tree cache" ) );
 
 1360    wxTreeItemIdValue  cookie;  
 
 1361    wxTreeItemId kid = 
m_TreeProject->GetFirstChild( root_id, cookie );
 
 1363    switch( event.GetChangeType() )
 
 1365    case wxFSW_EVENT_CREATE:
 
 1380    case wxFSW_EVENT_DELETE:
 
 1394    case wxFSW_EVENT_RENAME :
 
 1396        const wxFileName& newpath = 
event.GetNewPath();
 
 1397        wxString newdir = newpath.GetPath();
 
 1398        wxString newfn = newpath.GetFullPath();
 
 1422        if( rootData && newpath.Exists() && ( newfn != rootData->
GetFileName() ) )
 
 1428            if( newitem.IsOk() )
 
 
 1449    wxString prj_dir = wxPathOnly( 
m_Parent->GetProjectFileName() );
 
 1451#if defined( _WIN32 ) 
 1460        m_Parent->m_FileWatcherInfo = 
_( 
"Network path: not monitoring folder changes" );
 
 1466        m_Parent->m_FileWatcherInfo = 
_( 
"Local path: monitoring folder changes" );
 
 1484    fn.AssignDir( prj_dir );
 
 1485    fn.DontFollowLink();
 
 1499                        TO_UTF8( fn.GetFullPath() ) );
 
 1507                        TO_UTF8( fn.GetFullPath() ) );
 
 1512    if( m_TreeProject->IsEmpty() )
 
 1516    wxTreeItemIdValue  cookie;
 
 1517    wxTreeItemId       root_id = m_root;
 
 1519    std::stack < wxTreeItemId > subdirs_id;
 
 1521    wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie );
 
 1522    int total_watch_count = 0;
 
 1528            if( subdirs_id.empty() )    
 
 1534                root_id = subdirs_id.top();
 
 1536                kid = m_TreeProject->GetFirstChild( root_id, cookie );
 
 1552            if( wxFileName::IsDirReadable( 
path ) )   
 
 1557                    fn.AssignDir( 
path );
 
 1558                    m_watcher->Add( fn );
 
 1559                    total_watch_count++;
 
 1563                if( itemData->
IsPopulated() && m_TreeProject->GetChildrenCount( kid ) )
 
 1564                    subdirs_id.push( kid );
 
 1568        kid = m_TreeProject->GetNextChild( root_id, cookie );
 
 1575#if defined(DEBUG) && 1 
 1576    wxArrayString paths;
 
 1577    m_watcher->GetWatchedPaths( &paths );
 
 1580    for( 
unsigned ii = 0; ii < paths.GetCount(); ii++ )
 
 
 1599        std::unique_lock<std::mutex> lock( 
m_TreeProject->GitCommon()->m_gitActionMutex, std::try_to_lock );
 
 1601        if( !lock.owns_lock() )
 
 1605                wxProgressDialog progress( 
_( 
"Please wait" ), 
_( 
"Waiting for Git operations to finish..." ),
 
 1606                                           100, 
this, wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_SMOOTH );
 
 1609                while ( !lock.try_lock() )
 
 1612                    std::this_thread::sleep_for( std::chrono::milliseconds(100) );
 
 
 1638    wxRect    rect( wxPoint( 0, 0 ), GetClientSize() );
 
 1639    wxPaintDC dc( 
this );
 
 1641    dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
 
 1642    dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
 
 1644    dc.DrawLine( rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetBottom() );
 
 1645    dc.DrawLine( rect.GetRight(), rect.GetTop(), rect.GetRight(), rect.GetBottom() );
 
 
 1659    wxString dir = tree_data->
GetDir();
 
 1663        wxLogError( 
"Failed to initialize git project: project directory is empty." );
 
 1668    wxWindow*        topLevelParent = wxGetTopLevelParent( 
this );
 
 1673                            _( 
"The selected directory is already a Git project." ) );
 
 1688    dlg.SetTitle( 
_( 
"Set default remote" ) );
 
 
 1743    handler.
SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>( 
this, 
_( 
"Fetch Remote" ), 1,
 
 
 1766    handler.
SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>( 
this, 
_( 
"Fetch Remote" ), 1,
 
 
 1786    wxString branchName;
 
 1795        if( retval == wxID_ADD )
 
 1797        else if( retval != wxID_OK )
 
 1802        std::vector<wxString> branches = 
m_TreeProject->GitCommon()->GetBranchNames();
 
 1805        if( branchIndex < 0 || 
static_cast<size_t>( branchIndex ) >= branches.size() )
 
 1808        branchName = branches[branchIndex];
 
 1811    wxLogTrace( 
traceGit, wxS( 
"onGitSwitchBranch: Switching to branch '%s'" ), branchName );
 
 
 1824      || !
IsOK( wxGetTopLevelParent( 
this ),
 
 1825                _( 
"Are you sure you want to remove Git tracking from this project?" ) ) )
 
 1831    wxLogTrace( 
traceGit, wxS( 
"onGitRemoveVCS: Removing VCS from project" ) );
 
 1843    std::stack<wxTreeItemId> items;
 
 1846    while( !items.empty() )
 
 1848        wxTreeItemId current = items.top();
 
 1852        m_TreeProject->SetItemState( current, wxTREE_ITEMSTATE_NONE );
 
 1854        wxTreeItemIdValue cookie;
 
 1855        wxTreeItemId      child = 
m_TreeProject->GetFirstChild( current, cookie );
 
 1857        while( child.IsOk() )
 
 1859            items.push( child );
 
 
 1868    wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIcons: Updating git status icons" ) );
 
 1871    if( !lock.owns_lock() )
 
 1873        wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIcons: Failed to acquire lock for git status icon update" ) );
 
 1880        wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIcons: Git is disabled or tree control is null" ) );
 
 1884    std::stack<wxTreeItemId> items;
 
 1887    while( !items.empty() )
 
 1889        wxTreeItemId current = items.top();
 
 1894            wxTreeItemIdValue cookie;
 
 1895            wxTreeItemId      child = 
m_TreeProject->GetFirstChild( current, cookie );
 
 1897            while( child.IsOk() )
 
 1899                items.push( child );
 
 1903                    m_TreeProject->SetItemState( child, 
static_cast<int>( it->second ) );
 
 1915        wxString filename = wxFileNameFromPath( rootItem->
GetFileName() );
 
 1920    wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIcons: Git status icons updated" ) );
 
 
 1926    wxLogTrace( 
traceGit, wxS( 
"updateTreeCache: Updating tree cache" ) );
 
 1930    if( !lock.owns_lock() )
 
 1932        wxLogTrace( 
traceGit, wxS( 
"updateTreeCache: Failed to acquire lock for tree cache update" ) );
 
 1938        wxLogTrace( 
traceGit, wxS( 
"updateTreeCache: Tree control is null" ) );
 
 1949    std::stack<wxTreeItemId> items;
 
 1952    while( !items.empty() )
 
 1964        gitAbsPath.Replace( wxS( 
"\\" ), wxS( 
"/" ) );
 
 1968        wxTreeItemIdValue cookie;
 
 1969        wxTreeItemId      child = 
m_TreeProject->GetFirstChild( kid, cookie );
 
 1971        while( child.IsOk() )
 
 1973            items.push( child );
 
 
 1982    wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIconMap: Updating git status icons" ) );
 
 1983#if defined( _WIN32 ) 
 2006    if( !lock1.owns_lock() || !lock2.owns_lock() )
 
 2008        wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIconMap: Failed to acquire locks for git status icon update" ) );
 
 2014        wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIconMap: No git repository found" ) );
 
 2021    wxFileName         rootFilename( 
Prj().GetProjectFullName() );
 
 2024    wxFileName relative = rootFilename;
 
 2025    relative.MakeRelativeTo( repoWorkDir );
 
 2026    wxString pathspecStr = relative.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
 
 2029    pathspecStr.Replace( wxS( 
"\\" ), wxS( 
"/" ) );
 
 2033    auto fileStatusMap = statusHandler.
GetFileStatus( pathspecStr );
 
 2034    auto [localChanges, remoteChanges] = 
m_TreeProject->GitCommon()->GetDifferentFiles();
 
 2037    bool updated = 
false;
 
 2040    for( 
const auto& [absPath, fileStatus] : fileStatusMap )
 
 2045            wxLogTrace( 
traceGit, wxS( 
"File '%s' not found in tree cache" ), absPath );
 
 2049        auto [it, inserted] = 
m_gitStatusIcons.try_emplace( iter->second, fileStatus.status );
 
 2050        if( inserted || it->second != fileStatus.status )
 
 2052        it->second = fileStatus.status;
 
 2058    wxLogTrace( 
traceGit, wxS( 
"updateGitStatusIconMap: Updated git status icons" ) );
 
 
 2078    if( repo == 
nullptr )
 
 2080        wxMessageBox( 
_( 
"The selected directory is not a Git project." ) );
 
 2092    std::map<wxString, int> modifiedFiles;
 
 2093    std::set<wxString> selected_files;
 
 2098            selected_files.emplace( item->GetFileName() );
 
 2103    for( 
const auto& [absPath, fileStatus] : fileStatusMap )
 
 2113        wxFileName fn( absPath );
 
 2116        wxString relativePath = absPath;
 
 2117        if( relativePath.StartsWith( repoWorkDir ) )
 
 2119            relativePath = relativePath.Mid( repoWorkDir.length() );
 
 2121            relativePath.Replace( wxS( 
"\\" ), wxS( 
"/" ) );
 
 2127        if( !absPath.StartsWith( projectPath ) )
 
 2142        if( fn.GetPath().Contains( 
Prj().GetProjectName() + wxT( 
"-backups" ) ) )
 
 2147            modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
 
 2149        else if( selected_files.count( absPath ) )
 
 2151            modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
 
 2160    if( ret != wxID_OK )
 
 2167        wxMessageBox( 
_( 
"Discarding commit due to empty commit message." ) );
 
 2173        wxMessageBox( 
_( 
"Discarding commit due to empty file selection." ) );
 
 2183        wxMessageBox( wxString::Format( 
_( 
"Failed to create commit: %s" ),
 
 2188    wxLogTrace( 
traceGit, wxS( 
"Created commit" ) );
 
 
 2208    for( 
const auto& [filePath, fileStatus] : fileStatusMap )
 
 2210        if( filePath.EndsWith( aFile ) || filePath == aFile )
 
 
 2224    wxLogTrace( 
traceGit, 
"Syncing project" );
 
 2229        wxLogTrace( 
traceGit, 
"sync: No git repository found" );
 
 
 2296    wxLogTrace( 
traceGit, 
"onGitSyncTimer" );
 
 2304    tp.detach_task( [
this]()
 
 2310            wxLogTrace( 
traceGit, 
"onGitSyncTimer: No git repository found" );
 
 2322        wxLogTrace( 
traceGit, 
"onGitSyncTimer: Restarting git sync timer" );
 
 
 2339    wxLogTrace( 
traceGit, 
"onGitStatusTimer" );
 
 
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
 
BITMAP_STORE * GetBitmapStore()
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
 
wxString GetCommitMessage() const
 
wxString GetAuthorEmail() const
 
std::vector< wxString > GetSelectedFiles() const
 
wxString GetAuthorName() const
 
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const
 
wxString GetRepoSSHPath() const
 
wxString GetRepoURL() const
 
wxString GetUsername() const
 
wxString GetPassword() const
 
void SetSkipButtonLabel(const wxString &aLabel)
 
wxString GetBranchName() const
 
virtual bool IsLibraryAvailable()=0
 
BranchResult SwitchToBranch(const wxString &aBranchName)
Switch to the specified branch.
 
CommitResult PerformCommit(const std::vector< wxString > &aFiles, const wxString &aMessage, const wxString &aAuthorName, const wxString &aAuthorEmail)
 
wxString GetErrorString() const
 
GitUserConfig GetUserConfig()
Get user configuration (name and email) from git config Falls back to common settings if not found in...
 
bool IsRepository(const wxString &aPath)
Check if a directory is already a git repository.
 
InitResult InitializeRepository(const wxString &aPath)
Initialize a new git repository in the specified directory.
 
bool SetupRemote(const RemoteConfig &aConfig)
Set up a remote for the repository.
 
void SetProgressReporter(std::unique_ptr< WX_PROGRESS_REPORTER > aProgressReporter)
 
bool PerformFetch(bool aSkipLock=false)
 
void PerformRemoveFromIndex()
 
bool PerformResolveConflict()
 
wxString GetCurrentBranchName()
Get the current branch name.
 
void UpdateRemoteStatus(const std::set< wxString > &aLocalChanges, const std::set< wxString > &aRemoteChanges, std::map< wxString, FileStatus > &aFileStatus)
Get status for modified files based on local/remote changes.
 
wxString GetWorkingDirectory()
Get the repository working directory path.
 
bool HasChangedFiles()
Check if the repository has any changed files.
 
std::map< wxString, FileStatus > GetFileStatus(const wxString &aPathspec=wxEmptyString)
Get detailed file status for all files in the specified path.
 
The main KiCad project manager frame.
 
PROJECT_TREE_PANE * m_leftWin
 
void OnChangeWatchedPaths(wxCommandEvent &aEvent)
Called by sending a event with id = ID_INIT_WATCHED_PATHS rebuild the list of watched paths.
 
static git_repository * GetRepositoryForFile(const char *aFilename)
Discover and open the repository that contains the given file.
 
static bool RemoveVCS(git_repository *&aRepo, const wxString &aProjectPath=wxEmptyString, bool aRemoveGitDir=false, wxString *aErrors=nullptr)
Remove version control from a directory by freeing the repository and optionally removing the ....
 
static int CreateBranch(git_repository *aRepo, const wxString &aBranchName)
Create a new branch based on HEAD.
 
wxString GetGitRootDirectory() const
 
bool HasPushAndPullRemote() const
 
bool HasLocalCommits() const
 
wxString GetErrorString()
 
git_repository * GetRepo() const
Get a pointer to the git repository.
 
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
 
void SetEllipsedTextField(const wxString &aText, int aFieldId)
Set the text in a field using wxELLIPSIZE_MIDDLE option to adjust the text size to the field size.
 
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
 
virtual COMMON_SETTINGS * GetCommonSettings() const
 
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
 
wxString m_GitRepoUsername
 
Handle one item (a file or a directory name) for the tree file.
 
void SetRootFile(bool aValue)
 
const wxString & GetFileName() const
 
void SetPopulated(bool aValue)
 
TREE_FILE_TYPE GetType() const
 
const wxString GetDir() const
 
void Activate(PROJECT_TREE_PANE *aTreePrjFrame)
 
PROJECT_TREE_PANE Window to display the tree files.
 
PROJECT_TREE_ITEM * m_selectedItem
 
std::unordered_map< wxString, wxTreeItemId > m_gitTreeCache
 
void onGitFetch(wxCommandEvent &event)
Fetch the latest changes from the git repository.
 
std::map< wxTreeItemId, KIGIT_COMMON::GIT_STATUS > m_gitStatusIcons
 
void onGitInitializeProject(wxCommandEvent &event)
Initialize a new git repository in the current project directory.
 
void onGitSyncProject(wxCommandEvent &event)
Sync the current project with the git repository.
 
void onDeleteFile(wxCommandEvent &event)
Function onDeleteFile Delete the selected file or directory in the tree project.
 
void onGitRemoveVCS(wxCommandEvent &event)
Remove the git repository from the current project directory.
 
void EmptyTreePrj()
Delete all m_TreeProject entries.
 
void FileWatcherReset()
Reinit the watched paths Should be called after opening a new project to rebuild the list of watched ...
 
wxString m_gitCurrentBranchName
 
std::vector< PROJECT_TREE_ITEM * > GetSelectedData()
Function GetSelectedData return the item data from item currently selected (highlighted) Note this is...
 
void onOpenDirectory(wxCommandEvent &event)
Function onOpenDirectory Handles the right-click menu for opening a directory in the current system f...
 
void onGitResolveConflict(wxCommandEvent &event)
Resolve conflicts in the git repository.
 
void onFileSystemEvent(wxFileSystemWatcherEvent &event)
called when a file or directory is modified/created/deleted The tree project is modified when a file ...
 
wxFileSystemWatcher * m_watcher
 
void onRight(wxTreeEvent &Event)
Called on a right click on an item.
 
void onGitCommit(wxCommandEvent &event)
Commit the current project saved changes to the git repository.
 
void onSelect(wxTreeEvent &Event)
Called on a double click on an item.
 
PROJECT_TREE * m_TreeProject
 
PROJECT_TREE_PANE(KICAD_MANAGER_FRAME *parent)
 
KICAD_MANAGER_FRAME * m_Parent
 
void onExpand(wxTreeEvent &Event)
Called on a click on the + or - button of an item with children.
 
void onGitSyncTimer(wxTimerEvent &event)
 
void onIdle(wxIdleEvent &aEvent)
Idle event handler, used process the selected items at a point in time when all other events have bee...
 
void updateTreeCache()
Updates the map of the wxtreeitemid to the name of each file for use in the thread.
 
void gitStatusTimerHandler()
 
std::mutex m_gitStatusMutex
 
void onGitRevertLocal(wxCommandEvent &event)
Revert the local repository to the last commit.
 
void onGitPullProject(wxCommandEvent &event)
Pull the latest changes from the git repository.
 
static wxString GetFileExt(TREE_FILE_TYPE type)
 
friend class PROJECT_TREE_ITEM
 
void onGitRemoveFromIndex(wxCommandEvent &event)
Remove a file from the git index.
 
wxTreeItemId findSubdirTreeItem(const wxString &aSubDir)
Function findSubdirTreeItem searches for the item in tree project which is the node of the subdirecto...
 
void ReCreateTreePrj()
Create or modify the tree showing project file names.
 
void onThemeChanged(wxSysColourChangedEvent &aEvent)
 
void onRunSelectedJobsFile(wxCommandEvent &event)
Run a selected jobs file.
 
void onGitCompare(wxCommandEvent &event)
Compare the current project to a different branch in the git repository.
 
void onGitStatusTimer(wxTimerEvent &event)
 
void shutdownFileWatcher()
Shutdown the file watcher.
 
std::mutex m_gitTreeCacheMutex
 
wxTreeItemId addItemToProjectTree(const wxString &aName, const wxTreeItemId &aParent, std::vector< wxString > *aProjectNames, bool aRecurse)
Function addItemToProjectTree.
 
bool hasChangedFiles()
Returns true if the current project has any uncommitted changes.
 
void onOpenSelectedFileWithTextEditor(wxCommandEvent &event)
Function onOpenSelectedFileWithTextEditor Call the text editor to open the selected file in the tree ...
 
void onGitAddToIndex(wxCommandEvent &event)
Add a file to the git index.
 
void updateGitStatusIcons()
Updates the icons shown in the tree project to reflect the current git status.
 
bool m_gitIconsInitialized
 
void updateGitStatusIconMap()
This is a threaded call that will change the map of git status icons for use in the main thread.
 
PROJECT_TREE_ITEM * GetItemIdData(wxTreeItemId aId)
Function GetItemIdData return the item data corresponding to a wxTreeItemId identifier.
 
void onGitSwitchBranch(wxCommandEvent &event)
Switch to a different branch in the git repository.
 
void onCreateNewDirectory(wxCommandEvent &event)
Function onCreateNewDirectory Creates a new subdirectory inside the current kicad project directory t...
 
void onSwitchToSelectedProject(wxCommandEvent &event)
Switch to a other project selected from the tree project (by selecting an other .pro file inside the ...
 
void onPaint(wxPaintEvent &aEvent)
We don't have uniform borders so we have to draw them ourselves.
 
void onRenameFile(wxCommandEvent &event)
Function onRenameFile Rename the selected file or directory in the tree project.
 
void onGitPushProject(wxCommandEvent &event)
Push the current project changes to the git repository.
 
bool canFileBeAddedToVCS(const wxString &aFilePath)
Returns true if the file has already been added to the repository or false if it has not been added y...
 
std::vector< wxString > m_filters
 
PROJECT_TREE This is the class to show (as a tree) the files in the project directory.
 
virtual const wxString GetProjectPath() const
Return the full path of the project.
 
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
 
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
 
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
 
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
 
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
 
This file is part of the common library.
 
EVT_MENU_RANGE(ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILEMAX, GERBVIEW_FRAME::OnDrlFileHistory) EVT_MENU_RANGE(ID_GERBVIEW_ZIP_FILE1
 
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
 
GIT_BACKEND * GetGitBackend()
 
int m_GitIconRefreshInterval
The interval in milliseconds to refresh the git icons in the project tree.
 
static const std::string LegacySchematicFileExtension
 
static const std::string HtmlFileExtension
 
static const wxString GerberFileExtensionsRegex
 
static const std::string NetlistFileExtension
 
static const std::string GerberJobFileExtension
 
static const std::string ReportFileExtension
 
static const std::string LockFileExtension
 
static const std::string ProjectFileExtension
 
static const std::string FootprintPlaceFileExtension
 
static const std::string LegacyPcbFileExtension
 
static const std::string LegacyProjectFileExtension
 
static const std::string KiCadSchematicFileExtension
 
static const std::string LegacySymbolLibFileExtension
 
static const std::string LockFilePrefix
 
static const std::string KiCadSymbolLibFileExtension
 
static const std::string SpiceFileExtension
 
static const std::string PdfFileExtension
 
static const std::string TextFileExtension
 
static const std::string DrawingSheetFileExtension
 
static const std::string BackupFileSuffix
 
static const std::string KiCadJobSetFileExtension
 
static const std::string FootprintAssignmentFileExtension
 
static const std::string SVGFileExtension
 
static const std::string DrillFileExtension
 
static const std::string DesignRulesFileExtension
 
static const std::string MarkdownFileExtension
 
static const std::string KiCadFootprintFileExtension
 
static const std::string ArchiveFileExtension
 
static const std::string KiCadPcbFileExtension
 
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
 
const wxChar *const traceGit
Flag to enable Git debugging output.
 
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
 
This file contains miscellaneous commonly used macros and functions.
 
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
 
KICOMMON_API wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmapBundle &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
 
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
 
wxDECLARE_EVENT(wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent)
 
PGM_BASE & Pgm()
The global program "get" accessor.
 
#define NAMELESS_PROJECT
default name for nameless projects
 
project_tree_ids
The frame that shows the tree list of files and subdirectories inside the working directory.
 
@ ID_PROJECT_SWITCH_TO_OTHER
 
@ ID_GIT_REMOVE_FROM_INDEX
 
@ ID_GIT_RESOLVE_CONFLICT
 
@ ID_GIT_INITIALIZE_PROJECT
 
std::vector< wxString > getProjects(const wxDir &dir)
 
static const wxChar * s_allowedExtensionsToList[]
 
#define wxFileSystemWatcher
 
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
 
KIGIT_COMMON::GIT_CONN_TYPE connType
 
wxString result
Test unit parsing edge cases and error handling.
 
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
 
BS::thread_pool< 0 > thread_pool
 
wxLogTrace helper definitions.
 
Definition of file extensions used in Kicad.