24#include <wx/textdlg.h>
43static bool findStashByIdUnlocked(
KIGIT_COMMON& aCommon,
const wxString& aId,
size_t& aIndexOut )
68 m_stashesList->AppendColumn(
_(
"Description" ), wxLIST_FORMAT_LEFT, FromDIP( 360 ) );
69 m_stashesList->AppendColumn(
_(
"Date" ), wxLIST_FORMAT_LEFT, FromDIP( 100 ) );
70 m_stashFiles->AppendColumn(
_(
"File" ), wxLIST_FORMAT_LEFT, FromDIP( 300 ) );
71 m_stashFiles->SetToolTip(
_(
"Double click a file to see what the stash changes in it." ) );
80 [
this]( wxListEvent& aEvent )
87 [
this]( wxListEvent& )
90 &&
m_stashesList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) == -1 )
98 [
this]( wxListEvent& aEvent )
101 wxLIST_STATE_SELECTED );
112 [
this]( wxCommandEvent& )
117 [
this]( wxCommandEvent& )
122 [
this]( wxCommandEvent& )
127 [
this]( wxCommandEvent& )
136 if( !
m_dialog->SessionStillCurrent() )
141 auto stashes = std::make_shared<std::vector<KIGIT_STASH_INFO>>();
147 *stashes = aCommon.GetStashes();
151 if( !m_dialog->SessionStillCurrent() )
154 long selectedRow = m_stashesList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
155 wxString selected = stashIdForRow( selectedRow );
156 long selectRow = wxNOT_FOUND;
158 m_detailQuery.Cancel();
159 m_fillingStashes = true;
160 m_stashesList->DeleteAllItems();
163 for( const KIGIT_STASH_INFO& s : *stashes )
165 long idx = m_stashesList->InsertItem( m_stashesList->GetItemCount(), s.message );
166 m_stashesList->SetItem( idx, 1, KIGIT::RelativeDate( s.when ) );
167 m_stashesList->SetItemData( idx, static_cast<long>( s.index ) );
168 m_stashIds.push_back( s.id );
171 if( s.id == selected || ( selected.IsEmpty() && idx == 0 ) )
176 m_stashCount->SetLabel( shown == 1 ?
_(
"1 stash" ) : wxString::Format(
_(
"%d stashes" ), shown ) );
178 if( selectRow != wxNOT_FOUND )
180 m_stashesList->SetItemState( selectRow, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
198 if( aId.IsEmpty() || !
m_dialog->SessionStillCurrent() )
201 auto detail = std::make_shared<KIGIT_STASH_DETAIL>();
207 *detail = aCommon.GetStashDetail( aId );
211 if( !m_dialog->SessionStillCurrent() )
214 long selectedRow = m_stashesList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
216 if( stashIdForRow( selectedRow ) == aId )
217 fillStashDetail( *detail );
237 for(
const wxString& file : aDetail.
files )
256 if( aRow < 0 ||
static_cast<size_t>( aRow ) >=
m_stashIds.size() )
257 return wxEmptyString;
265 if( !
m_dialog->SessionStillCurrent() )
276 m_dialog->RefuseOverUncommittedWork(
279 wxString question = aRemoveAfterApply ?
_(
"Apply this stash and remove it from the list?" )
280 :
_(
"Apply this stash to the working tree?" );
282 if( !
IsOK(
this, question ) )
285 if( !
m_dialog->ConfirmWorkingTreeChange( aStatus ) )
293 if( !findStashByIdUnlocked( aCommon,
id,
index ) )
298 aRemoveAfterApply ?
_(
"Could not pop the stash. Another program may have changed the stash "
299 "list, so nothing was applied." )
300 :
_(
"Could not apply the stash. Another program may have changed the stash "
301 "list, so nothing was applied." ),
321 if( !
m_dialog->SessionStillCurrent() )
331 if( !
IsOK(
this,
_(
"Drop this stash? This cannot be undone." ) ) )
339 if( !findStashByIdUnlocked( aCommon,
id,
index ) )
344 _(
"Could not drop the stash. Another program may have changed the stash list, so nothing "
351 if( !
m_dialog->SessionStillCurrent() )
360 std::shared_ptr<KIGIT_COMMON> common =
m_frame->Prj().GetGitCommon();
361 auto preflight = std::make_shared<PREFLIGHT>();
370 [
this, common, preflight]()
372 if( !
m_dialog->SessionStillCurrent() || !common->GetRepo() )
375 if( !preflight->lfsMessage.IsEmpty() )
387 if( !
m_dialog->ConfirmWorkingTreeChange() )
400 bool hasNewFilesOnly =
false;
403 wxString projectPath =
m_frame->Prj().GetProjectPath();
405 auto outcome = std::make_shared<OUTCOME>();
411 outcome->worktree = ReadGitWorktreeStatus( aCommon, projectPath );
412 outcome->hasNewFilesOnly = !outcome->worktree.hasTrackedChanges
413 && !BuildGitChangeEntries( aCommon, projectPath, dark ).empty();
417 if( !m_dialog->SessionStillCurrent() )
420 if( !ProjectSafeToRewrite( m_frame, this, outcome->worktree, true ) )
423 if( !outcome->worktree.hasTrackedChanges )
427 if( outcome->hasNewFilesOnly )
429 DisplayInfoMessage( this, _(
"The changed files have never been committed, and a stash only "
430 "includes files that have been. Commit them from the Version "
431 "Control panel first, or discard them there." ) );
435 DisplayInfoMessage( this, _(
"There are no changes to stash." ) );
441 wxTextEntryDialog dlg(
this,
_(
"Optional description for this stash:" ),
_(
"Stash Changes" ) );
443 if( dlg.ShowModal() != wxID_OK || !
m_dialog->SessionStillCurrent() )
451 wxString
message = dlg.GetValue().Trim(
true ).Trim(
false );
456 return aCommon.StashSave( message );
458 _(
"Could not stash the changes." ),
true );
The base frame for deriving all KiCad main window classes.
The advanced Git window: a non-modal dialog with a top bar naming the repository and branch and a sid...
static wxString LfsRefusal(KIGIT_COMMON *aCommon)
Return a refusal message for LFS files or an unknown project folder, otherwise empty.
The project's git session.
bool StashPop(size_t aIndex)
std::vector< KIGIT_STASH_INFO > GetStashes() const
bool StashApply(size_t aIndex)
bool StashDrop(size_t aIndex)
PANEL_GIT_STASHES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxListCtrl * m_stashFiles
wxPanel * m_stashListPanel
wxTextCtrl * m_stashMessage
wxButton * m_stashSaveButton
wxStaticText * m_stashBranch
wxStaticText * m_stashCount
wxStaticText * m_stashCommit
wxButton * m_popStashButton
wxSplitterWindow * m_stashesSplitter
wxButton * m_dropStashButton
wxListCtrl * m_stashesList
wxButton * m_applyStashButton
wxStaticText * m_stashWhen
int m_stashSashPos
Where the user left the sash between the list and its detail pane.
void showStashDetail(const wxString &aId)
Fill the detail pane with the stash aId names, or hide it when the id is empty or gone.
void Populate()
Fill the list from the repository's stashes. The repository is read on a worker.
wxString stashIdForRow(long aRow) const
The stash shown on aRow, by its commit, or empty when the row is gone.
PANEL_GIT_STASHES(wxWindow *aParent, GIT_ADVANCED_DIALOG *aDialog, EDA_BASE_FRAME *aFrame)
KIGIT_QUERY m_listQuery
List and detail reads share the session lock without waiting on the UI thread.
KIGIT_QUERY m_detailQuery
void checkStashChanges()
After saving the editors, read the changes before asking for a stash description.
std::vector< wxString > m_stashIds
The stash commit behind each row, since a row's index is only valid for the listing it came from.
void restoreSelectedStash(bool aRemoveAfterApply)
bool m_fillingStashes
True while the list is being refilled, when its selection events are its own.
GIT_ADVANCED_DIALOG * m_dialog
KIGIT_QUERY m_actionQuery
Reads needed before an action's confirmation, separate from list refreshes.
void fillStashDetail(const KIGIT_STASH_DETAIL &aDetail)
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
Base window classes and related definitions.
void ShowGitCommitDiff(EDA_BASE_FRAME *aFrame, const wxString &aCommitHash, wxWindow *aParentWindow, const wxString &aRelativePath)
Open the diff for what a commit changed, comparing it against its parent.
bool ProjectSafeToRewrite(EDA_BASE_FRAME *aFrame, wxWindow *aParent, const GIT_WORKTREE_STATUS &aStatus, bool aAllowTrackedChanges)
Combine the repository snapshot with live editor state and explain any refusal.
GIT_IDENTITY ReadGitIdentity(KIGIT_COMMON &aCommon)
Read on a worker while holding the session's action lock.
bool EnsureGitIdentity(wxWindow *aParent, EDA_BASE_FRAME *aFrame, const std::shared_ptr< KIGIT_COMMON > &aCommon, const GIT_IDENTITY &aIdentity)
Open the same editor when the worker snapshot has no usable Git identity.
void UnsplitKeepingSash(wxSplitterWindow *aSplitter, wxWindow *aPane, int &aSashPos)
Close a splitter's second pane, keeping the sash where the user left it for next time.
wxString RelativeDate(const wxDateTime &aWhen)
"just now", "3 hours ago", or the ISO date once it is more than a month old.
void MarkDestructive(wxButton *aButton)
Paint a button's text the diff's red, for one that throws something away.
Repository state used before an operation that requires a clean working tree.
Repository values and whether Git can use them to record a commit.
wxString branch
The branch the stash was taken on, as its message records it.
std::vector< wxString > files
Paths the stash changes, new files included.
wxString message
What was stashed, without the "WIP on branch:" prefix.
wxString baseHash
Short hash of the commit the stash was taken on.