26#include <wx/richmsgdlg.h>
27#include <wx/stdpaths.h>
30#include <wx/textdlg.h>
32#include <wx/wupdlock.h>
34#include <wx/dcclient.h>
35#include <wx/progdlg.h>
36#include <wx/settings.h>
113 wxT(
"^.*\\.kicad_pro$" ),
116 wxT(
"^.*\\.kicad_sch$" ),
117 wxT(
"^[^$].*\\.brd$" ),
118 wxT(
"^[^$].*\\.kicad_pcb$" ),
119 wxT(
"^[^$].*\\.kicad_dru$" ),
120 wxT(
"^[^$].*\\.kicad_wks$" ),
121 wxT(
"^[^$].*\\.kicad_mod$" ),
125 wxT(
"^.*\\.kicad_sym$" ),
130 wxT(
"^.*\\.gbrjob$" ),
131 wxT(
"^.*\\.gb[alops]$" ),
132 wxT(
"^.*\\.gt[alops]$" ),
133 wxT(
"^.*\\.g[0-9]{1,2}$" ),
134 wxT(
"^.*\\.gm[0-9]{1,2}$" ),
138 wxT(
"^.*\\.html$" ),
149 wxT(
"^.*\\.kicad_jobset" ),
236 wxSashLayoutWindow( parent,
ID_LEFT_FRAME, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL )
247 Bind( wxEVT_FSWATCHER,
250 Bind( wxEVT_SYS_COLOUR_CHANGED,
266 m_filters.emplace_back( wxT(
"^no KiCad files found" ) );
274 Unbind( wxEVT_FSWATCHER,
276 Unbind( wxEVT_SYS_COLOUR_CHANGED,
312 if( tree_data.size() != 1 )
315 wxString prj_filename = tree_data[0]->GetFileName();
317 m_Parent->LoadProject( prj_filename );
329 wxString curr_dir = item_data->GetDir();
331 if( curr_dir.IsEmpty() )
334 curr_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
337 if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
340 if( !curr_dir.IsEmpty() )
341 curr_dir += wxFileName::GetPathSeparator();
356 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
359 wxString curr_dir = item_data->GetDir();
361 if( curr_dir.IsEmpty() )
364 wxString new_dir = wxGetTextFromUser(
_(
"Directory name:" ),
_(
"Create New Directory" ) );
366 if( new_dir.IsEmpty() )
369 wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir;
371 if( !wxMkdir( full_dirname ) )
419 return wxEmptyString;
425 std::vector<wxString> projects;
426 wxString dir_filename;
427 bool haveFile = dir.GetFirst( &dir_filename );
431 wxFileName file( dir_filename );
435 projects.push_back( file.GetName() );
437 haveFile = dir.GetNext( &dir_filename );
448 const wxTreeItemId& aParent,
449 std::vector<wxString>* aProjectNames,
453 wxFileName fn( aName );
456 return wxTreeItemId();
458 if( wxDirExists( aName ) )
466 bool addFile =
false;
468 for(
const wxString& m_filter :
m_filters )
470 wxCHECK2_MSG( reg.Compile( m_filter, wxRE_ICASE ),
continue,
471 wxString::Format(
"Regex %s failed to compile.", m_filter ) );
473 if( reg.Matches( aName ) )
481 return wxTreeItemId();
488 if( ext == wxT(
"" ) )
491 if( reg.Compile( wxString::FromAscii(
"^.*\\." ) + ext + wxString::FromAscii(
"$" ), wxRE_ICASE )
492 && reg.Matches( aName ) )
500 wxString file = wxFileNameFromPath( aName );
501 wxFileName currfile( file );
503 bool showAllSchematics =
m_TreeProject->GetGitRepo() !=
nullptr;
507 && ( currfile.GetName().CmpNoCase(
project.GetName() ) == 0 ) )
509 return wxTreeItemId();
518 return wxTreeItemId();
524 if( !parentTreeItem )
525 return wxTreeItemId();
527 wxDir parentDir( parentTreeItem->
GetDir() );
528 std::vector<wxString> projects =
getProjects( parentDir );
531 return wxTreeItemId();
536 wxTreeItemIdValue cookie;
537 wxTreeItemId kid =
m_TreeProject->GetFirstChild( aParent, cookie );
544 return itemData->GetId();
565 if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 )
571 return wxTreeItemId();
577 return wxTreeItemId();
604 wxTreeItemId newItemId =
m_TreeProject->AppendItem( aParent, file );
611 wxString fileName = currfile.GetName().Lower();
612 wxString projName =
project.GetName().Lower();
614 if( fileName == projName || fileName.StartsWith( projName +
"-" ) )
618 bool subdir_populated =
false;
629 std::vector<wxString> projects =
getProjects( dir );
630 wxString dir_filename;
631 bool haveFile = dir.GetFirst( &dir_filename );
636 subdir_populated = aRecurse;
642 wxString
path = aName + wxFileName::GetPathSeparator() + dir_filename;
645 haveFile = dir.GetNext( &dir_filename );
654 if( subdir_populated )
676 wxString pro_dir =
m_Parent->GetProjectFileName();
692 wxFileName fn = pro_dir;
693 bool prjReset =
false;
704 bool prjOpened = fn.FileExists();
707 if(
Pgm().GetCommonSettings()->m_Git.enableGit
708 && !
Prj().GetLocalSettings().m_GitIntegrationDisabled )
718 const char* canonicalWorkDir = git_repository_workdir(
m_TreeProject->GetGitRepo() );
720 if( canonicalWorkDir )
723 fn.GetPath(), wxString::FromUTF8( canonicalWorkDir ) );
727 m_TreeProject->GitCommon()->SetUsername(
Prj().GetLocalSettings().m_GitRepoUsername );
728 m_TreeProject->GitCommon()->SetSSHKey(
Prj().GetLocalSettings().m_GitSSHKey );
735 if( !prjOpened && !prjReset )
738 prjOpened = fn.FileExists();
758 pro_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
759 wxDir dir( pro_dir );
763 std::vector<wxString> projects =
getProjects( dir );
765 bool haveFile = dir.GetFirst( &filename );
769 if( filename != fn.GetFullName() )
771 wxString
name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
778 haveFile = dir.GetNext( &filename );
795 wxLogTrace(
traceGit,
"PROJECT_TREE_PANE::ReCreateTreePrj: starting timers" );
814 wxTreeItemId curr_item = Event.GetItem();
822 bool can_switch_to_project =
true;
823 bool can_create_new_directory =
true;
824 bool can_open_this_directory =
true;
825 bool can_edit =
true;
826 bool can_rename =
true;
827 bool can_delete =
true;
828 bool run_jobs =
false;
832 bool vcs_can_init = !vcs_has_repo;
833 bool vcs_can_set_remote = vcs_has_repo;
834 bool vcs_can_amend = vcs_has_repo && git_repository_head_unborn(
m_TreeProject->GetGitRepo() ) == 0;
838 bool vcs_can_remove = vcs_has_repo || gitIntegrationDisabled;
841 bool vcs_can_pull = vcs_can_fetch;
842 bool vcs_can_switch = vcs_has_repo;
848 vcs_menu &= libgit_init;
850 if( selection.size() == 0 )
854 if( selection.size() != 1 )
856 can_switch_to_project =
false;
857 can_create_new_directory =
false;
866 can_switch_to_project =
false;
872 can_delete = item->CanDelete();
873 can_rename = item->CanRename();
875 switch( item->GetType() )
883 can_switch_to_project =
false;
887 can_create_new_directory =
false;
888 can_open_this_directory =
false;
893 can_switch_to_project =
false;
900 can_switch_to_project =
false;
901 can_create_new_directory =
false;
902 can_open_this_directory =
false;
915 can_switch_to_project =
false;
916 can_create_new_directory =
false;
917 can_open_this_directory =
false;
927 if( can_switch_to_project )
930 _(
"Close all editors, and switch to the selected project" ),
932 popup_menu.AppendSeparator();
935 if( can_create_new_directory )
941 if( can_open_this_directory )
943 if( selection.size() == 1 )
946 text =
_(
"Reveal in Finder" );
947 help_text =
_(
"Reveals the directory in a Finder window" );
949 text =
_(
"Open Directory in File Explorer" );
950 help_text =
_(
"Opens the directory in the default system file manager" );
956 text =
_(
"Reveal in Finder" );
957 help_text =
_(
"Reveals the directories in a Finder window" );
959 text =
_(
"Open Directories in File Explorer" );
960 help_text =
_(
"Opens the directories in the default system file manager" );
970 if( selection.size() == 1 )
971 help_text =
_(
"Open the file in a Text Editor" );
973 help_text =
_(
"Open files in a Text Editor" );
979 if( run_jobs && selection.size() == 1 )
987 if( selection.size() == 1 )
989 text =
_(
"Rename File..." );
990 help_text =
_(
"Rename file" );
994 text =
_(
"Rename Files..." );
995 help_text =
_(
"Rename files" );
1004 if( selection.size() == 1 )
1005 help_text =
_(
"Delete the file and its content" );
1007 help_text =
_(
"Delete the files and their contents" );
1009 if( can_switch_to_project
1010 || can_create_new_directory
1011 || can_open_this_directory
1015 popup_menu.AppendSeparator();
1029 wxMenu* vcs_submenu =
new wxMenu();
1030 wxMenu* branch_submenu =
new wxMenu();
1031 wxMenuItem* vcs_menuitem =
nullptr;
1034 _(
"Add Project to Version Control..." ),
1035 _(
"Initialize a new repository" ) );
1036 vcs_menuitem->Enable( vcs_can_init );
1039 _(
"Set or change the default remote URL and credentials" ) );
1040 vcs_menuitem->Enable( vcs_can_set_remote );
1043 _(
"Commit changes to the local repository" ) );
1044 vcs_menuitem->Enable( vcs_can_commit );
1047 _(
"Rewrite the most recent commit on the current branch" ) );
1048 vcs_menuitem->Enable( vcs_can_amend );
1050 wxString pushLabel =
_(
"Push" );
1051 wxString pullLabel =
_(
"Pull" );
1060 vcs_submenu->Append(
ID_GIT_PUSH, pushLabel,
_(
"Push committed local changes to remote repository" ) );
1061 vcs_menuitem->Enable( vcs_can_push );
1064 vcs_submenu->Append(
ID_GIT_PULL, pullLabel,
_(
"Pull changes from remote repository into local" ) );
1065 vcs_menuitem->Enable( vcs_can_pull );
1067 vcs_submenu->AppendSeparator();
1070 _(
"Commit changes to the local repository" ) );
1071 vcs_menuitem->Enable( vcs_can_commit );
1073 vcs_submenu->AppendSeparator();
1079 std::vector<wxString> branchNames =
m_TreeProject->GitCommon()->GetBranchNames();
1082 for(
size_t ii = 1; ii < branchNames.size() && ii < 6; ++ii )
1084 wxString msg =
_(
"Switch to branch " ) + branchNames[ii];
1086 vcs_menuitem->Enable( vcs_can_switch );
1090 _(
"Switch to a different branch" ) );
1091 vcs_menuitem->Enable( vcs_can_switch );
1095 vcs_submenu->AppendSeparator();
1097 if( gitIntegrationDisabled )
1099 vcs_menuitem = vcs_submenu->Append(
ID_GIT_REMOVE_VCS,
_(
"Enable Git Integration" ),
1100 _(
"Re-enable Git integration for this project" ) );
1104 vcs_menuitem = vcs_submenu->Append(
ID_GIT_REMOVE_VCS,
_(
"Disable Git Integration" ),
1105 _(
"Disable Git integration for this project" ) );
1108 vcs_menuitem->Enable( vcs_can_remove );
1110 popup_menu.AppendSeparator();
1111 popup_menu.AppendSubMenu( vcs_submenu,
_(
"Version Control" ) );
1114 if( popup_menu.GetMenuItemCount() > 0 )
1115 PopupMenu( &popup_menu );
1123 if( editorname.IsEmpty() )
1125 wxMessageBox(
_(
"No text editor selected in KiCad. Please choose one." ) );
1133 wxString fullFileName = item_data->GetFileName();
1135 if( !fullFileName.IsEmpty() )
1137 ExecuteFile( editorname, fullFileName.wc_str(),
nullptr,
false );
1148 item_data->Delete();
1158 if( tree_data.size() != 1 )
1162 wxString msg = wxString::Format(
_(
"Change filename: '%s'" ),
1163 tree_data[0]->GetFileName() );
1164 wxTextEntryDialog dlg( wxGetTopLevelParent(
this ), msg,
_(
"Change filename" ), buffer );
1166 if( dlg.ShowModal() != wxID_OK )
1169 buffer = dlg.GetValue();
1170 buffer.Trim(
true );
1171 buffer.Trim(
false );
1173 if( buffer.IsEmpty() )
1176 tree_data[0]->Rename( buffer,
true );
1185 if( tree_data.size() != 1 )
1208 std::vector<wxTreeItemId> validItemIds;
1211 for( wxTreeItemId
id : validItemIds )
1230 wxTreeItemId itemId = Event.GetItem();
1240 wxTreeItemIdValue cookie;
1241 wxTreeItemId kid =
m_TreeProject->GetFirstChild( itemId, cookie );
1244 bool subdir_populated =
false;
1247 for( ; kid.IsOk(); kid =
m_TreeProject->GetNextChild( itemId, cookie ) )
1258 wxDir dir( fileName );
1260 if( dir.IsOpened() )
1262 std::vector<wxString> projects =
getProjects( dir );
1263 wxString dir_filename;
1264 bool haveFile = dir.GetFirst( &dir_filename );
1269 wxString
name = fileName + wxFileName::GetPathSeparator() + dir_filename;
1272 haveFile = dir.GetNext( &dir_filename );
1278 subdir_populated =
true;
1287 if( subdir_populated )
1295 wxArrayTreeItemIds selection;
1296 std::vector<PROJECT_TREE_ITEM*> data;
1300 for(
const wxTreeItemId itemId : selection )
1306 wxLogTrace(
traceGit, wxS(
"Null tree item returned for selection, dynamic_cast failed?" ) );
1310 data.push_back( item );
1325 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
1329 if( prj_dir == aSubDir )
1333 wxTreeItemIdValue cookie;
1334 wxTreeItemId root_id =
m_root;
1335 std::stack<wxTreeItemId> subdirs_id;
1337 wxTreeItemId child =
m_TreeProject->GetFirstChild( root_id, cookie );
1341 if( ! child.IsOk() )
1343 if( subdirs_id.empty() )
1350 root_id = subdirs_id.top();
1371 subdirs_id.push( child );
1389 if( !( event.GetChangeType() & ( wxFSW_EVENT_CREATE |
1390 wxFSW_EVENT_DELETE |
1391 wxFSW_EVENT_RENAME |
1392 wxFSW_EVENT_MODIFY ) ) )
1397 const wxFileName& pathModified =
event.GetPath();
1400 if( pathModified.GetFullPath().Contains( wxS(
".history" ) ) )
1403 wxString subdir = pathModified.GetPath();
1404 wxString fn = pathModified.GetFullPath();
1407 if( pathModified.GetFullName().IsEmpty() )
1409 subdir = subdir.BeforeLast(
'/' );
1410 fn = fn.BeforeLast(
'/' );
1415 if( !root_id.IsOk() )
1418 CallAfter( [
this] ()
1420 wxLogTrace(
traceGit, wxS(
"File system event detected, updating tree cache" ) );
1424 wxTreeItemIdValue cookie;
1425 wxTreeItemId kid =
m_TreeProject->GetFirstChild( root_id, cookie );
1427 switch( event.GetChangeType() )
1429 case wxFSW_EVENT_CREATE:
1444 case wxFSW_EVENT_DELETE:
1458 case wxFSW_EVENT_RENAME :
1460 const wxFileName& newpath =
event.GetNewPath();
1461 wxString newdir = newpath.GetPath();
1462 wxString newfn = newpath.GetFullPath();
1486 if( rootData && newpath.Exists() && ( newfn != rootData->
GetFileName() ) )
1492 if( newitem.IsOk() )
1513 wxString prj_dir = wxPathOnly(
m_Parent->GetProjectFileName() );
1515#if defined( _WIN32 )
1522 m_Parent->m_FileWatcherInfo =
_(
"Network path: not monitoring folder changes" );
1528 m_Parent->m_FileWatcherInfo =
_(
"Local path: monitoring folder changes" );
1546 class WatcherLogHandler :
public wxLog
1549 explicit WatcherLogHandler(
bool* err ) :
1557 void DoLogTextAtLevel( wxLogLevel level,
const wxString&
text )
override
1559 if( m_err && ( level == wxLOG_Error || level == wxLOG_FatalError ) )
1567 bool watcherHasError =
false;
1568 WatcherLogHandler tmpLog( &watcherHasError );
1577 if( watcherHasError )
1585 fn.AssignDir( prj_dir );
1586 fn.DontFollowLink();
1600 TO_UTF8( fn.GetFullPath() ) );
1608 TO_UTF8( fn.GetFullPath() ) );
1613 if( m_TreeProject->IsEmpty() )
1617 wxTreeItemIdValue cookie;
1618 wxTreeItemId root_id = m_root;
1620 std::stack < wxTreeItemId > subdirs_id;
1622 wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie );
1623 int total_watch_count = 0;
1629 if( subdirs_id.empty() )
1635 root_id = subdirs_id.top();
1637 kid = m_TreeProject->GetFirstChild( root_id, cookie );
1652 if(
path.Contains( wxS(
".history" ) ) )
1654 kid = m_TreeProject->GetNextChild( root_id, cookie );
1660 if( wxFileName::IsDirReadable(
path ) )
1665 fn.AssignDir(
path );
1666 m_watcher->Add( fn );
1667 total_watch_count++;
1671 if( itemData->
IsPopulated() && m_TreeProject->GetChildrenCount( kid ) )
1672 subdirs_id.push( kid );
1676 kid = m_TreeProject->GetNextChild( root_id, cookie );
1683#if defined(DEBUG) && 1
1684 wxArrayString paths;
1685 m_watcher->GetWatchedPaths( &paths );
1688 for(
unsigned ii = 0; ii < paths.GetCount(); ii++ )
1706 std::unique_lock<std::mutex> lock( common->
m_gitActionMutex, std::try_to_lock );
1708 constexpr auto kGraceMs = std::chrono::seconds( 2 );
1709 auto graceEnd = std::chrono::steady_clock::now() + kGraceMs;
1711 while( !lock.owns_lock() && std::chrono::steady_clock::now() < graceEnd )
1713 if( lock.try_lock() )
1715 std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) );
1718 constexpr auto kCheckInterval = std::chrono::seconds( 30 );
1719 bool userAbandoned =
false;
1721 while( !lock.owns_lock() && !userAbandoned )
1723 auto intervalEnd = std::chrono::steady_clock::now() + kCheckInterval;
1726 wxProgressDialog progress(
_(
"Please wait" ),
1727 _(
"Closing project..." ),
1729 wxPD_APP_MODAL | wxPD_SMOOTH );
1731 while( !lock.try_lock()
1732 && std::chrono::steady_clock::now() < intervalEnd )
1735 std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
1740 if( lock.owns_lock() )
1743 wxMessageDialog ask(
this,
1744 _(
"A Git operation is still running.\n"
1745 "Keep waiting, or abandon?" ),
1746 _(
"Git Operation Delayed" ),
1747 wxYES_NO | wxICON_QUESTION );
1748 ask.SetYesNoLabels(
_(
"Keep Waiting" ),
_(
"Abandon" ) );
1750 if( ask.ShowModal() == wxID_NO )
1751 userAbandoned =
true;
1757 std::shared_ptr<KIGIT_COMMON> oldCommon =
m_TreeProject->TakeGitCommon();
1767 wxString projectDir = oldCommon ? oldCommon->GetProjectDir() : wxString();
1769 auto cleanup = [orphan, old = std::move( oldCommon )]()
mutable
1771 std::lock_guard<std::mutex> g( old->m_gitActionMutex );
1772 git_repository_free( orphan );
1779 std::string label =
"abandon close " + projectDir.ToStdString();
1814 std::unique_lock<std::mutex> gitLock( common->
m_gitActionMutex, std::try_to_lock );
1816 if( gitLock.owns_lock() )
1819 git_repository_free( repo );
1827 std::shared_ptr<KIGIT_COMMON> oldCommon =
m_TreeProject->TakeGitCommon();
1830 wxString projectDir = oldCommon ? oldCommon->GetProjectDir() : wxString();
1832 auto cleanup = [repo, old = std::move( oldCommon )]()
mutable
1834 std::lock_guard<std::mutex> g( old->m_gitActionMutex );
1835 git_repository_free( repo );
1842 std::string label =
"release repo " + projectDir.ToStdString();
1867 wxRect rect( wxPoint( 0, 0 ), GetClientSize() );
1868 wxPaintDC dc(
this );
1870 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
1871 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
1873 dc.DrawLine( rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetBottom() );
1874 dc.DrawLine( rect.GetRight(), rect.GetTop(), rect.GetRight(), rect.GetBottom() );
1917 wxString dir = tree_data->
GetDir();
1921 wxLogError(
"Failed to initialize git project: project directory is empty." );
1926 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
1931 _(
"The selected directory is already a Git project." ) );
1947 const char* canonicalWorkDir = git_repository_workdir( initHandler.
GetRepo() );
1949 if( canonicalWorkDir )
1952 dir, wxString::FromUTF8( canonicalWorkDir ) );
1953 m_TreeProject->GitCommon()->SetProjectDir( symlinkWorkDir );
1957 dlg.SetTitle(
_(
"Set default remote" ) );
1988 std::make_unique<WX_PROGRESS_REPORTER>(
this,
_(
"Fetch Remote" ), 1,
PR_NO_ABORT ) );
2015 git_repository* repo = common ? common->
GetRepo() :
nullptr;
2020 wxString existingURL;
2021 git_remote* remote =
nullptr;
2023 if( git_remote_lookup( &remote, repo,
"origin" ) == GIT_OK )
2027 if(
const char* url = git_remote_url( remote ) )
2028 existingURL = wxString::FromUTF8( url );
2031 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
2033 dlg.SetTitle(
_(
"Configure Default Remote" ) );
2090 std::make_unique<WX_PROGRESS_REPORTER>(
this,
_(
"Fetch Remote" ), 1,
PR_NO_ABORT ) );
2099 switch( pullResult )
2103 : wxString::Format(
_(
"Already up to date with %s." ), upstream ) );
2108 upstream.empty() || branch.empty()
2109 ?
_(
"Pulled changes (fast-forward)." )
2110 : wxString::Format(
_(
"Pulled %s into %s (fast-forward)." ), upstream, branch ) );
2115 ?
_(
"Pulled changes." )
2116 : wxString::Format(
_(
"Pulled %s into %s." ), upstream, branch ) );
2125 wxRichMessageDialog dlg( wxGetTopLevelParent(
this ),
2126 _(
"Your local changes and the remote changes conflict, so the pull was "
2127 "cancelled and nothing was changed.\n\n"
2128 "You can discard your local commits and use the remote version, or "
2129 "rebase your commits on top of the remote." ),
2130 _(
"Pull Conflict" ),
2131 wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING | wxCENTER );
2133 dlg.SetYesNoCancelLabels(
_(
"&Use Remote (discard my changes)" ),
_(
"&Rebase" ),
_(
"Cancel" ) );
2135 int choice = dlg.ShowModal();
2137 if( choice == wxID_YES )
2144 else if( choice == wxID_NO )
2189 std::make_unique<WX_PROGRESS_REPORTER>(
this,
_(
"Fetch Remote" ), 1,
PR_NO_ABORT ) );
2199 ?
_(
"Pushed to remote." )
2200 : wxString::Format(
_(
"Pushed %s to %s." ), branch, upstream ) );
2211 wxRichMessageDialog dlg(
2212 wxGetTopLevelParent(
this ),
2213 wxString::Format(
_(
"Push rejected: your local branch and %s have diverged.\n\n"
2214 "This usually happens after amending or rewriting a commit "
2215 "that was already pushed. Force push to overwrite the remote?\n\n"
2216 "Anyone who already pulled the previous version will need to "
2217 "reset their copy." ),
2218 upstream.empty() ? wxString(
"the remote" ) : upstream ),
2219 _(
"Force Push?" ), wxYES_NO | wxNO_DEFAULT | wxICON_WARNING | wxCENTER );
2221 dlg.SetYesNoLabels(
_(
"&Force Push" ),
_(
"Cancel" ) );
2223 if( dlg.ShowModal() == wxID_YES )
2245 wxString branchName;
2254 if( retval == wxID_ADD )
2256 else if( retval != wxID_OK )
2261 std::vector<wxString> branches =
m_TreeProject->GitCommon()->GetBranchNames();
2264 if( branchIndex < 0 ||
static_cast<size_t>( branchIndex ) >= branches.size() )
2267 branchName = branches[branchIndex];
2270 wxLogTrace(
traceGit, wxS(
"onGitSwitchBranch: Switching to branch '%s'" ), branchName );
2289 wxLogTrace(
traceGit, wxS(
"onGitRemoveVCS: Git integration %s" ),
2299 std::stack<wxTreeItemId> items;
2302 while( !items.empty() )
2304 wxTreeItemId current = items.top();
2307 m_TreeProject->SetItemState( current, wxTREE_ITEMSTATE_NONE );
2309 wxTreeItemIdValue cookie;
2310 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
2312 while( child.IsOk() )
2314 items.push( child );
2322 wxFileName fn(
Prj().GetProjectPath() );
2329 const char* canonicalWorkDir = git_repository_workdir(
m_TreeProject->GetGitRepo() );
2331 if( canonicalWorkDir )
2334 fn.GetPath(), wxString::FromUTF8( canonicalWorkDir ) );
2335 m_TreeProject->GitCommon()->SetProjectDir( symlinkWorkDir );
2350 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Updating git status icons" ) );
2353 if( !lock.owns_lock() )
2355 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Failed to acquire lock for git status icon update" ) );
2362 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git is disabled or tree control is null" ) );
2366 std::stack<wxTreeItemId> items;
2369 while( !items.empty() )
2371 wxTreeItemId current = items.top();
2374 if( current.IsOk() &&
m_TreeProject->ItemHasChildren( current ) )
2376 wxTreeItemIdValue cookie;
2377 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
2379 while( child.IsOk() )
2381 items.push( child );
2384 m_TreeProject->SetItemState( child,
static_cast<int>( it->second ) );
2398 wxString filename = wxFileNameFromPath( rootItem->
GetFileName() );
2404 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git status icons updated" ) );
2410 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Updating tree cache" ) );
2414 if( !lock.owns_lock() )
2416 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Failed to acquire lock for tree cache update" ) );
2422 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Tree control is null" ) );
2433 std::stack<wxTreeItemId> items;
2436 while( !items.empty() )
2448 gitAbsPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2452 wxTreeItemIdValue cookie;
2453 wxTreeItemId child =
m_TreeProject->GetFirstChild( kid, cookie );
2455 while( child.IsOk() )
2457 items.push( child );
2466 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updating git status icons" ) );
2467#if defined( _WIN32 )
2490 if( !lock1.owns_lock() || !lock2.owns_lock() )
2492 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Failed to acquire locks for git status icon update" ) );
2500 std::shared_ptr<KIGIT_COMMON> gitCommon =
m_TreeProject->GitCommonPtr();
2502 if( !gitCommon || !gitCommon->GetRepo() )
2504 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: No git repository found" ) );
2510 std::unique_lock<std::mutex> gitLock( gitCommon->m_gitActionMutex, std::try_to_lock );
2512 if( !gitLock.owns_lock() )
2514 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Failed to acquire git action mutex" ) );
2519 if( gitCommon->IsCancelled() )
2521 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Cancelled" ) );
2528 wxFileName rootFilename(
Prj().GetProjectFullName() );
2531 wxFileName relative = rootFilename;
2532 relative.MakeRelativeTo( repoWorkDir );
2533 wxString pathspecStr = relative.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
2536 pathspecStr.Replace( wxS(
"\\" ), wxS(
"/" ) );
2540 auto fileStatusMap = statusHandler.
GetFileStatus( pathspecStr );
2541 auto [localChanges, remoteChanges] = gitCommon->GetDifferentFiles();
2544 bool updated =
false;
2547 for(
const auto& [absPath, fileStatus] : fileStatusMap )
2552 wxLogTrace(
traceGit, wxS(
"File '%s' not found in tree cache" ), absPath );
2556 auto [it, inserted] =
m_gitStatusIcons.try_emplace( iter->second, fileStatus.status );
2557 if( inserted || it->second != fileStatus.status )
2559 it->second = fileStatus.status;
2571 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updated git status icons" ) );
2591 if( repo ==
nullptr )
2593 wxMessageBox(
_(
"The selected directory is not a Git project." ) );
2607 const DirtyEditor candidates[] = {
2612 std::vector<const DirtyEditor*> dirty;
2614 for(
const DirtyEditor& d : candidates )
2619 dirty.push_back( &d );
2622 if( !dirty.empty() )
2626 for(
const DirtyEditor* d : dirty )
2627 listed += wxString::Format( wxS(
"\n • %s" ), d->label );
2629 wxRichMessageDialog dlg( wxGetTopLevelParent(
this ),
2630 wxString::Format(
_(
"The following editors have unsaved changes:%s\n\n"
2631 "Save them before committing?" ),
2633 _(
"Unsaved Changes" ),
2634 wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
2636 dlg.SetYesNoCancelLabels(
_(
"&Save and Commit" ),
_(
"Commit &Anyway" ),
_(
"Cancel" ) );
2638 int answer = dlg.ShowModal();
2640 if( answer == wxID_CANCEL )
2643 if( answer == wxID_YES )
2645 for(
const DirtyEditor* d : dirty )
2647 std::string payload;
2648 m_Parent->Kiway().ExpressMail( d->frameType, d->saveMail, payload );
2650 if( payload !=
"success" )
2653 wxString::Format(
_(
"Could not save %s." ), d->label ) );
2660 m_Parent->GetSettingsManager()->SaveProject();
2669 std::map<wxString, FileStatus> fileStatusMap = statusHandler.
GetFileStatus();
2671 std::map<wxString, int> modifiedFiles;
2672 std::set<wxString> selected_files;
2679 wxString itemPath = item->GetFileName();
2681 itemPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2683 selected_files.emplace( itemPath );
2690 projectPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2693 for(
const auto& [absPath, fileStatus] : fileStatusMap )
2703 wxFileName fn( absPath );
2706 wxString relativePath = absPath;
2708 if( relativePath.StartsWith( repoWorkDir ) )
2710 relativePath = relativePath.Mid( repoWorkDir.length() );
2712 relativePath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2732 if( fn.GetPath().Contains(
Prj().GetProjectName() + wxT(
"-backups" ) ) )
2736 if( fn.IsDir() && fn.GetDirs().Last().StartsWith( wxS(
".history" ) ) )
2751 modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
2753 else if( selected_files.count( absPath ) )
2755 modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
2764 if( ret != wxID_OK )
2771 wxMessageBox(
_(
"Discarding commit due to empty commit message." ) );
2777 wxMessageBox(
_(
"Discarding commit due to empty file selection." ) );
2787 wxMessageBox( wxString::Format(
_(
"Failed to create commit: %s" ), commitHandler.
GetErrorString() ) );
2791 wxLogTrace(
traceGit, wxS(
"Created commit" ) );
2800 if( repo ==
nullptr )
2802 wxMessageBox(
_(
"The selected directory is not a Git project." ) );
2812 std::unique_lock<std::mutex> gitLock(
m_TreeProject->GitCommon()->m_gitActionMutex, std::try_to_lock );
2814 if( gitLock.owns_lock() )
2817 git_repository_free( repo );
2822 git_repository_free( fresh );
2826 if( git_repository_head_unborn( repo ) != 0 )
2828 DisplayErrorMessage( wxGetTopLevelParent(
this ),
_(
"Cannot amend: the branch has no commits yet." ) );
2834 git_reference* headRef =
nullptr;
2836 if( git_repository_head( &headRef, repo ) != GIT_OK )
2840 git_commit* headCommit =
nullptr;
2842 if( git_reference_peel( (git_object**) &headCommit, headRef, GIT_OBJECT_COMMIT ) != GIT_OK )
2846 wxString headMessage = wxString::FromUTF8( git_commit_message( headCommit ) );
2847 const git_oid* headOid = git_commit_id( headCommit );
2851 bool headIsPublished =
false;
2852 git_reference* upstreamRef =
nullptr;
2854 if( git_branch_upstream( &upstreamRef, headRef ) == GIT_OK )
2857 git_oid upstreamOid;
2859 if( git_reference_name_to_id( &upstreamOid, repo, git_reference_name( upstreamRef ) ) == GIT_OK )
2861 headIsPublished = git_oid_equal( headOid, &upstreamOid )
2862 || git_graph_descendant_of( repo, &upstreamOid, headOid ) == 1;
2866 if( headIsPublished )
2868 wxString upstreamName =
m_TreeProject->GitCommon()->GetUpstreamShorthand();
2870 wxRichMessageDialog dlg( wxGetTopLevelParent(
this ),
2871 wxString::Format(
_(
"The last commit has already been pushed to %s.\n\n"
2872 "Amending rewrites public history. Anyone who pulled "
2873 "this commit will need to reset their copy." ),
2875 _(
"Amend Published Commit?" ), wxYES_NO | wxNO_DEFAULT | wxICON_WARNING | wxCENTER );
2877 dlg.SetYesNoLabels(
_(
"Amend &Anyway" ),
_(
"Cancel" ) );
2879 if( dlg.ShowModal() != wxID_YES )
2893 const DirtyEditor candidates[] = {
2898 std::vector<const DirtyEditor*> dirty;
2900 for(
const DirtyEditor& d : candidates )
2905 dirty.push_back( &d );
2908 if( !dirty.empty() )
2912 for(
const DirtyEditor* d : dirty )
2913 listed += wxString::Format( wxS(
"\n • %s" ), d->label );
2915 wxRichMessageDialog dlg( wxGetTopLevelParent(
this ),
2916 wxString::Format(
_(
"The following editors have unsaved changes:%s\n\n"
2917 "Save them before amending?" ),
2919 _(
"Unsaved Changes" ),
2920 wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
2922 dlg.SetYesNoCancelLabels(
_(
"&Save and Amend" ),
_(
"Amend &Anyway" ),
_(
"Cancel" ) );
2924 int answer = dlg.ShowModal();
2926 if( answer == wxID_CANCEL )
2929 if( answer == wxID_YES )
2931 for(
const DirtyEditor* d : dirty )
2933 std::string payload;
2934 m_Parent->Kiway().ExpressMail( d->frameType, d->saveMail, payload );
2936 if( payload !=
"success" )
2939 wxString::Format(
_(
"Could not save %s." ), d->label ) );
2946 m_Parent->GetSettingsManager()->SaveProject();
2954 std::map<wxString, FileStatus> fileStatusMap = statusHandler.
GetFileStatus();
2959 projectPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2962 std::map<wxString, int> modifiedFiles;
2964 for(
const auto& [absPath, fileStatus] : fileStatusMap )
2973 wxFileName fn( absPath );
2974 wxString relativePath = absPath;
2976 if( relativePath.StartsWith( repoWorkDir ) )
2978 relativePath = relativePath.Mid( repoWorkDir.length() );
2980 relativePath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2993 if( fn.GetPath().Contains(
Prj().GetProjectName() + wxT(
"-backups" ) ) )
2996 modifiedFiles.emplace( relativePath, fileStatus.gitStatus );
2999 if( git_reference* headRefForDiff =
nullptr; git_repository_head( &headRefForDiff, repo ) == GIT_OK )
3002 git_commit* lastCommit =
nullptr;
3004 if( git_reference_peel( (git_object**) &lastCommit, headRefForDiff, GIT_OBJECT_COMMIT ) == GIT_OK )
3007 git_commit* parentCommit =
nullptr;
3008 git_tree* parentTree =
nullptr;
3009 git_tree* lastTree =
nullptr;
3011 if( git_commit_parentcount( lastCommit ) > 0
3012 && git_commit_parent( &parentCommit, lastCommit, 0 ) == GIT_OK )
3014 git_commit_tree( &parentTree, parentCommit );
3020 if( git_commit_tree( &lastTree, lastCommit ) == GIT_OK )
3023 git_diff* diff =
nullptr;
3025 if( git_diff_tree_to_tree( &diff, repo, parentTree, lastTree,
nullptr ) == GIT_OK )
3030 [&modifiedFiles, &repoWorkDir, &projectPath](
const git_diff_delta& aDelta )
3032 const char*
path = aDelta.new_file.path ? aDelta.new_file.path
3033 : aDelta.old_file.path;
3040 wxString absPath = repoWorkDir + wxString::FromUTF8(
path );
3045 int flag = GIT_STATUS_INDEX_MODIFIED;
3047 if( aDelta.status == GIT_DELTA_ADDED )
3048 flag = GIT_STATUS_INDEX_NEW;
3049 else if( aDelta.status == GIT_DELTA_DELETED )
3050 flag = GIT_STATUS_INDEX_DELETED;
3052 modifiedFiles[wxString::FromUTF8(
path )] |=
flag;
3061 dlg.SetTitle(
_(
"Amend Last Commit" ) );
3070 wxMessageBox(
_(
"Discarding amend due to empty commit message." ) );
3080 wxMessageBox( wxString::Format(
_(
"Failed to amend commit: %s" ), commitHandler.
GetErrorString() ) );
3084 wxLogTrace(
traceGit, wxS(
"Amended commit" ) );
3101 std::map<wxString, FileStatus> fileStatusMap = statusHandler.
GetFileStatus();
3104 for(
const auto& [filePath, fileStatus] : fileStatusMap )
3106 if( filePath.EndsWith( aFile ) || filePath == aFile )
3120 wxLogTrace(
traceGit,
"Syncing project" );
3125 wxLogTrace(
traceGit,
"sync: No git repository found" );
3152 : wxString::Format(
_(
"Fetched from %s." ), remoteName ) );
3211 wxLogTrace(
traceGit,
"onGitSyncTimer" );
3220 &&
m_gitSyncTask.wait_for( std::chrono::seconds( 0 ) ) != std::future_status::ready )
3222 wxLogTrace(
traceGit,
"onGitSyncTimer: previous fetch still running, skipping" );
3227 if( std::shared_ptr<KIGIT_COMMON> gitCommon =
m_TreeProject->GitCommonPtr() )
3228 gitCommon->SetCancelled(
false );
3236 std::shared_ptr<KIGIT_COMMON> gitCommon =
m_TreeProject->GitCommonPtr();
3238 if( !gitCommon || !gitCommon->GetRepo() )
3240 wxLogTrace(
traceGit,
"onGitSyncTimer: No git repository found" );
3245 if( gitCommon->IsCancelled() )
3247 wxLogTrace(
traceGit,
"onGitSyncTimer: Cancelled" );
3255 if( !gitCommon->IsCancelled() )
3259 wxLogTrace(
traceGit,
"onGitSyncTimer: Restarting git sync timer" );
3281 wxLogTrace(
traceGit,
"onGitStatusTimer" );
3294 m_Parent->SetStatusText( aText, 0 );
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.
void SetFileSelectionRequired(bool aRequired)
When false, OK is allowed with no files selected (e.g. amending only the message).
wxString GetCommitMessage() const
void SetCommitMessage(const wxString &aMessage)
Pre-fill the commit message.
wxString GetAuthorEmail() const
std::vector< wxString > GetSelectedFiles() const
wxString GetAuthorName() const
KIGIT_COMMON::GIT_CONN_TYPE GetConnType() const
wxString GetPassword() const
wxString GetUsername() const
wxString GetSSHKey() const
bool SaveCredentials() 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 IsContentModified() const
Get if the contents of the frame have been modified since the last save.
virtual bool IsLibraryAvailable()=0
KIGIT_ORPHAN_REGISTRY & OrphanRegistry()
Return the process-wide orphan thread registry owned by this backend.
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
CommitResult PerformAmend(const std::vector< wxString > &aFiles, const wxString &aMessage, const wxString &aAuthorName, const wxString &aAuthorEmail)
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)
PullResult RebaseOntoUpstream()
PushResult PerformPush(bool aForce=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.
void OnChangeWatchedPaths(wxCommandEvent &aEvent)
Called by sending a event with id = ID_INIT_WATCHED_PATHS rebuild the list of watched paths.
PROJECT_TREE_PANE * m_projectTreePane
static git_repository * GetRepositoryForFile(const char *aFilename)
Discover and open the repository that contains the given file.
static wxString ComputeSymlinkPreservingWorkDir(const wxString &aUserProjectPath, const wxString &aCanonicalWorkDir)
Compute a working directory path that preserves symlinks from the user's project path.
static bool IsWithinProjectPath(const wxString &aAbsPath, const wxString &aProjectPath)
Test whether an absolute file path lives inside the current project directory.
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.
std::mutex m_gitActionMutex
const wxString & GetRemote() const
GIT_CONN_TYPE GetConnType() const
bool WasAuthFailure() const
wxString GetCurrentBranchName() const
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
wxString GetRemoteNameOrDefault() const
Returns GetRemotename() when non-empty, otherwise "origin".
git_repository * GetRepo() const
bool HasPushAndPullRemote() const
wxString GetUsername() const
void UpdateCurrentBranchInfo()
bool HasLocalCommits() const
wxString GetUpstreamShorthand() const
Returns the upstream shorthand for the current branch (e.g.
void SetCancelled(bool aCancel)
void SetPassword(const wxString &aPassword)
wxString GetErrorString()
bool Register(const std::string &aLabel, F &&aWork)
Spawn a tracked orphan thread running aWork.
git_repository * GetRepo() const
Get a pointer to the git repository.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
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.
The project local settings are things that are attached to a particular project, but also might be pa...
bool m_GitIntegrationDisabled
If true, KiCad will not use Git integration for this project even if a .git directory exists.
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then writes the contents of the JSON document to a file.
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 showGitFeedback(const wxString &aText)
Show a short message in the project status bar after a git operation.
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
std::future< void > m_gitSyncTask
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.
void onGitAmendCommit(wxCommandEvent &event)
Amend (rewrite) the last commit on the current branch.
void onGitFeedbackTimer(wxTimerEvent &event)
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...
wxTimer m_gitFeedbackTimer
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 onGitRemoteSettings(wxCommandEvent &event)
Configure (or change) the default remote on an already-initialized repository.
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
std::future< void > m_gitStatusIconTask
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.
wxString m_gitCurrentUpstream
void releaseGitRepo()
Releases the git repository handle, deferring the free to the orphan registry while a background git ...
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
A scoped application of a wxLog target.
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.
wxDECLARE_EVENT(wxEVT_REFRESH_CUSTOM_COMMAND, wxCommandEvent)
EVT_MENU_RANGE(ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILEMAX, GERBVIEW_FRAME::OnDrlFileHistory) EVT_MENU_RANGE(ID_GERBVIEW_ZIP_FILE1
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
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 ProjectLocalSettingsFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string LockFilePrefix
static const std::string CsvFileExtension
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.
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
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 ...
MAIL_T
The set of mail types sendable via KIWAY::ExpressMail() and supplied as the aCommand parameter to tha...
std::unique_ptr< git_tree, decltype([](git_tree *aTree) { git_tree_free(aTree); })> GitTreePtr
A unique pointer for git_tree objects with automatic cleanup.
std::unique_ptr< git_commit, decltype([](git_commit *aCommit) { git_commit_free(aCommit); })> GitCommitPtr
A unique pointer for git_commit objects with automatic cleanup.
void CollectDiffDeltas(git_diff *aDiff, const std::function< void(const git_diff_delta &)> &aCallback)
Walk every delta in a computed diff, invoking aCallback once per delta.
std::unique_ptr< git_reference, decltype([](git_reference *aRef) { git_reference_free(aRef); })> GitReferencePtr
A unique pointer for git_reference objects with automatic cleanup.
std::unique_ptr< git_diff, decltype([](git_diff *aDiff) { git_diff_free(aDiff); })> GitDiffPtr
A unique pointer for git_diff objects with automatic cleanup.
std::unique_ptr< git_remote, decltype([](git_remote *aRemote) { git_remote_free(aRemote); })> GitRemotePtr
A unique pointer for git_remote objects with automatic cleanup.
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.
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[]
static bool promptForGitCredentials(wxWindow *aParent, KIGIT_COMMON *aCommon)
#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.