30#include <wx/stdpaths.h>
33#include <wx/textdlg.h>
35#include <wx/wupdlock.h>
56#include <wx/dcclient.h>
57#include <wx/progdlg.h>
58#include <wx/settings.h>
107 wxT(
"^.*\\.kicad_pro$" ),
110 wxT(
"^.*\\.kicad_sch$" ),
111 wxT(
"^[^$].*\\.brd$" ),
112 wxT(
"^[^$].*\\.kicad_pcb$" ),
113 wxT(
"^[^$].*\\.kicad_dru$" ),
114 wxT(
"^[^$].*\\.kicad_wks$" ),
115 wxT(
"^[^$].*\\.kicad_mod$" ),
119 wxT(
"^.*\\.kicad_sym$" ),
124 wxT(
"^.*\\.gbrjob$" ),
125 wxT(
"^.*\\.gb[alops]$" ),
126 wxT(
"^.*\\.gt[alops]$" ),
127 wxT(
"^.*\\.g[0-9]{1,2}$" ),
128 wxT(
"^.*\\.gm[0-9]{1,2}$" ),
132 wxT(
"^.*\\.html$" ),
143 wxT(
"^.*\\.kicad_jobset" ),
226 wxSashLayoutWindow( parent,
ID_LEFT_FRAME, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL )
237 Bind( wxEVT_FSWATCHER,
240 Bind( wxEVT_SYS_COLOUR_CHANGED,
254 m_filters.emplace_back( wxT(
"^no KiCad files found" ) );
262 Unbind( wxEVT_FSWATCHER,
264 Unbind( wxEVT_SYS_COLOUR_CHANGED,
291 if( tree_data.size() != 1 )
294 wxString prj_filename = tree_data[0]->GetFileName();
296 m_Parent->LoadProject( prj_filename );
308 wxString curr_dir = item_data->GetDir();
310 if( curr_dir.IsEmpty() )
313 curr_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
316 if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
319 if( !curr_dir.IsEmpty() )
320 curr_dir += wxFileName::GetPathSeparator();
335 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
338 wxString curr_dir = item_data->GetDir();
340 if( curr_dir.IsEmpty() )
343 wxString new_dir = wxGetTextFromUser(
_(
"Directory name:" ),
_(
"Create New Directory" ) );
345 if( new_dir.IsEmpty() )
348 wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir;
350 if( !wxMkdir( full_dirname ) )
397 return wxEmptyString;
403 std::vector<wxString> projects;
404 wxString dir_filename;
405 bool haveFile = dir.GetFirst( &dir_filename );
409 wxFileName file( dir_filename );
413 projects.push_back( file.GetName() );
415 haveFile = dir.GetNext( &dir_filename );
426 const wxTreeItemId& aParent,
427 std::vector<wxString>* aProjectNames,
431 wxFileName fn( aName );
434 return wxTreeItemId();
436 if( wxDirExists( aName ) )
444 bool addFile =
false;
446 for(
const wxString& m_filter :
m_filters )
448 wxCHECK2_MSG( reg.Compile( m_filter, wxRE_ICASE ),
continue,
449 wxString::Format(
"Regex %s failed to compile.", m_filter ) );
451 if( reg.Matches( aName ) )
459 return wxTreeItemId();
466 if( ext == wxT(
"" ) )
469 if( reg.Compile( wxString::FromAscii(
"^.*\\." ) + ext + wxString::FromAscii(
"$" ), wxRE_ICASE )
470 && reg.Matches( aName ) )
478 wxString file = wxFileNameFromPath( aName );
479 wxFileName currfile( file );
481 bool showAllSchematics =
m_TreeProject->GetGitRepo() !=
nullptr;
485 && ( currfile.GetName().CmpNoCase(
project.GetName() ) == 0 ) )
487 return wxTreeItemId();
496 return wxTreeItemId();
501 wxDir parentDir( parentTreeItem->
GetDir() );
502 std::vector<wxString> projects =
getProjects( parentDir );
505 return wxTreeItemId();
510 wxTreeItemIdValue cookie;
511 wxTreeItemId kid =
m_TreeProject->GetFirstChild( aParent, cookie );
518 return itemData->GetId();
539 if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 )
545 return wxTreeItemId();
551 return wxTreeItemId();
578 wxTreeItemId newItemId =
m_TreeProject->AppendItem( aParent, file );
585 wxString fileName = currfile.GetName().Lower();
586 wxString projName =
project.GetName().Lower();
588 if( fileName == projName || fileName.StartsWith( projName +
"-" ) )
592 bool subdir_populated =
false;
603 std::vector<wxString> projects =
getProjects( dir );
604 wxString dir_filename;
605 bool haveFile = dir.GetFirst( &dir_filename );
610 subdir_populated = aRecurse;
616 wxString
path = aName + wxFileName::GetPathSeparator() + dir_filename;
619 haveFile = dir.GetNext( &dir_filename );
628 if( subdir_populated )
642 while(
tp.get_tasks_running() )
644 tp.wait_for( std::chrono::milliseconds( 250 ) );
652 wxString pro_dir =
m_Parent->GetProjectFileName();
670 wxFileName fn = pro_dir;
671 bool prjReset =
false;
682 bool prjOpened = fn.FileExists();
685 if(
Pgm().GetCommonSettings()->m_Git.enableGit )
691 m_TreeProject->GitCommon()->SetUsername(
Prj().GetLocalSettings().m_GitRepoUsername );
692 m_TreeProject->GitCommon()->SetSSHKey(
Prj().GetLocalSettings().m_GitSSHKey );
699 if( !prjOpened && !prjReset )
702 prjOpened = fn.FileExists();
722 pro_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
723 wxDir dir( pro_dir );
727 std::vector<wxString> projects =
getProjects( dir );
729 bool haveFile = dir.GetFirst( &filename );
733 if( filename != fn.GetFullName() )
735 wxString
name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
742 haveFile = dir.GetNext( &filename );
759 wxLogTrace(
traceGit,
"PROJECT_TREE_PANE::ReCreateTreePrj: starting timers" );
778 wxTreeItemId curr_item = Event.GetItem();
785 wxFileName prj_dir(
Prj().GetProjectPath(), wxEmptyString );
787 prj_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
788 | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
789 git_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
790 | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
791 wxString prj_name = prj_dir.GetFullPath();
792 wxString git_name = git_dir.GetFullPath();
794 bool can_switch_to_project =
true;
795 bool can_create_new_directory =
true;
796 bool can_open_this_directory =
true;
797 bool can_edit =
true;
798 bool can_rename =
true;
799 bool can_delete =
true;
800 bool run_jobs =
false;
804 bool vcs_can_init = !vcs_has_repo;
805 bool vcs_can_remove = vcs_has_repo && git_name.StartsWith( prj_name );
808 bool vcs_can_pull = vcs_can_fetch;
809 bool vcs_can_switch = vcs_has_repo;
815 vcs_menu &= libgit_init;
817 if( selection.size() == 0 )
821 if( selection.size() != 1 )
823 can_switch_to_project =
false;
824 can_create_new_directory =
false;
833 can_switch_to_project =
false;
839 can_delete = item->CanDelete();
840 can_rename = item->CanRename();
842 switch( item->GetType() )
850 can_switch_to_project =
false;
854 can_create_new_directory =
false;
855 can_open_this_directory =
false;
860 can_switch_to_project =
false;
867 can_switch_to_project =
false;
868 can_create_new_directory =
false;
869 can_open_this_directory =
false;
882 can_switch_to_project =
false;
883 can_create_new_directory =
false;
884 can_open_this_directory =
false;
894 if( can_switch_to_project )
897 _(
"Close all editors, and switch to the selected project" ),
899 popup_menu.AppendSeparator();
902 if( can_create_new_directory )
908 if( can_open_this_directory )
910 if( selection.size() == 1 )
913 text =
_(
"Reveal in Finder" );
914 help_text =
_(
"Reveals the directory in a Finder window" );
916 text =
_(
"Open Directory in File Explorer" );
917 help_text =
_(
"Opens the directory in the default system file manager" );
923 text =
_(
"Reveal in Finder" );
924 help_text =
_(
"Reveals the directories in a Finder window" );
926 text =
_(
"Open Directories in File Explorer" );
927 help_text =
_(
"Opens the directories in the default system file manager" );
937 if( selection.size() == 1 )
938 help_text =
_(
"Open the file in a Text Editor" );
940 help_text =
_(
"Open files in a Text Editor" );
946 if( run_jobs && selection.size() == 1 )
954 if( selection.size() == 1 )
956 text =
_(
"Rename File..." );
957 help_text =
_(
"Rename file" );
961 text =
_(
"Rename Files..." );
962 help_text =
_(
"Rename files" );
971 if( selection.size() == 1 )
972 help_text =
_(
"Delete the file and its content" );
974 help_text =
_(
"Delete the files and their contents" );
976 if( can_switch_to_project
977 || can_create_new_directory
978 || can_open_this_directory
982 popup_menu.AppendSeparator();
996 wxMenu* vcs_submenu =
new wxMenu();
997 wxMenu* branch_submenu =
new wxMenu();
998 wxMenuItem* vcs_menuitem =
nullptr;
1001 _(
"Add Project to Version Control..." ),
1002 _(
"Initialize a new repository" ) );
1003 vcs_menuitem->Enable( vcs_can_init );
1007 _(
"Commit changes to the local repository" ) );
1008 vcs_menuitem->Enable( vcs_can_commit );
1010 vcs_menuitem = vcs_submenu->Append(
ID_GIT_PUSH,
_(
"Push" ),
1011 _(
"Push committed local changes to remote repository" ) );
1012 vcs_menuitem->Enable( vcs_can_push );
1014 vcs_menuitem = vcs_submenu->Append(
ID_GIT_PULL,
_(
"Pull" ),
1015 _(
"Pull changes from remote repository into local" ) );
1016 vcs_menuitem->Enable( vcs_can_pull );
1018 vcs_submenu->AppendSeparator();
1021 _(
"Commit changes to the local repository" ) );
1022 vcs_menuitem->Enable( vcs_can_commit );
1024 vcs_submenu->AppendSeparator();
1030 std::vector<wxString> branchNames =
m_TreeProject->GitCommon()->GetBranchNames();
1033 for(
size_t ii = 1; ii < branchNames.size() && ii < 6; ++ii )
1035 wxString msg =
_(
"Switch to branch " ) + branchNames[ii];
1037 vcs_menuitem->Enable( vcs_can_switch );
1041 _(
"Switch to a different branch" ) );
1042 vcs_menuitem->Enable( vcs_can_switch );
1046 vcs_submenu->AppendSeparator();
1048 vcs_menuitem = vcs_submenu->Append(
ID_GIT_REMOVE_VCS,
_(
"Remove Version Control" ),
1049 _(
"Delete all version control files from the project directory." ) );
1050 vcs_menuitem->Enable( vcs_can_remove );
1052 popup_menu.AppendSeparator();
1053 popup_menu.AppendSubMenu( vcs_submenu,
_(
"Version Control" ) );
1056 if( popup_menu.GetMenuItemCount() > 0 )
1057 PopupMenu( &popup_menu );
1065 if( editorname.IsEmpty() )
1067 wxMessageBox(
_(
"No text editor selected in KiCad. Please choose one." ) );
1075 wxString fullFileName = item_data->GetFileName();
1077 if( !fullFileName.IsEmpty() )
1079 ExecuteFile( editorname, fullFileName.wc_str(),
nullptr,
false );
1090 item_data->Delete();
1100 if( tree_data.size() != 1 )
1104 wxString msg = wxString::Format(
_(
"Change filename: '%s'" ),
1105 tree_data[0]->GetFileName() );
1106 wxTextEntryDialog dlg( wxGetTopLevelParent(
this ), msg,
_(
"Change filename" ), buffer );
1108 if( dlg.ShowModal() != wxID_OK )
1111 buffer = dlg.GetValue();
1112 buffer.Trim(
true );
1113 buffer.Trim(
false );
1115 if( buffer.IsEmpty() )
1118 tree_data[0]->Rename( buffer,
true );
1127 if( tree_data.size() != 1 )
1150 std::vector<wxTreeItemId> validItemIds;
1153 for( wxTreeItemId
id : validItemIds )
1172 wxTreeItemId itemId = Event.GetItem();
1182 wxTreeItemIdValue cookie;
1183 wxTreeItemId kid =
m_TreeProject->GetFirstChild( itemId, cookie );
1186 bool subdir_populated =
false;
1189 for( ; kid.IsOk(); kid =
m_TreeProject->GetNextChild( itemId, cookie ) )
1200 wxDir dir( fileName );
1202 if( dir.IsOpened() )
1204 std::vector<wxString> projects =
getProjects( dir );
1205 wxString dir_filename;
1206 bool haveFile = dir.GetFirst( &dir_filename );
1211 wxString
name = fileName + wxFileName::GetPathSeparator() + dir_filename;
1214 haveFile = dir.GetNext( &dir_filename );
1220 subdir_populated =
true;
1229 if( subdir_populated )
1237 wxArrayTreeItemIds selection;
1238 std::vector<PROJECT_TREE_ITEM*> data;
1242 for(
const wxTreeItemId itemId : selection )
1248 wxLogTrace(
traceGit, wxS(
"Null tree item returned for selection, dynamic_cast failed?" ) );
1252 data.push_back( item );
1267 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
1271 if( prj_dir == aSubDir )
1275 wxTreeItemIdValue cookie;
1276 wxTreeItemId root_id =
m_root;
1277 std::stack<wxTreeItemId> subdirs_id;
1279 wxTreeItemId child =
m_TreeProject->GetFirstChild( root_id, cookie );
1283 if( ! child.IsOk() )
1285 if( subdirs_id.empty() )
1292 root_id = subdirs_id.top();
1313 subdirs_id.push( child );
1331 if( !( event.GetChangeType() & ( wxFSW_EVENT_CREATE |
1332 wxFSW_EVENT_DELETE |
1333 wxFSW_EVENT_RENAME |
1334 wxFSW_EVENT_MODIFY ) ) )
1339 const wxFileName& pathModified =
event.GetPath();
1340 wxString subdir = pathModified.GetPath();
1341 wxString fn = pathModified.GetFullPath();
1344 if( pathModified.GetFullName().IsEmpty() )
1346 subdir = subdir.BeforeLast(
'/' );
1347 fn = fn.BeforeLast(
'/' );
1352 if( !root_id.IsOk() )
1355 CallAfter( [
this] ()
1357 wxLogTrace(
traceGit, wxS(
"File system event detected, updating tree cache" ) );
1361 wxTreeItemIdValue cookie;
1362 wxTreeItemId kid =
m_TreeProject->GetFirstChild( root_id, cookie );
1364 switch( event.GetChangeType() )
1366 case wxFSW_EVENT_CREATE:
1381 case wxFSW_EVENT_DELETE:
1395 case wxFSW_EVENT_RENAME :
1397 const wxFileName& newpath =
event.GetNewPath();
1398 wxString newdir = newpath.GetPath();
1399 wxString newfn = newpath.GetFullPath();
1423 if( rootData && newpath.Exists() && ( newfn != rootData->
GetFileName() ) )
1429 if( newitem.IsOk() )
1450 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
1452#if defined( _WIN32 )
1461 m_Parent->m_FileWatcherInfo =
_(
"Network path: not monitoring folder changes" );
1467 m_Parent->m_FileWatcherInfo =
_(
"Local path: monitoring folder changes" );
1485 class WatcherLogHandler :
public wxLog
1488 explicit WatcherLogHandler(
bool* err ) :
1496 void DoLogTextAtLevel( wxLogLevel level,
const wxString&
text )
override
1498 if( m_err && ( level == wxLOG_Error || level == wxLOG_FatalError ) )
1506 bool watcherHasError =
false;
1507 WatcherLogHandler tmpLog( &watcherHasError );
1508 wxLog* oldLog = wxLog::SetActiveTarget( &tmpLog );
1514 wxLog::SetActiveTarget( oldLog );
1516 if( watcherHasError )
1524 fn.AssignDir( prj_dir );
1525 fn.DontFollowLink();
1539 TO_UTF8( fn.GetFullPath() ) );
1547 TO_UTF8( fn.GetFullPath() ) );
1552 if( m_TreeProject->IsEmpty() )
1556 wxTreeItemIdValue cookie;
1557 wxTreeItemId root_id = m_root;
1559 std::stack < wxTreeItemId > subdirs_id;
1561 wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie );
1562 int total_watch_count = 0;
1568 if( subdirs_id.empty() )
1574 root_id = subdirs_id.top();
1576 kid = m_TreeProject->GetFirstChild( root_id, cookie );
1592 if( wxFileName::IsDirReadable(
path ) )
1597 fn.AssignDir(
path );
1598 m_watcher->Add( fn );
1599 total_watch_count++;
1603 if( itemData->
IsPopulated() && m_TreeProject->GetChildrenCount( kid ) )
1604 subdirs_id.push( kid );
1608 kid = m_TreeProject->GetNextChild( root_id, cookie );
1615#if defined(DEBUG) && 1
1616 wxArrayString paths;
1617 m_watcher->GetWatchedPaths( &paths );
1620 for(
unsigned ii = 0; ii < paths.GetCount(); ii++ )
1639 std::unique_lock<std::mutex> lock(
m_TreeProject->GitCommon()->m_gitActionMutex, std::try_to_lock );
1641 if( !lock.owns_lock() )
1645 wxProgressDialog progress(
_(
"Please wait" ),
_(
"Waiting for Git operations to finish..." ),
1646 100,
this, wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_SMOOTH );
1649 while ( !lock.try_lock() )
1652 std::this_thread::sleep_for( std::chrono::milliseconds(100) );
1678 wxRect rect( wxPoint( 0, 0 ), GetClientSize() );
1679 wxPaintDC dc(
this );
1681 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
1682 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
1684 dc.DrawLine( rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetBottom() );
1685 dc.DrawLine( rect.GetRight(), rect.GetTop(), rect.GetRight(), rect.GetBottom() );
1699 wxString dir = tree_data->
GetDir();
1703 wxLogError(
"Failed to initialize git project: project directory is empty." );
1708 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
1713 _(
"The selected directory is already a Git project." ) );
1728 dlg.SetTitle(
_(
"Set default remote" ) );
1783 handler.
SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>(
this,
_(
"Fetch Remote" ), 1,
1806 handler.
SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>(
this,
_(
"Fetch Remote" ), 1,
1826 wxString branchName;
1835 if( retval == wxID_ADD )
1837 else if( retval != wxID_OK )
1842 std::vector<wxString> branches =
m_TreeProject->GitCommon()->GetBranchNames();
1845 if( branchIndex < 0 ||
static_cast<size_t>( branchIndex ) >= branches.size() )
1848 branchName = branches[branchIndex];
1851 wxLogTrace(
traceGit, wxS(
"onGitSwitchBranch: Switching to branch '%s'" ), branchName );
1864 || !
IsOK( wxGetTopLevelParent(
this ),
1865 _(
"Are you sure you want to remove Git tracking from this project?" ) ) )
1871 wxLogTrace(
traceGit, wxS(
"onGitRemoveVCS: Removing VCS from project" ) );
1883 std::stack<wxTreeItemId> items;
1886 while( !items.empty() )
1888 wxTreeItemId current = items.top();
1892 m_TreeProject->SetItemState( current, wxTREE_ITEMSTATE_NONE );
1894 wxTreeItemIdValue cookie;
1895 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
1897 while( child.IsOk() )
1899 items.push( child );
1908 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Updating git status icons" ) );
1911 if( !lock.owns_lock() )
1913 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Failed to acquire lock for git status icon update" ) );
1920 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git is disabled or tree control is null" ) );
1924 std::stack<wxTreeItemId> items;
1927 while( !items.empty() )
1929 wxTreeItemId current = items.top();
1934 wxTreeItemIdValue cookie;
1935 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
1937 while( child.IsOk() )
1939 items.push( child );
1943 m_TreeProject->SetItemState( child,
static_cast<int>( it->second ) );
1955 wxString filename = wxFileNameFromPath( rootItem->
GetFileName() );
1960 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git status icons updated" ) );
1966 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Updating tree cache" ) );
1970 if( !lock.owns_lock() )
1972 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Failed to acquire lock for tree cache update" ) );
1978 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Tree control is null" ) );
1989 std::stack<wxTreeItemId> items;
1992 while( !items.empty() )
2004 gitAbsPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2008 wxTreeItemIdValue cookie;
2009 wxTreeItemId child =
m_TreeProject->GetFirstChild( kid, cookie );
2011 while( child.IsOk() )
2013 items.push( child );
2022 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updating git status icons" ) );
2023#if defined( _WIN32 )
2046 if( !lock1.owns_lock() || !lock2.owns_lock() )
2048 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Failed to acquire locks for git status icon update" ) );
2054 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: No git repository found" ) );
2061 wxFileName rootFilename(
Prj().GetProjectFullName() );
2064 wxFileName relative = rootFilename;
2065 relative.MakeRelativeTo( repoWorkDir );
2066 wxString pathspecStr = relative.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
2069 pathspecStr.Replace( wxS(
"\\" ), wxS(
"/" ) );
2073 auto fileStatusMap = statusHandler.
GetFileStatus( pathspecStr );
2074 auto [localChanges, remoteChanges] =
m_TreeProject->GitCommon()->GetDifferentFiles();
2077 bool updated =
false;
2080 for(
const auto& [absPath, fileStatus] : fileStatusMap )
2085 wxLogTrace(
traceGit, wxS(
"File '%s' not found in tree cache" ), absPath );
2089 auto [it, inserted] =
m_gitStatusIcons.try_emplace( iter->second, fileStatus.status );
2090 if( inserted || it->second != fileStatus.status )
2092 it->second = fileStatus.status;
2098 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updated git status icons" ) );
2118 if( repo ==
nullptr )
2120 wxMessageBox(
_(
"The selected directory is not a Git project." ) );
2132 std::map<wxString, int> modifiedFiles;
2133 std::set<wxString> selected_files;
2138 selected_files.emplace( item->GetFileName() );
2143 for(
const auto& [absPath, fileStatus] : fileStatusMap )
2153 wxFileName fn( absPath );
2156 wxString relativePath = absPath;
2157 if( relativePath.StartsWith( repoWorkDir ) )
2159 relativePath = relativePath.Mid( repoWorkDir.length() );
2161 relativePath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2167 if( !absPath.StartsWith( projectPath ) )
2182 if( fn.GetPath().Contains(
Prj().GetProjectName() + wxT(
"-backups" ) ) )
2187 modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
2189 else if( selected_files.count( absPath ) )
2191 modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
2200 if( ret != wxID_OK )
2207 wxMessageBox(
_(
"Discarding commit due to empty commit message." ) );
2213 wxMessageBox(
_(
"Discarding commit due to empty file selection." ) );
2223 wxMessageBox( wxString::Format(
_(
"Failed to create commit: %s" ),
2228 wxLogTrace(
traceGit, wxS(
"Created commit" ) );
2248 for(
const auto& [filePath, fileStatus] : fileStatusMap )
2250 if( filePath.EndsWith( aFile ) || filePath == aFile )
2264 wxLogTrace(
traceGit,
"Syncing project" );
2269 wxLogTrace(
traceGit,
"sync: No git repository found" );
2336 wxLogTrace(
traceGit,
"onGitSyncTimer" );
2344 tp.detach_task( [
this]()
2350 wxLogTrace(
traceGit,
"onGitSyncTimer: No git repository found" );
2362 wxLogTrace(
traceGit,
"onGitSyncTimer: Restarting git sync timer" );
2379 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::priority_thread_pool thread_pool
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.